Здравствуйте!
Моя версия фонарика с микроконтроллерным управлением.
При подаче питания микроконтроллер на пине PB0 ШИМ сигнал малой скважности (OCR0A=10), при однократном нажатии на тактовую кнопку ШИМ увеличивается до среднего значения (OCR0A=128), при втором нажатии до максимального значения (OCR0A=255). Третье нажатие на кнопку переводит фонарик в режим стробоскопа. Четвёртое нажатие позволяет эмитировать фонариком подачу сигнала SOS (три коротких, три длинных, три коротких вспышки). Последующее нажатие на кнопку переводит фонарик в первый режим (малая яркость), и так по кругу. Длительное удержание кнопки (4 секунды) переводит фонарик в спящий режим, при этом потребление тока практически отсутствует. Пробуждение производится однократным нажатием, при этом включается тот режим, который был в момент засыпания.
С выхода PB0 сигнал поступает на транзисторный ключ (2n2222), который коммутирует светодиод D2 (1Вт), через резистор R4 (10 Ом, 2 Вт). При таком номинале резистора светодиод работает не на полную мощность, зато не греется, но вообще сопротивление можно смело уменьшить до 8 Ом.
Светодиод использовал такой:
Для контроля уровня питания использовал аналоговый компаратор tiny13 (третья нога), на который через потенциометр подаётся напряжение с аккумулятора. При снижении напряжения ниже заданного порога загорается светодиод D1. При настройке потенциометр следует выставить таким образом, чтобы светодиод D1 загорался при выбранном вами пороге, для этого нужно использовать лабораторный источник питания, при отсутствии его, можно использовать ещё один потенциометр с мультиметром.
Прошивка написана в AtmelStudio 6.2, исходный код прилагаю:
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> /*библиотека прерываний*/
volatile unsigned char z=0;
volatile unsigned int button_count;// счетчик кнопки
volatile uint8_t button_clk; // флаг клика
volatile unsigned int main_tmr; //таймер для стробоскопа
unsigned char r=0; // SOS
// Пробуждение. Устанавливаем вектор прерывания INT0
ISR (INT0_vect)
{
//пробуждение
main_tmr = 0;
r=0;
}
// обработчик прерывания по переполнению таймера 0
ISR(TIM0_OVF_vect){
if (PINB&(1<<PB1)) // если на ПИНе 1
{
if (button_count>=321 && button_count<14000) button_clk=1; //если в рамках поднять флаг короткого клика 1
button_count=0;// обнулить счетчик
}
else // ИНАЧЕ на ПИНе 0
{
if (button_count<14001) button_count++; // инкермент счетчика с ограничением 14000 - 3 sec
if (button_count==14000) button_clk=101;// если в счетчике 14000 поднять флаг длинного клика
}
main_tmr++;
}
int main(void)
{
DDRB = 0b00010001; // PB0 ака OC0A и PB1 ака OC0B на выход
PORTB = 0b00000010;
ADCSRB|=(1<<ACME); // подключить инверсный вход AIN1 компаратора к мультиплексору. при этом ADEN в ADCSRA должен быть 0.
// т.е. биты MUX0-1 (регистра ADMUX) подключат вход к ADC0-3
ADMUX|=(1<<MUX0) | (0<<MUX1);// инверсный вход к АДС1
ACSR|=(1<<ACBG);// подключить опорное 1.1(для тини13) на неинверсный вход, если 0 подключен к AIN0
TCCR0B |= (1<<CS00); // без делителя
TIMSK0 |=(1<<TOIE0); // разрешить прерывание по переполнению таймера 0
MCUCR|=(1<<SE);// разрешить сон
MCUCR|=(1<<SM1);// выбор режима сна - power down
asm("sei");
// Режим Fast PWM
TCCR0A |=(1<<WGM00) | (1<<WGM01); // Режим Fast PWM, таймер считает до 255 и сбрасывается в 0
TCCR0A |=(1<<COM0A1) | (0<<COM0A0); // 0 при равенстве регистров TCNT0 и OCROA. 1 при переполнении (инвертированный ШИМ-сигнал) Включение канала А
OCR0A = 100; // регистр сравнения
while(1)
{
if (button_clk==1) // проверка флажка клика
{
z++; // отработка клика
button_clk=0;// сбросить флаг клика в 0
}
if (z==5) z=0;
if (button_clk==101) // проверка флажка клика
{
GIMSK |= (1<<INT0); // разрешаем работать прерыванию
ACSR|=(1<<ACD); // 1 выключает компаратор.
TCCR0A &= ~(1<<7); //COM0A1 в нуль, чтобы отключить выход шим
PORTB = 0b00000010;
DDRB|= 0b00000000;// пин светодиода на выход
_delay_ms(1000);
asm("sleep"); // уход в сон
_delay_ms(500);
GIMSK &= ~(1<<INT0); // запрешаем работать прерыванию
DDRB = 0b00010001; // PB0 ака OC0A и PB1 ака OC0B на выход
TCCR0A |=(1<<COM0A1); // востанавливаем работу шим
ACSR &= ~ (1<<ACD); // 1 включает компаратор.
button_clk=0; // сбросить флаг клика в 0
}
if (z==0) //10
{
TCCR0A |=(1<<COM0A1); // востанавливаем работу шим после стробоскопа
OCR0A=10;
}
if (z==1) //50
{
OCR0A=128;
}
if (z==2) //100
{
OCR0A=255;
}
if (z==3) //STROBOSKOP
{
TCCR0A &= ~(1<<7); //COM0A1 в нуль, чтобы отключить выход шим
if (main_tmr >=169)
{
PORTB^=(1<<PB0);
main_tmr = 0;
}
}
if (z==4) //SOS
{
TCCR0A &= ~(1<<7); //COM0A1 в нуль, чтобы отключить выход шим
if (main_tmr >=938)
{
r++;
main_tmr = 0;
}
if (r>29) r=0;
if (r ==0) PORTB &= ~(1 << PB0);
if (r ==1) PORTB |= (1 << PB0);
if (r ==2) PORTB &= ~(1 << PB0);
if (r ==3) PORTB |= (1 << PB0);
if (r ==4) PORTB &= ~(1 << PB0);
if (r ==5) PORTB |= (1 << PB0);
if (r ==6) PORTB &= ~(1 << PB0);
if (r ==7) PORTB |= (1 << PB0);
if (r ==8) PORTB |= (1 << PB0);
if (r ==9) PORTB |= (1 << PB0);
if (r ==10) PORTB &= ~(1 << PB0);
if (r ==11) PORTB |= (1 << PB0);
if (r ==12) PORTB |= (1 << PB0);
if (r ==13) PORTB |= (1 << PB0);
if (r ==14) PORTB &= ~(1 << PB0);
if (r ==15) PORTB |= (1 << PB0);
if (r ==16) PORTB |= (1 << PB0);
if (r ==17) PORTB |= (1 << PB0);
if (r ==18) PORTB &= ~(1 << PB0);
if (r ==19) PORTB |= (1 << PB0);
if (r ==20) PORTB &= ~(1 << PB0);
if (r ==21) PORTB |= (1 << PB0);
if (r ==22) PORTB &= ~(1 << PB0);
if (r ==23) PORTB |= (1 << PB0);
if (r ==24) PORTB &= ~(1 << PB0);
if (r ==25) PORTB &= ~(1 << PB0);
if (r ==26) PORTB &= ~(1 << PB0);
if (r ==27) PORTB &= ~(1 << PB0);
if (r ==28) PORTB &= ~(1 << PB0);
if (r ==29) PORTB &= ~(1 << PB0);
}
if(ACSR&(1<<ACO)) // проверяем бит ACO - выход компаратора.
{
PORTB|=(1<<PB4);
}
else
{
PORTB&=~(1<<PB4);
}
}
}
Для питания использовал литий-ионный аккумулятор 18650, DC/DC преобразователь выставленный на 5В, плату заряда и защиты аккумулятора с разъёмом microUSB. Тумблер или кнопка с фиксацией нужны, чтобы отключать питание при длительном хранение или транспортировке.
Смонтировал всё это в прямоугольном китайском корпусе, но можно использовать корпус от старого неисправного фонарика подходящего размера.
Спасибо за внимание! Подписывайтесь на канал, ставьте лайки, если понравилось!