Chevroletavtoliga - Автомобильный портал

Arduino примеры скетчей бегущие огни с плавным. Бегущие поворотники на ленте WS2812 и Arduino. Задания для самостоятельного решения

Ардуино начинающим

В этом уроке мы продолжим работу со светодиодами, но количество светодиодов увеличим до 5. И сделаем эффект бегущего огня . Для управления светодиодами будем использовать манипуляции с портами Arduino. Мы будем напрямую записывать данные в порты Arduino. Это лучше, чем работать с конкретными входами/выходами контроллера. Это позволит установить значения для светодиодов при помощи одной лишь операции.

У Arduino UNO имеется 3 порта:

  • B (цифровые входа/выхода с 8 по 13)
  • C (аналоговые входа)
  • D (цифровые входа/выхода с 0 по 7)

Каждый порт управляется 3 регистрами. Регистр DDR определяет чем будет являться нога (pin) входом или выходом. При помощи регистра PORT можно установить pin в состояние HIGH или LOW. При помощи регистра PIN можно считать состояние ножек Arduino, когда они работает на вход.

Мы будем использовать порт B. Сначала, мы должны установить все ножки порта B как цифровые выхода. У порта B имеется только 6 ножек. Биты регистра для В-порта DDRB должны быть установлены в 1, если нога будет использоваться как выход (OUTPUT), и в 0, если нога будет использовать как вход (INPUT). Биты портов нумеруются с 0 по 7, но не всегда содержат все 8 ног.

Пример:

DDRB = B00111110; // установить ножки порта В с 1 по 5 как выхода, а 0 как вход.

Обратите внимание, что в микроконтроллерах фирмы Microchip все наоборот. 0 бит - нога работает как выход, а 1 - как вход.

В нашем проекте бегущего огня мы будем использовать 5 выходов:

DDRB = B00011111; // установить ноги порта В с 0 по 4 как выхода

Для записи значений в порт В необходимо использовать регистр PORTB. Зажечь первый светодиод можно командой:

PORTB = B00000001;
первый и четвертый:
PORTB = B00001001;

Теперь вы видите, как легко мы можем включать и выключать светодиоды. Теперь расскажем вам об операторах сдвига

Есть 2 оператора двоичного сдвига: оператор сдвига влево << и оператор сдвига вправо >>. Оператор сдвига влево << заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> сдвигает биты вправо.

Пример:

varA = 1; // 00000001
varA = 1 << 0; // 00000001
varA = 1 << 1; // 00000010
varA = 1 << 2; // 00000100

Теперь вернемся к нашей программе, которая показана ниже. Нам нужно ввести 2 переменные: первая upDown будет содержать значение куда двигаться - вверх или вниз, а вторая cylon какие светодиоды зажигать.

В функции setup() мы определяем какие ножки должны работать как выхода.

В главном цикле программы loop() , светодиоды по очереди загораются вверх путем увеличения переменной cylon , а когда доходит до самого верхнего, то переменной upDown присваивается 0 и светодиоды загораются вниз по очереди.

Код: /* Бегущий огонь. 5 светодиодов */ unsigned char upDown=1; // начинаем с движения вверх unsigned char cylon=0; // определяет очередность LED void setup() { DDRB = B00011111; // устанавливаем порт B с 0 по 4 как выхода } void loop() { if(upDown==1){ // если идем вверх, то cylon++; if(cylon>=4) upDown=0; // когда достигнут наибольший номер LED, то в след. цикле идем вниз } else { cylon--; if(cylon==0) upDown=1; // когда достигнут наименьший номер LED, то в след. цикле идем вверх } PORTB = 1 << cylon; //сдвиг delay(200); // пауза 200 мс

Давайте еще ​​немного поморгаем светодиодами. Давайте создадим с Вашей Arduino линейку светодиодов, моргающих слева направо и справа налево, и используя не один, а восемь штук. Заставим моргать светодиоды в бесконечном цикле последовательности 1-2-3-4-5-6-7-8-7-6-5-4-3-2-1-2-3 - ... с задержкой в ​​одну секунду.
Вам понадобится:

  • Ваши стандартные настройки Arduino (компьютер, кабель, Uno или совместимый)
  • 8 светоизлучающих диодов.
  • 8 резисторов 360 Ом 0,25 Вт. Резисторы необходимы для ограничения тока светодиодов.
  • Макетная плата и соединительного провода
