Гирлянда на arduino и светодиодах

Напишем и сделаем гирлянду на arduino.





..И  немного неродного кода для arduino —  Си AVR.

Все светодиоды будут подключены параллельно для упрощения кода, схемы и быстрой сборки.

Будет 6 режимов(в скобках значение переменной mode, что значит режим, с англ.).

(0)1-ый режим: Яркость светодиода изменяется от 0% до 100%, затем  от 100% до 0%.

(1)2-ой режим:Яркость led-светодиода от 0% до 100%, от 100% до 0%, быстрее в 9 раз.

(2)3 — ий режим:Простое мигание светодиода раз в секунду.

(3)4 — ый режим:Мерцание.

(4)5-ый режим: Яркость «в пол накала»,мерцание,  яркость изменяется от 0% до 100%, затем яркость становится 0%.

(5)6-ой режим:Яркость 0-50%, затем 100%(подмигивание), яркость 100-50%, затем 0%.

Видео режимов второй версии(ускорено в 2 раза):

Схема:

Транзистор T1 — Любой MOSFET с N-каналом, нужен для того, чтобы повесить на него нагрузку, а не на ножку микроконтроллера, у который максимально-допустимый ток нагрузки — 20 мА.

Резистор R1 как раз и нужен для ограничения тока от вывода микроконтроллера на затвор G транзистора.

R2 — Для избегания не полного закрытия транзистора, во время отсутствия сигнала на затворе.

R3 — Для низкого уровня(0 вольт) на выводе, для избегания наводок и случайных срабатываний кнопки

R4 — Подбирается индивидуально, в зависимости от того сколько светодиодов подключено(LED String).

Для одного светодиода это 150 Ом, так как 5 вольт -2 вольта= 3 вольт /0,02 А=150 Ом,

для двух это — 3/0,04 =75 Ом — светодиода будет два и потребление уже будет 0,04 А, а не 0,02 А,

для трех — 3/0,06=50 Ом и так далее.
Количество светодиодов может быть любым, главное, чтобы ток нагрузки не превышал допустимый ток нагрузки транзистора и параметры светодиодов были примерно одинаковыми, например для синего светодиода требуется больше тока, чем для других цветов.Если требуется подключить светодиоды с другими параметрами, то у них должен быть свой резистор, т.е. своя независимая цепь питания.

Push — обычная push-кнопка, которая не фиксируется, при ее нажатии на вывод 11 микроконтроллера поступает высокий уровень сигнала(+5 вольт), что значит, что кнопка была нажата

Все резисторы можно брать чуть бОльшего номинала, но не меньшего.

 

Обновление кода v2(Код и скетч для ардуино ниже):

Убрана кнопка, в следствии значит убран неродной код для ардуино и прерывание, теперь можно исключить кнопку Push и резистор R3.Переключение режима осуществляется выключением/включением/кнопкой reset на плате — значение режима считывается из памяти EEPROM, если режим равен максимальному значению, то записать в EEPROM значение 0(1-ый режим), иначе записать в EEPROM значение режим+1, после чего при следующем включении режим, считанный из EEPROM будет иметь другое значение.Добавлены дополнительные режимы — всего их стало 12.Определена константа #define pinLed значение — где просто надо изменить цифру ножки мк в одном месте, вместо того, чтобы изменять все встречающиеся значения в коде по одному.

Код v1 для Arduino Pro Mini 5V 16 MHz:

 

 
uint8_t mode=0; //Режим свечения гирлянды
uint16_t counter; //счетчик 16-битный(до 65535)
uint8_t val=0; //счетчик 8-битный (до 255)
bool reverse=false; //флаг реверса
uint8_t cc=0; //счетчик для кнопки
 
 
//Настраиваем изначальные параметры
void setup(){
  pinMode(10, OUTPUT);//Ножку 10 назначить выходом
  //обратите внимание, что этот вывод должен поддерживать
  //ШИМ(PWM)
  pinMode(11,INPUT);//Ножку 11 назначить входом, будет кнопкой
 
//!Не arduino-код
//Управление прерываниями - установка бита TOIE1 в 
//регистре TIMSK1 разрешает прерывание по переполнению
   TIMSK1 = (1 << TOIE1);
 
   //Устанавливаем второй таймер, так как первый таймер уже занят ардуино
   //таймер 16-ти битный
   //нужен, чтобы поймать нажатие кнопки
   //Здесь выбираем предделитель(предделитель отсутствет)
   //и режим тактирования(тактовый генератор - CLK, частота процессора)
   //и запускаем таймер
   //как только произойдет переполнение вызовется прерывание ISR(TIMER1_OVF_vect)
   TCCR1B |= (0 << CS12)|(0 << CS11)|(1 << CS10);
  }
 
 
