Мигание светодиода в Ардуино, что может быть проще и бесполезнее. На самом деле практическую пользу от этой простой функции можно найти.
Бывает при программирование какого-нибудь устройства не хватает портов ввода-вывода микроконтроллера. Или из экономических соображений, а может нехватки места в корпусе, не хочется устанавливать дисплей, а как то сигнализировать о режимах работы устройства очень хотелось бы. Часто достаточно сигнализировать о этих режимах горением или миганием светодиода. А если режимов много?
На мысль меня навела автомобильная сигнализация, в которой я как то программировал режим автозапуска. Там, чтобы установить, например, 14-й бит определенного регистра нужно было после входа в режим программирования этого регистра 14 раз нажать на определенную кнопку брелка, а потом дождаться 14-ти коротких сигналов (или мигания поворотников). Затем нажать кнопку в подтверждения и услышать длинный сигнал. Гениально! Никаких дисплеев и экранных меню. Правда, одновременно, и жутко неудобно.
Но если внутренних режимов немного, то использовать количество морганий светодиодом вполне функционально.
Начнем с простого.
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void loop() {
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
}
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
uint32_t ms, ms1 = 0;
bool led_stat = true;
void loop() {
ms = millis();
// Событие срабатывающее каждые 500 мс
if( ( ms - ms1 ) > 500 || ms < ms1 ){
ms1 = ms;
// Инвертируем светодиод
digitalWrite(13, led_stat);
led_stat = !led_stat;
}
}
// Массив режимов работы светодиода
byte modes[] = {
0B00000000, //Светодиод выключен
0B11111111, //Горит постоянно
0B00001111, //Мигание по 0.5 сек
0B00000001, //Короткая вспышка раз в секунду
0B00000101, //Две короткие вспышки раз в секунду
0B00010101, //Три короткие вспышки раз в секунду
0B01010101 //Частые короткие вспышки (4 раза в секунду)
};
uint32_t ms, ms1 = 0, ms2 = 0;
uint8_t blink_loop = 0;
uint8_t blink_mode = 0;
uint8_t modes_count = 0;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
modes_count = 1;
blink_mode = modes[modes_count];
}
void loop() {
ms = millis();
// Событие срабатывающее каждые 125 мс
if( ( ms - ms1 ) > 125|| ms < ms1 ){
ms1 = ms;
// Режим светодиода ищем по битовой маске
if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
blink_loop++;
}
// Этот код служит для демонстрации переключения режимов
// Один раз в 5 секунд меняем эффект
if( ( ms - ms2 ) > 5000|| ms < ms2 ){
ms2 = ms;
blink_mode = modes[modes_count++];
if( modes_count >= 7 )modes_count = 1;
}
}
byte bytes[] = {0B00010101,0B00110011,0B10100011,0B00000010};
uint32_t ms, ms1 = 0;
uint8_t blink_loop = 0;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void loop() {
ms = millis();
// Событие срабатывающее каждые 125 мс
if( ( ms - ms1 ) > 125|| ms < ms1 ){
ms1 = ms;
// Выделяем сдвиг светодиода (3 бита)
uint8_t n_shift = blink_loop&0x07;
// Выделяем номер байта в массиве (2 байта со здвигом 3 )
uint8_t b_count = (blink_loop>>3)&0x3;
if( bytes[b_count] & 1<< n_shift )digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
blink_loop++;
}
}
uint8_t blink_loop = 0;
uint8_t blink_mode = 0;
uint8_t modes_count = 0;
// Начальное значение таймера
uint16_t n = 63583;
// Обработчик прерывания по переполнению таймера
ISR( TIMER1_OVF_vect )
{
if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
blink_loop++;
TCNT1 = n; //выставляем начальное значение TCNT1
}
void setup() {
pinMode(13,OUTPUT);
blink_mode = 0B00000000;
// А вот и хардкор - установка регистров таймера
TCCR1A = 0;
// Устанавливаем делитель 1024 к тактовой частоте 16МГц
TCCR1B = 1<<CS22 | 0<<CS21 | 1<<CS20;
//Подключаем прерывание по переполнению Timer1
TIMSK1 = 1<<TOIE1;
//Загружаем начальное значение таймера для первого цикла
TCNT1 = n;
sei(); // выставляем бит общего разрешения прерываний}
}
void loop() {
blink_mode = 0B00001111; //Мигание по 0.5 сек
delay(5000);
blink_mode = 0B00000001; //Короткая вспышка раз в секунду
delay(5000);
blink_mode = 0B00000101; //Две короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B00010101; //Три короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B01010101; //Частые короткие вспышки (4 раза в секунду)
delay(5000);
}
#include "TimerOne.h"
uint8_t blink_loop = 0;
uint8_t blink_mode = 0;
uint8_t modes_count = 0;
// Callback функция по таймеру
void timerIsr()
{
if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
blink_loop++;
}
void setup() {
pinMode(13,OUTPUT);
blink_mode = 0B00000000;
Timer1.initialize(125000);
Timer1.attachInterrupt( timerIsr );
}
void loop() {
blink_mode = 0B00001111; //Мигание по 0.5 сек
delay(5000);
blink_mode = 0B00000001; //Короткая вспышка раз в секунду
delay(5000);
blink_mode = 0B00000101; //Две короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B00010101; //Три короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B01010101; //Частые короткие вспышки (4 раза в секунду)
delay(5000);
}
#include <Ticker.h>
uint8_t blink_loop = 0;
uint8_t blink_mode = 0;
uint8_t modes_count = 0;
Ticker blinker;
void timerIsr()
{
if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
blink_loop++;
}
void setup() {
pinMode(13,OUTPUT);
blink_mode = 0B00000000;
blinker.attach(0.125, timerIsr);
}
void loop() {
blink_mode = 0B00001111; //Мигание по 0.5 сек
delay(5000);
blink_mode = 0B00000001; //Короткая вспышка раз в секунду
delay(5000);
blink_mode = 0B00000101; //Две короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B00010101; //Три короткие вспышки раз в секунду
delay(5000);
blink_mode = 0B01010101; //Частые короткие вспышки (4 раза в секунду)
delay(5000);
}
К сожалению, не доступен сервер mySQL