Фонарик-2...

Dec 13, 2018 23:29

Сделал еще такой светодиодный фонарик из хлама с микропроцессором...
У нас на работе, в небоскребе выдают, а потом выкидывают такие одноразовые 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();
}
}
}

#pragma, очумелые ручки, фото, #include, радиолюбительское, #define, электронная хрень

Previous post Next post
Up