//функция прерывания
//происходит всегда в независимости от установки delay и т.д.
//так как таймер 16 битный, а частота процессора 16 000 000 Герц, то
//16 000 000 / 65535=244 раза эта функция вызовется за секунду
ISR(TIMER1_OVF_vect)
{
 
  //считать значение вывода 11(кнопки)
   int reading = digitalRead(11);    
 
//если кнопка нажата
if(reading==HIGH){
 
//прибавить к счетчику+1
cc++;
 
//если счетчик больше 48
//почему 48?
//так как эта функция у нас вызывается 244 раза в секунду
//то за 1 миллисекунду счетчик прибавится на 244/1000 миллисекунд = на 0,244
//0,244*200 миллисекунд = 48.8, где 200 миллисекунд пройдет, пока cc достигнет 
//значения 48
//нужно для устранения дребезга контактов кнопок и ложных срабатываний
  if(cc>48)  {
 
  //сбросить счетчик, так как кнопка была удержана 200 миллисекунд
    cc=0;
 
    //сбросить счетчик val, так как будет включен другой режим
    //чтобы другой режим не перенял значение от предыдущего
  val=0; 
 
//циклический выбор режима
//режим = режим+1
//если режим стал больше 5, то режим становится 0
  if(mode<5){ mode++;}  
  else{
    mode=0;}
  }
 
}//reading==HIGH
 
 
  }//isr
 
 
 
 
//искуственное прерывание
void fake_interrupt(){
 
//Контакт 10 - выход +5 вольт
digitalWrite(10,HIGH);
//Ждать val миллисекунд
delayMicroseconds(val);
//Контакт 10 - выход 0 вольт
digitalWrite(10,LOW);
//Ждать val миллисекунд
delayMicroseconds(val);
 
//сброс счетчика
counter=0;
}
 
 
 
//циклический код
  void loop(){
 
 
//конструкция switch
//код выполняется в зависимости от значения переменной mode
//значение указывается после слова case:
//case Значение_Переменной_mode:Код, который выполнится, если 
//mode = Значение_Переменной_mode ;break; и т.д.
//переменная mode может иметь 6 значений(от 0 до 5)
switch(mode){
 
//Режим 1
case 0:
//Если флаг reverse не установлен, то повышать яркость светодиода
if(!reverse){
  //Выход ШИМ, микроконтроллер устанавливает напряжение на ввыводе
  //в зависимости от значения
  //для 255 - это 5 вольт, для 0 - 0 вольт, для 127 = 2,5 вольт
  //здесь значение устанавливается из переменной val
analogWrite(10,val);
delay(9);
val++;
//Если значение достигло максимума, установить флаг reverse
if(val==255){reverse=true;}
}
 
//Если флаг reverse установлен, то понижать яркость до 0
if(reverse){
  val--;
  if(val==0){reverse=false;return;}
  analogWrite(10,val);
  delay(9);
  }
;break;
 
 
//Режим 2
//То же самое, что и в первом режиме, только быстрее в 9 раз
case 1:
if(!reverse){
analogWrite(10,val);
delay(1);
val++;
if(val==255){reverse=true;}
}
 
 
if(reverse){
  val--;
  if(val==0){reverse=false;return;}
  analogWrite(10,val);
  delay(1);
  }
 
;break;
 
//Режим 3
//Простое моргание светодиода ~раз в секунду
case 2:
digitalWrite(10,HIGH);
delay(500);
digitalWrite(10,LOW);
delay(500);  
 
;break;
 
//Режим 4
//Мерцание светодиода в следствии более быстрого переключения
case 3:
  digitalWrite(10,HIGH);
  delay(20);
  digitalWrite(10,LOW);
  delay(20);
;break;
 
 
//Режим 5
case 4:
//счетчик
counter++;
//каждые 512 тиков вызывать искуственное прерывание, где быстро переключать светодиод
//затем ждать 33 мс, за счет чего осуществляется свечение в "пол накала",прибавить к 
//val+1, пауза включения\выключения светодиода в "прерывании", устанавливается из val, за 
//счет чего увеличивается яркость
 if(counter>=512){fake_interrupt();delay(33);val++;}
 
 
;break;
 
//Режим 6
case 5:
//Выполнять код в цикле for до тех пор, пока i не достигнет 127
//прибавлять к i+1 каждую итерацию
for(int i=0;i<127;i++){
analogWrite(10,i);
delay(10);
}
 
//Ждать 50 мс
delay(50);
//Резко повысить значение с 127(50%) до 255(100%), за
//счет чего светодиод моргнет
analogWrite(10,255);
//Ждать 50 мсек
delay(50);
 
//Аналогичные, обратные, реверсивные действия по уменьшению яркости и 
//резкому спаду яркости до 0%.
for(int i=127;i>0;i--){
analogWrite(10,i);
delay(10);
}
 
delay(50);
analogWrite(10,0);
delay(50);
 
 
;break;
 
 
  }//switch
 
 
 }//loop

 