Предлагаю сделать задержку переменной. Так что вы могли легко изменить её .
В исходном проекте «мигающий светодиод», описанный в книге Массимо Банци, использовался цифровой вывод 13. На этот раз, вы можете использовать цифровые контакты со 2 до 9. Аппаратная сторона проста - подключите провод от каждого цифрового контакта к аноду светодиода, затем подключите соединительным проводом резистор 360 Ом резистор и далее катод светодиода на землю. См. схему ниже:

Теперь ваша задача - написать код! Но прежде чем сделать это, надо написать план работы или алгоритм. Например, для этого упражнения вы могли бы написать что-то вроде...

0.1 алгоритм работы программы.
Устанавливаем, что все контакты мы будем использовать как выходы Создаем переменную для хранения длительность задержки в миллисекундах Начинаем бесконечно повторяемый цикл включить контакт 2, ждать установленное время задержки, выключить его включить контакт 3, ждать установленное время задержки, выключить его Повторите эти операции для остальных выходов - с 4 до 9 Затем сделайте то же самое, но в обратном направлении до контакта 3 Окончание бесконечного цикла Что получилось у Вас? Ни чего страшного нет, если у вас ни чего не получилось. Так как Вы учитесь. Но чтобы сэкономить ваше время ниже приведен код для данной схемы .

