Сделал еще такой светодиодный фонарик из хлама с микропроцессором...
У нас на работе, в небоскребе выдают, а потом выкидывают такие одноразовые emergency фонарики.
Я переделал, на крутой манер: с микроконтроллером, DC-DC преобразователями для светодиода
и зарядки аккумулятора от USB. А питается от одного Ni-MH элемента (чуть побольше AA).
Причем микроконтроллер подкачивает все время для себя необходимые 2-3V из батареечных 1.2V.
Светодиод (LED 1W) светится чуть-чуть и фонарик всегда можно найти в темноте.
Процессор просыпается от Watch Dog Timer-а, следит за напряжениями, переключателем и засыпает.
Переключателем можно выбрать яркий и экономный режим. Мне было интересно это попрограммировать.
Для любителей языка Си, под катом программа, между прочим 300 строк! :) Enjoy! :)
/*
* File: FlashLight2.c
* Author:
*
* Created on December 8, 2018, 8:06 AM
*/
// PIC12F510 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config OSC = IntRC // Oscillator Select (INTOSC with 1.125 ms DRT)
#pragma config WDT = ON // Watchdog Timer Enable bit (WDT enabled)
#pragma config CP = OFF // Code Protect (Code protection off)
#pragma config MCLRE = OFF // Master Clear Enable bit (GP3/MCLR pin functions as GP3, MCLR internally tied to VDD)
#pragma config IOSCFS = OFF // Internal Oscillator Frequency Select bit (4 MHz INTOSC Speed)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include xc.h
typedef unsigned char byte;
#define INIT_GPIO 0b010000
#define INIT_TRIS 0b001101
#define INIT_CM1CON0 0b11110001
#define PIN_LED GPIObits.GP1
#define PIN_SWITCH GPIObits.GP3
#define PIN_FLASH GPIObits.GP5
#define PIN_CHARGE GPIObits.GP4
#define BIT_BAT 0b100
#define ADC_OFF 0b00111100
#define ADC_VREF 0b00111111
#define ADC_BAT 0b01111011
#define ADC_SET(set) ADCON0 = set;
#define ADC_WAIT while(ADCON0 & 2u);
static bit bit_wake, bit_power, bit_switch, bit_beam, bit_charge, bit_charge_fast;
static volatile byte timer1, timer2;
//--------------------------------------------------------------------------
inline void InitMCU()
{
OPTION = 0b11000111;
TRIS = INIT_TRIS;
GPIO = INIT_GPIO;
ADC_SET(ADC_VREF)
bit_beam = CM1CON0 & 1;
CM1CON0 = INIT_CM1CON0;
}
static void ADC(byte adc)
{
byte t = 10;
while (--t)
{
ADC_SET(adc);
ADC_WAIT
}
}
inline void FlashPump()
{
byte t = 3;
CLRWDT();
while (--t)
{
PIN_FLASH = 1;
NOP();
if (bit_beam)
{
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
}
PIN_FLASH = 0;
NOP();
}
}//void FlashPump()
inline void FlashIdle()
{
byte t = 3u;
while (--t)
{
PIN_FLASH = 1;
NOP();
PIN_FLASH = 0;
}
}
#define TIMER_SEC(sec) sec << 4
// OSC 4 MHz
inline void UpdateTimer()
{
static byte timer;
byte t = TMR0;
if (t < timer)
{
if (timer1)
--timer1;
if (timer2)
--timer2;
}
timer = t;
}
inline void CheckPower()
{
if (ADRES < 39u) // V > 4.1V
{
ADC_SET(ADC_VREF)
bit_power = 1;
}
else
{
ADC_SET(ADC_VREF)
if (bit_power)
{
PIN_LED = 0;
bit_power = 0;
}
}
}
inline void CheckBattery()
{
if (timer1 == 0)
{
if (bit_charge)
{
timer2 = 7;
bit_charge = 0;
return;
}
if (timer2)
return;
ADC(ADC_VREF);
byte vref = ADRES;
ADC(ADC_BAT);
byte t = vref << 1;
if (ADRES >= t + (vref >> 1)) // 1.5V
bit_charge = 0;
else
{
if (ADRES < (t - (vref >> 2))) // 1.05V
bit_charge_fast = 0;
else
bit_charge_fast = 1;
bit_charge = 1;
}
ADC(ADC_VREF);
PIN_LED = 1;
timer1 = 255u;
}
if (!bit_charge)
return;
if (timer2 == 0)
{
PIN_LED = !PIN_LED;
timer2 = 7u;
}
// bit_charge_fast = 0;
byte t = 3;
CLRWDT();
while (--t)
{
PIN_CHARGE = 0;
if (bit_charge_fast)
{
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
}
PIN_CHARGE = 1;
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
}
}
inline void Sleep()
{
ADC_SET(ADC_OFF)
if (bit_beam)
CM1CON0 = INIT_CM1CON0 | 1u;
else
CM1CON0 = INIT_CM1CON0 & 0b11111110u;
SLEEP();
}
#define SWITCH_BEAM_COUNTER 120u
inline void CheckSwitch()
{
if (PIN_SWITCH)
{
if (bit_switch)
{
bit_switch = 0;
TMR0 = 0;
}
else
if (++TMR0 > SWITCH_BEAM_COUNTER)
TMR0 = SWITCH_BEAM_COUNTER;
}
else
{
if (bit_switch == 0)
{
if (TMR0 < SWITCH_BEAM_COUNTER)
bit_beam = !bit_beam;
bit_switch = 1;
}
}
}
//================================== MAIN ======================================
void main(void)
{
InitMCU();
FlashIdle();
for(;;)
{
UpdateTimer();
CheckPower();
CLRWDT();
if (bit_power)
{
CheckBattery();
continue;
}
CheckSwitch();
if (bit_switch)
FlashPump();
else
Sleep();
}
}
}