Код v2 для Arduino Pro Mini 5V 16 MHz:

 
#include <EEPROM.h>
uint8_t mode=0; //Режим свечения гирлянды
uint16_t counter; //счетчик 16-битный(до 65535)
uint8_t val=0; //счетчик 8-битный (до 255)
bool reverse=false; //флаг реверса
uint8_t cc=0; //счетчик для кнопки
int addr = 0; //адрес в еепром
#define pinLed 10 
 
 
//Настраиваем изначальные параметры
void setup(){
 
 
  pinMode(pinLed, OUTPUT);//Ножку 10 назначить выходом
  //обратите внимание, что этот вывод должен поддерживать
  //ШИМ(PWM)
 
 
//считать в переменную mode значение из EEPROM поадресу 0
mode = EEPROM.read(0);
 
//Если режим равен максимальному значению, то записать в EEPROM значение 0 по адресу addr 
if(mode==11){EEPROM.write(addr, 0);}
//Иначе записатьь значение mode+1
else{
EEPROM.write(addr, mode+1);
}
 
 
  }
 
 
 
 
 
 
//искуственное прерывание
void fake_interrupt(){
 
//Контакт 10 - выход +5 вольт
digitalWrite(pinLed,HIGH);
//Ждать val миллисекунд
delayMicroseconds(val);
//Контакт 10 - выход 0 вольт
digitalWrite(pinLed,LOW);
//Ждать val миллисекунд
delayMicroseconds(val);
 
//сброс счетчика
counter=0;
}
 
 
 
 
 
 
 