int del=100; // sets a default delay time, 100 milliseconds (one tenth of a second)
void setup()
{
// initialize the digital pins as outputs:
// later on there will be easier ways to do this
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
}
// the loop() method repeats indefinitely until you turn off the power
void loop()
{
digitalWrite(2, HIGH); // turn on LED on pin 2
delay(del); // wait (length determined by value of "del")
digitalWrite(2, LOW); // turn it off

delay(del); // wait


delay(del); // wait


delay(del); // wait


delay(del); // wait


delay(del); // wait


delay(del); // wait

digitalWrite(9, HIGH); // turn on LED on pin 9
delay(del); // wait
digitalWrite(9, LOW); // turn it off
digitalWrite(8, HIGH); // turn on LED on pin 8
delay(del); // wait
digitalWrite(8, LOW); // turn it off
digitalWrite(7, HIGH); // turn on LED on pin 7
delay(del); // wait
digitalWrite(7, LOW); // turn it off
digitalWrite(6, HIGH); // turn on LED on pin 6
delay(del); // wait
digitalWrite(6, LOW); // turn it off
digitalWrite(5, HIGH); // turn on LED on pin 5
delay(del); // wait
digitalWrite(5, LOW); // turn it off
digitalWrite(4, HIGH); // turn on LED on pin 4
delay(del); // wait
digitalWrite(4, LOW); // turn it off
digitalWrite(3, HIGH); // turn on LED on pin 3
delay(del); // wait
digitalWrite(3, LOW); // turn it off

Делаем бегущие огни из светодиодов на Arduino. В данном случае используется Arduino Mega 2560, который потенциально способен управлять бегущей дорожкой из 54-х светодиодов. Но схема и программа не изменятся, если вы будете использовать другие контроллеры из платформы Arduino такого типа (UNO, Leonardo...)

Схема подключения светодиодов к Ардуино Мега 2560.

Так выглядит скетч в окне стандартного приложения для программирования Ардуино.

Текст программы для реализации бегущих огней на платформе ардуино.

int first_out = 11; //первый дискретный выход

int last_out = 13; //последний дискретный выход

//блок для инициализации входов-выходов и других исходных данных

last_out = last_out + 1; //добавляем единицу для корректного использования в циклах

//определение 11-го, 12-го и 13-го дискретных выводов платы Ардуино как выходы

for (i = first_out; i < last_out; i++) { pinMode(i, OUTPUT); }

for (t = first_out; t < last_out; t++) { //перебираем номера дискретных выходов 11,12,13 поочереди

digitalWrite(t, HIGH); //зажигание следующего светодиода

delay(500); //задержка 500мсек

for (i = first_out; i < last_out; i++) { digitalWrite(i, LOW); }//гасим все светодиоды

Для увеличения количества управляемых светодиодов в гирлянде, в программе нужно будет просто заменить значения переменных first_out и last_out. Первая переменная хранит начальный дискретный выход контроллера, а вторая последний из группы выходов, которые идут подряд. Например, если мы хотим подключить 10 светодиодов в гирлянду, вводим такие значения: first_out = 4, last_out = 13. И светодиоды к выводам по порядку с 4-го по 13-й. А первый и второй вывод дискретных входов-выходов лучше не трогать, так как им мешает usb-порт, подключенный к компьютеру.

В этом уроке мы продолжим работу со светодиодами, но количество светодиодов увеличим до 5. И сделаем эффект бегущего огня. Для управления светодиодами будем использовать манипуляции с портами Arduino. Мы будем напрямую записывать данные в порты Arduino. Это лучше, чем работать с конкретными входами/выходами контроллера. Это позволит установить значения для светодиодов при помощи одной лишь операции.

У Arduino UNO имеется 3 порта:

  • B (цифровые входа/выхода с 8 по 13)
  • C (аналоговые входа)
  • D (цифровые входа/выхода с 0 по 7)

Каждый порт управляется 3 регистрами. Регистр DDR определяет чем будет являться нога (pin) входом или выходом. При помощи регистра PORT можно установить pin в состояние HIGH или LOW. При помощи регистра PIN можно считать состояние ножек Arduino, когда они работает на вход.

Мы будем использовать порт B. Сначала, мы должны установить все ножки порта B как цифровые выхода. У порта B имеется только 6 ножек. Биты регистра для В-порта DDRB должны быть установлены в 1, если нога будет использоваться как выход (OUTPUT), и в 0, если нога будет использовать как вход (INPUT). Биты портов нумеруются с 0 по 7, но не всегда содержат все 8 ног.

Пример :

DDRB = B00111110; // установить ножки порта В с 1 по 5 как выхода, а 0 как вход.

Обратите внимание, что в микроконтроллерах фирмы Microchip все наоборот. 0 бит - нога работает как выход, а 1 - как вход.

В нашем проекте бегущего огня мы будем использовать 5 выходов:

DDRB = B00011111; // установить ноги порта В с 0 по 4 как выхода

Для записи значений в порт В необходимо использовать регистр PORTB. Зажечь первый светодиод можно командой:

PORTB = B00000001;
первый и четвертый:
PORTB = B00001001;

Теперь вы видите, как легко мы можем включать и выключать светодиоды. Теперь расскажем вам об операторах сдвига

Есть 2 оператора двоичного сдвига: оператор сдвига влево << и оператор сдвига вправо >>. Оператор сдвига влево << заставляет все биты сдвигаться влево, соответственно оператор сдвига вправо >> сдвигает биты вправо.

Пример:

VarA = 1; // 00000001
varA = 1 << 0; // 00000001
varA = 1 << 1; // 00000010
varA = 1 << 2; // 00000100

Теперь вернемся к нашей программе, которая показана ниже. Нам нужно ввести 2 переменные: первая upDown будет содержать значение куда двигаться - вверх или вниз, а вторая cylon какие светодиоды зажигать.

В функции setup() мы определяем какие ножки должны работать как выхода.

В главном цикле программы loop() , светодиоды по очереди загораются вверх путем увеличения переменной cylon , а когда доходит до самого верхнего, то переменной upDown присваивается 0 и светодиоды загораются вниз по очереди.

Сказал в прошлом еще году «Гоп» - пришла пора прыгать:)
Вернее, делать обещанный обзор бегущих поворотников.
Был заказан 1 метр черной ленты WS2812B (144 светодиода) в силиконовой трубке, при заказе выбирал «Black 1m 144led IP67» (возможно, кому-то понравится белый цвет подложки, такой выбор есть).

Небольшое предостережение

Мне пришла лента, спаянная из двух полуметровых кусков. Минус этого - уязвимое место спайки (со временем могут нарушиться контакты) и увеличенный зазор между светодиодами.
Перед покупкой уточняйте у продавца этот момент

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



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

Подробности установки

Обезжирил поверхности, вначале приклеил клейкую ленту к трубке (буду так называть, хоть сечение и прямоугольное), срезал выступающие излишки более широкой ленты, просунул края трубки в щели между потолком и верхними частями декоративных панелей задних стоек (контактные провода с разъемом спрятал за одной панелью), отцентровал и стал прижимать к стеклу, потихоньку вытягивая защитный слой ленты.
Видео, к сожалению, нет - свободных рук для съемки не было, да и машины у всех разные.
Если что непонятно - спрашивайте в комментариях.
Проверка летней жарой прошла успешно - ничего не отклеилось и не поплыло.
Единственный минус - угол наклона стекла пологий, светодиоды светят больше вверх. В солнечный день плохо видно, но так как это дублирующие сигналы, то

Теперь переходим к электронной начинке.
Я использовал , но не так давно открыл для себя

Примерно за ту же стоимость получаем больше плюшек

Скетч без особых переделок будет работать и на Wemos при программировании в среде Arduino IDE, а если реализовать небольшой web-сервер, то при подключении к нему по Wi-Fi можно изменять значения таких переменных, как время задержки между миганиями, величина замедления при экстренном торможении и т.д.
Здесь в дальнейшем, если у кого-то появится заинтересованность в реализации проекта на ESP8266, могу выложить пример для изменения настроек через web-интерфейс, сохранения их в EEPROM, последующего чтения.
Запуск web-сервера можно реализовать, например, через включенный поворотник и нажатую педать тормоза при включении зажигания (в процедуре setup опросить состояние соответствующих входов).

Для реализации мигающего режима при резком торможении был куплен
В скетче отслеживается уровень замедления при нажатии педали тормоза, если он превышает 0,5G (резкое замедление, но без визга тормозов), то для привлечения дополнительного внимания на несколько секунд включается мигающий режим.
Управляющие сигналы на входы Arduino с «плюса» стопов, поворотников и заднего хода подаются через гальванические развязки - оптопары с ограничивающими ток резисторами, которые в итоге формируют уровень LOW на входах Arduino (постоянно притянуты к плюсу через резисторы 10кОм).
Питание - 5 вольт через понижающий преобразователь DC-DC.
Все это дело сложено бутербродом и упаковано в подходящую коробочку, на которой стрелочкой отметил направление монтажа для правильной ориентации датчика гравитации

Схема и фото



Номинал подтягивающих (к плюсу) резисторов стандартный - 10 кОм, ограничивающих ток оптопары резисторов - 1кОм. Оптопары выпаял из старых плат, две попались PC123, две - PC817.


На первом фото можно увидеть два дополнительных вывода, их я сделал для поворотников. Так как в моем автомобиле при включении подрулевого рычага происходит замыкание на массу, то подключил провода к колодке рычага и входам Arduino. Если подрулевой рычаг коммутирует плюс или берете сигнал с "+" лампочек левого/правого поворотника, то подключаете их через гальваническую развязку.



Ну и теперь сам скетч (Arduino IDE)

#include #include //несколько общих комментариев // я отключил по одному крайнему светодиоду, т.к. они отсвечивали на декоративные панели стоек //видно на примере этого цикла for (int i=1; i<143; i++) //если отключать не нужно, заменяем на for (int i=0; i<144; i++) //задний ход и аварийка у меня не используются, т.к. в первом случае яркость никакая, во втором надо подключать входы к лампам поворотников //поворотники и стоп-сигнал одновременно не включаются, чтобы это реализовать, нужно переписывать соответствующий код скетча (делить ленту на три секции, подбирать тайминги миганий, менять диапазон переменных циклов). //Дерзайте - все в ваших руках // Пин для подключения управляющего сигнала светодной ленты const int PinLS = 2; //Пины для подключения датчиков //если более удобно будет подключать контакты в другом порядке - просто поменяйте значения переменных const int buttonPinL = 3; const int buttonPinR = 4; const int buttonPinS = 6; const int buttonPinD = 5; //начальные статусы входов (подтянуты к плюсу) int buttonStateS = HIGH; int buttonStateD = HIGH; int buttonStateL = HIGH; int buttonStateR = HIGH; // пауза pause_pov1 (в миллисекундах) нужна, чтобы синхронизировать циклы "пробегания" полоски и включения лампочки поворотника // такое может быть, если используется меньше половины светодиодов // в моем случае паузы нет (pause_pov1 = 0) int pause_pov1 = 1; // этой паузой регулируем длительность состояния, когда все светодиоды выключены //я определял опытным путем - включал поворотник, засекал по отдельности время ста мыргов лампочкой и ста беганий полоски, разницу делил на 100, на полученное время увеличивал или уменьшал значение переменной (в зависимости от того, отставали или убегали вперед лампочки) int pause_pov2 = 62; // переменная для получения значения ускорения int ix; Adafruit_NeoPixel strip = Adafruit_NeoPixel(144, PinLS, NEO_GRB + NEO_KHZ800); Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); void setup() { pinMode(buttonPinS, INPUT); pinMode(buttonPinD, INPUT); pinMode(buttonPinL, INPUT); pinMode(buttonPinR, INPUT); strip.begin(); // гасим ленту for (int i=0; i<144; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); accel.begin(); // ограничиваем измеряемый диапазон четырьмя G (этого хватит с большим запасом) accel.setRange(ADXL345_RANGE_4_G); accel.setDataRate(ADXL345_DATARATE_100_HZ); } void loop() { // СТОПЫ: если включены - высший приоритет //Чтобы сделать меняющуюся по ширине полоску в зависимости от интенсивности торможения //(уточнение - никакой светомузыки, ширина полосы после нажатия на тормоз не меняется!) //от плавного торможения до тапки в пол. //Добавляем еще одну переменную, например, ix2, //присваиваем ей значение ix с коэффициентом умножения, //заодно инвертируем и округляем до целого //ix = event.acceleration.x; //ix2 = -round(ix*10); //ограничиваем для плавного торможения в пробках //(чтобы не менялась при каждом продвижении на 5 метров) //if (ix2<10) ix2 = 0; //и для резкого торможения. //Реальный диапазон изменения переменной ix - от 0 до -5 //для максимальной ширины полосы при G равном или большем 0.5 //if (ix2 >50) ix2 = 50; //затем меняем циклы в блоке СТОП for (int i=1; i<143; i++) на for (int i=51-ix2; i<93+ix2; i++) //Получаем минимальную ширину полоски ~30 см (для стояния в пробке) и максимальную для резкого торможения //конец комментария buttonStateS = digitalRead(buttonPinS); if (buttonStateS == LOW) { sensors_event_t event; accel.getEvent(&event); ix = event.acceleration.x; // проверка резкого торможения - мигающий режим // значение 5 - это 0,5G, минус - торможение if (ix < -5) { for (int is=0; is<15; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(240,0,0)); strip.show(); delay(10 + is*10); for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(0,0,0)); strip.show(); delay(10 + is*3); buttonStateS = digitalRead(buttonPinS); if (buttonStateS == HIGH) return; } } // помигали - и хватит, включаем постоянный режим, если педаль тормоза еще нажата // или если не было резкого торможения и предыдущее условие не сработало if (buttonStateS == LOW) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(200,0,0)); strip.show(); while(buttonStateS == LOW){ buttonStateS = digitalRead(buttonPinS); delay(50); } // плавно гасим for (int is=0; is<20; is++) { for (int i=1; i<143; i++) strip.setPixelColor(i, strip.Color(190 - is*10,0,0)); strip.show(); delay(10); } // СТОПЫ конец } } else // если СТОПЫ выключены { // ЗАДНИЙ ХОД: если включен - средний приоритет buttonStateD = digitalRead(buttonPinD); if (buttonStateD == LOW) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(63,63,63)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(63,63,63)); strip.show(); while(buttonStateD == LOW){ buttonStateD = digitalRead(buttonPinD); delay(50); } //плавно гасим for (int is=0; is<16; is++) { for (int i=1; i<37; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); for (int i=107; i<143; i++) strip.setPixelColor(i, strip.Color(60 - is*4,60 - is*4,60 - is*4)); strip.show(); delay(10); } } buttonStateL = digitalRead(buttonPinL); buttonStateR = digitalRead(buttonPinR); // если включена аварийка if (buttonStateL == LOW && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(63,31,0)); strip.setPixelColor(il+72, strip.Color(63,31,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ЛЕВЫЙ ПОВОРОТНИК if (buttonStateL == LOW && buttonStateR == HIGH) { for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(il+72, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } // если включен ПРАВЫЙ ПОВОРОТНИК if (buttonStateL == HIGH && buttonStateR == LOW) { for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(220,120,0)); strip.show(); delay(pause_pov1); } for (int il=0; il<71; il++) { strip.setPixelColor(71-il, strip.Color(0,0,0)); strip.show(); delay(pause_pov1); } delay(pause_pov2); } //правый поворотник конец } //конец условия else Стоп // задержка для следующего опроса датчиков delay(10); }

Постарался по максимуму его откомментировать, но если будут вопросы, постараюсь добавлять комментарии (поэтому располагаю его в тексте обзора, а не приложенным файлом). Это, кстати, касается и других пунктов обзора - также буду его дополнять, если в комментариях будут существенные вопросы.

И напоследок демонстрация работы (для видео использовал скетч с демо-режимом).

Upd. Скетч с демо-режимом сделал специально, чтобы в одно короткое видео вместить все.
Стоп-сигнал мигает только при резком торможении (об этом писалось выше), при плавном и стоянии в пробках просто горит, не раздражая водителей сзади.
Яркость в темное время суток не чрезмерная, т.к. светики из-за наклона стекла направлены больше вверх, чем назад.
Штатные фонари работают как обычно, эта полоса их дублирует.

Планирую купить +95 Добавить в избранное Обзор понравился +89 +191

Похожие публикации