//циклический код
  void loop(){
 
 
//конструкция switch
//код выполняется в зависимости от значения переменной mode
//значение указывается после слова case:
//case Значение_Переменной_mode:Код, который выполнится, если 
//mode = Значение_Переменной_mode ;break; и т.д.
//переменная mode может иметь 6 значений(от 0 до 5)
switch(mode){
 
//Режим 1
case 0:
//Если флаг reverse не установлен, то повышать яркость светодиода
if(!reverse){
  //Выход ШИМ, микроконтроллер устанавливает напряжение на ввыводе
  //в зависимости от значения
  //для 255 - это 5 вольт, для 0 - 0 вольт, для 127 = 2,5 вольт
  //здесь значение устанавливается из переменной val
analogWrite(pinLed,val);
delay(9);
val++;
//Если значение достигло максимума, установить флаг reverse
if(val==255){reverse=true;}
}
 
//Если флаг reverse установлен, то понижать яркость до 0
if(reverse){
  val--;
  if(val==0){reverse=false;return;}
  analogWrite(pinLed,val);
  delay(9);
  }
;break;
 
 
//Режим 2
//То же самое, что и в первом режиме, только быстрее в 9 раз
case 1:
if(!reverse){
analogWrite(pinLed,val);
delay(1);
val++;
if(val==255){reverse=true;}
}
 
 
if(reverse){
  val--;
  if(val==0){reverse=false;return;}
  analogWrite(pinLed,val);
  delay(1);
  }
 
;break;
 
//Режим 3
//Простое моргание светодиода ~раз в секунду
case 2:
digitalWrite(pinLed,HIGH);
delay(500);
digitalWrite(pinLed,LOW);
delay(500);  
 
;break;
 
//Режим 4
//Мерцание светодиода в следствии более быстрого переключения
case 3:
  digitalWrite(pinLed,HIGH);
  delay(20);
  digitalWrite(pinLed,LOW);
  delay(20);
;break;
 
 
//Режим 5
case 4:
//счетчик
counter++;
//каждые 512 тиков вызывать искуственное прерывание, где быстро переключать светодиод
//затем ждать 33 мс, за счет чего осуществляется свечение в "пол накала",прибавить к 
//val+1, пауза включения\выключения светодиода в "прерывании", устанавливается из val, за 
//счет чего увеличивается яркость
 if(counter>=512){fake_interrupt();delay(33);val++;}
 
 
;break;
 
//Режим 6
case 5:
//Выполнять код в цикле for до тех пор, пока i не достигнет 127
//прибавлять к i+1 каждую итерацию
for(int i=0;i<127;i++){
analogWrite(pinLed,i);
delay(10);
}
 
//Ждать 50 мс
delay(50);
//Резко повысить значение с 127(50%) до 255(100%), за
//счет чего светодиод моргнет
analogWrite(pinLed,255);
//Ждать 50 мсек
delay(50);
 
//Аналогичные, обратные, реверсивные действия по уменьшению яркости и 
//резкому спаду яркости до 0%.
for(int i=127;i>0;i--){
analogWrite(pinLed,i);
delay(10);
}
 
delay(50);
analogWrite(pinLed,0);
delay(50);
 
 
;break;
 
//Быстрое мигание
 case 6:
  digitalWrite(pinLed,HIGH);
  delay(55);
  digitalWrite(pinLed,LOW);
  delay(55);
;break;
 
 
//Ступенька
case 7:
analogWrite(pinLed,0);
delay(200);
 
analogWrite(pinLed,255);
delay(200);
analogWrite(pinLed,127);
delay(200);
analogWrite(pinLed,127);
delay(200);
 
 
analogWrite(pinLed,255);
delay(200);
analogWrite(pinLed,127);
delay(200);
analogWrite(pinLed,63);
delay(200);
 
break;
 
 
//Биение сердца
case 8:
 
analogWrite(pinLed,63);
delay(200);
analogWrite(pinLed,127);
delay(200);
 
analogWrite(pinLed,50);
delay(400);
 
analogWrite(pinLed,63);
delay(200);
analogWrite(pinLed,127);
delay(200);
 
break;
 
//Лампа с плохим контактом
case 9:
 
for(int i=0;i<94;i++){
 
analogWrite(pinLed,i);
delay(20);
}
 
analogWrite(pinLed,0);
delay(999);
break;
 
//Среднее переливание/волна
case 10:
 
for(int i=32;i<190;i++){
analogWrite(pinLed,i);
delay(15);
}
 
 
 
for(int i=190;i>32;i--){
analogWrite(pinLed,i);
delay(15);
}
 
 
break;
 
//Светодиод светится 7 секунд, 7 секунд не светится
case 11:
 
analogWrite(pinLed,255);
delay(7000);
 
analogWrite(pinLed,0);
delay(7000);
 
break;
 
  }//switch
 
 
 }//loop
 

Скетч v2:

led_festoon_arduino_sketch_v20

Насколько полезной была эта запись?

Нажмите на звезду для оценки!

Средний рейтинг / 5. Количество оценок:

Мы сожалеем, что эта запись вас не устроила.

Сохранить в:

Оставить комментарий

avatar
  Подписаться  
Уведомление о