Pull to refresh

Мигающая строка из светодиодов для стоп-сигнала на Arduino Pro Mini

Reading time 8 min
Views 133K
Мигающая строка из светодиодов для стоп-сигнала на Arduino Mini Я просто не хотел наклеивать на заднее стекло автомобиля никаких наклеек — не известно кто по ночам проходит мимо машины и какая будет реакция на надпись. Решено было сделать надпись светодиодами под задним стеклом. В неактивное время ее не видно совсем (стекло сзади тонированное), к тому же можно выключать/включать когда нужно. Ну и чуть позже пришла идея включать надпись только когда загорается стоп-сигнал и сделать надпись из красных светодиодов — получается простое дублирование стоп-сигнала, но с дополнительной информацией. Вся работа заняла 3 вечера, вот что получилось.

Конечно, можно просто купить бегущую строку или световую доску и поставить под заднее стекло… Но быстро пробежавшись по ценам этих девайсов сразу стало как-то жалко денег и было решено все сделать своими руками.

Во-первых, я определился с железом — это Arduino Pro Mini, которая стоит 4$ на eBay. Почему именно она? Потому что ее вполне достаточно, даже с избытком. Светодиоды планировалось подключать к ШИМ каналам, чтобы можно было управлять яркостью светодиодов. У Arduino Mini всего 6 таких выходов — нам вполне достаточно. На самом деле, для нашей задачи подойдет абсолютно любая Arduina.

Arduino Pro MiniДалее я определился с надписью и разбил ее на 6 независимых секций. Этого оказалось даже много, поэтому оставил только 5 действующих и один канал запланировал на «прозапас». В каждой секции получилось от 2-х до 4-х букв, на каждую букву нужно примерно по 10-20 светодиодов.

Как известно, выход Arduino тянет всего 40ma, из-за этого подключить такую ораву светодиодов напрямую к выходам Arduino не получится. Для решения проблемы использовались мосфеты P16NF06 — мощные полевики, которых у меня оказалось в загашнике штук 20. Конечно, использовать мосфеты для такой задачи — это перебор, т.к. они могут переключать токи вплоть 1 ампера (например, тянут спокойно светодиодную ленту хорошей длины). Вместо них можно использовать простые биполярные транзисторы, которые дешевле. Зато мосфеты можно подключать напрямую к выводам Arduino, т.к. у них высокое входное сопротивление и по этой же причине они не требуют обвеса в виде резистора(-ов).

Далее пришлось выделить из запасов около 130 красных светодиодов 5мм. К сожалению, столько красных светодиодов у меня в наличии не оказалось, поэтому пришлось некоторые буквы сделать зеленого цвета. Как известно, светодиоды нужно подключать через резистор для ограничения тока. Было решено подключать последовательно по 6 штук и уже этот блок светодиодов подключать через резистор к +12В. Было рассчитано и подобрано опытным путем, что для 6-ти светодиодов и напряжении питания 12В нужен резистор номиналом примерно 50 Ом.

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

В качестве основы для панели был взят обычный картон от старой коробки. Были вырезаны две полоски размером 80х15 см. Этот размер оказался оптимальным для размещения под задним стеклом автомобиля. Далее на принтере была распечатана текстовая строка и подобран шрифт для букв — Calibri размером 300. Путем прикладывания к картону, надпись была перенесена на полоску. С помощью пинцета были проделаны дырки для светодиодов. Здесь нужно обязательно учесть, что светодиоды подключаются блоками по 6 штук, поэтому к каждому каналу должно быть подсоединено число светодиодов кратное 6-ти. В принципе, это можно обойти, создав последовательную цепочку из светодиодов из любого другого количества и рассчитав резистор для подключения их к 12В.

Светодиодная панель своими руками

Также для меня было очень важным сохранить ножки светодиодов в целости и сохранности, чтобы можно было использовать их в других конструкциях. Поэтому для соединения ножки только чуть-чуть отгибались и припаивались друг к другу. Короче говоря, конструкция была собрана и запаяна примерно за 3 часа.

Светодиодная панель своими руками

Arduino Mini обычно продается без ножек, поэтому первым делом припаиваем к ней ножки. Получается практически Arduino Nano, но только без 3.3В :)

image

На макетную плату также припаиваются разъемы для вставки платы контроллера. Далее припаиваются мосфеты так, чтобы можно было прикрутить к ним единый теплоотвод (хотя, никакой теплоотвод здесь не нужен, т.к. очень маленькие токи). Выводы ШИМ 3, 5, 6, 9, 10, и 11 из Arduino Mini припаиваются к соответствующим входам соответствующего мосфета.

image

Преобразователь DC DCДалее встала задача обеспечить Arduino Mini стабильным питанием. Как известно, от прикуривателя автомобиля мы имеем 12В, но это напряжение вполне может быть и 13 и 14 вольт в определенные моменты использования автомобиля. В документации Arduino Mini написано, что максимальное питающее напряжение может быть не более 12В, а на форуме было вычитано, что даже небольшое превышение может вывести плату из строя. Поэтому было решено использовать для питания Arduino отдельный регулируемый стабилизатор DC-DC. Его также можно заказать на EBay (стоит 1$), но можно собрать самому. У меня такие блоки есть, поэтому я использовал готовый. Таким образом, на отдельный стабилизатор подается 12В (а может вплоть до 30В), а на выходе установлено, скажем 6В, которые подаются на RAW вывод Arduino Mini. Питание светодиодов же происходит напрямую от 12В (через мосфеты).


В результате проектирования печатной платы в уме получилось следующее расположение элементов:

image

Теперь настала пора решить по какому сигналу все это будет включаться. Сначала планировалось подключение всего устройства прямо параллельно лампочке стоп-сигнала на автомобиле. Но, к сожалению, при подаче напряжения на Arduino происходит инициализация контроллера и длится это достаточно продолжительное время >1 сек. Более того, сразу после включения выходы Arduino находятся в Z состоянии и мосфеты реагируют на это весьма случайным образом. В результате после включения происходит произвольная индикация в течении всего периода инициализации контроллера. Конечно, с помощью дополнительного обвеса можно задать начальное состояние ключей, но на это нужны еще детали и время…

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

ФоторезисторХотелось совсем какого-то простого решения и оно было найдено! Было решено использовать простой фоторезистор, подключенный к аналоговому входу Arduino. Сам же фоторезистор просто помещается в коробку со стоп-сигналом. Получается такая своеобразная опто-пара :) Такое решение позволяет совсем не влазить в электрику автомобиля. Правда это возможно только когда стоп-сигнал находится в салоне под стеклом и к нему можно просунуть наш фоторезистор. Короче говоря, у меня такой доступ есть, поэтому я сделал именно так.

Более того, вариант с фоторезистором позволил решить еще одну задачу — яркость свечения в зависимости от внешней освещенности. По фоторезистору можно примерно оценить освещенность на улице и днем включать подсветку ярче, а ночью потускнее. Я это учел в программе, хотя на практике оказалось, что и ночью светодиоды далеко не слепят сзади едущих водителей.

Фоторезистор подключается к выводу А0 и к +5В. Также необходим резистор номиналом 10 кОм от вывода А0 на землю. Тип фоторезистора и номинал резистора в делителе влияют на константы, которые будут заданы в программе (их можно подобрать экспериментальным путем).

В результате получилась вот такая плата:

image

FTDI BasicТеперь приступим к самому любимому занятию — программированию. Для того чтобы залить программу в Arduino Pro Mini нам потребуется преобразователь USB Serial. Я использую для этих целей FTDI Basic, который также можно приобрести на eBay.

Вот так должна выглядеть Arduino Pro Mini перед началом прошивки:

Прошивка Arduino Pro Mini

Для этого загружаем среду разработки Arduino. Если у вас все корректно установлено, то COM порт должен появиться в меню Сервис/Последовательный порт. Если его там нет, то вам нужно установить соответствующий драйвер из папки «drivers» самой платформы.

После выбора порта следует обязательно выбрать Сервис/Плата/Arduino Mini. К сожалению, здесь не все так просто. В зависимости от версии bootloader-а у вас может не получится записать программу в контроллер. Если после компиляции будет выдаваться ошибка типа

stk500_getsync(): not in sync: resp=0x00

, то скорее всего скорость COM порта среды разработки не совпадает с этим же параметром, заданным в bootloader. Чтобы это исправить, рекомендуется:

  1. Выбрать Сервис/Плата/Arduino Nano. Обычно это помогает, но если не сработало, то см. следующий пункт.
  2. В папке среды разработки находим файл "\hardware\arduino\avr\boards.txt". В этом файле находим секцию «mini.name=Arduino Mini» и далее параметр «menu.cpu.mini.atmega328.upload.speed=57600». Вот здесь пробуем менять значение 57600 (у вас может быть другое) на другие. Все возможные значения скоростей можно узнать в мониторе: меню Сервис/Монитор порта и здесь выбор в правом нижнем углу. Перед проверкой нужно перегружать среду разработки.


Сама программа спрятана тут
#define pinZA 3
#define pinNA 5
#define pinVAL 6
#define pinNO 9
#define pinGO 10
#define pinEMPTY 11

#define pinSTOPSIGNAL 0
#define sensValue 900 // порог включения. Значения 0-1024

#define sensNight 200 // ниже этого значения считается, что на дворе ночь. Значения 0-1024

#define lightDay 255 // Яркость днем. Значения 0-255
#define lightNight 150 // Яркость ночью. Значения 0-255

int currentMaxValueLight = 255;

void setup() {
  Serial.begin(9600);
  pinMode(pinZA, OUTPUT);  pinMode(pinNA, OUTPUT);  pinMode(pinVAL, OUTPUT);
  pinMode(pinNO, OUTPUT);  pinMode(pinGO, OUTPUT);
  setAll(0);
}

int currentEffect = 1;
int maxEffects = 2; // Всего эффектов в программе

void loop() {
  if(checkState()){
    switch(currentEffect){
      case 1: // Эффект 1
        effect_1();
        delayWithStateCheck(2000);
        effect_off();
      break;
      case 2: // Эффект 2
        effect_2();
        delayWithStateCheck(2000);
        effect_off();
      break;
      case 3: // Эффект 3... и тд.
         // ...................
      break;
    }
    currentEffect++;
    if(currentEffect > maxEffects){ // Больше нет эффектов, перематываем на первый
      currentEffect = 1;
    }
  }
}

void effect_2(){
  for(int i=0; i <= 1; i++){
    fade(pinZA, 3, true); fade(pinNA, 3, true); fade(pinVAL, 3, true); fade(pinNO, 3, true); fade(pinGO, 3, true);
    fade(pinZA, 3, false); fade(pinNA, 3, false); fade(pinVAL, 3, false); fade(pinNO, 3, false); fade(pinGO, 3, false);
    fade(pinGO, 3, true); fade(pinNO, 3, true); fade(pinVAL, 3, true); fade(pinNA, 3, true); fade(pinZA, 3, true);
    fade(pinGO, 3, false); fade(pinNO, 3, false); fade(pinVAL, 3, false); fade(pinNA, 3, false); fade(pinZA, 3, false);
  }  
  setAll(currentMaxValueLight);
  delayWithStateCheck(200);
  setAll(0);
  delayWithStateCheck(100);
  setAll(currentMaxValueLight);
  delayWithStateCheck(200);
}


void effect_1(){
  fade(pinZA, 10, true);
  fade(pinNA, 10, true);
  fade(pinVAL, 10, true);
  fade(pinNO, 10, true);
  fade(pinGO, 10, true);  fade(pinGO, 3, false);  fade(pinGO, 3, true);  fade(pinGO, 3, false);  fade(pinGO, 3, true);
}

void effect_off(){
  fade(pinGO, 3, false);
  fade(pinNO, 3, false);
  fade(pinVAL, 3, false);
  fade(pinNA, 3, false);
  fade(pinZA, 3, false);
}

void fade(int pin, int d, boolean side){ // Включить/выключить с эффектом fade
  if(side){
    for(int value = 0 ; value <= currentMaxValueLight; value+=5){ 
      if(!checkState()) break;
      analogWrite(pin, value);           
      delay(d);
    } 
  }else{  
    for(int value = currentMaxValueLight; value >=0; value-=5){ 
      if(!checkState()) break;
      analogWrite(pin, value); 
      delay(d);                            
    }  
  }
}

void delayWithStateCheck(int d){ // Задержка с проверкой не нужно ли выключать подсветку
  for(int value = 0 ; value <= d; value++){
    if(!checkState()) break;
    delay(1);
  }
}

boolean checkState(){ // проверка зажжен ли стоп-сигнал
  int val = analogRead(pinSTOPSIGNAL);
  boolean state = val > sensValue;
  if(!state){ // стоп-сигнал не горит
    setAll(0);
    if(val < sensNight){ // На дворе ночь или просто темно
      currentMaxValueLight = lightNight; // Уменьшаем максимальную яркость
    }else{
      currentMaxValueLight = lightDay; // Обычная яркость
    }
  }
  return state;
}

void setAll(int val){ // Установить все каналы в значение
  analogWrite(pinZA, val);
  analogWrite(pinNA, val);
  analogWrite(pinVAL, val);
  analogWrite(pinNO, val);
  analogWrite(pinGO, val);
}





Основная «сложность» в программе это обход стандартной функции delay. Дело в том, что нам нужно выключать все сразу после того, как стоп-сигнал погаснет. Для этого нужно использовать либо прерывания, либо постоянно опрашивать освещенность фоторезистора. Т.к. прерывания по аналоговому входу человечество еще не придумало (либо нужно делать обвес и зашивать пороговые значения в схему), то мы просто используем самодельную функцию delayWithStateCheck, которая «вылетает» когда стоп-сигнал гаснет.

Результат получился следующим:



Девайс в сборе, готовый к установке:

image

Стоп-сигнал с внедренным фоторезистором:

image

Вид ночью:

image



Стоимость


Все компоненты покупались на eBay в Китае или Гонконге заблаговременно.
  • Arduino Pro Mini — 150 руб
  • 6 шт P16NF06 — 120 руб
  • 130 шт светодиоды — 90 руб
  • Фоторезистор — 3 руб
  • Преобразователь DCDC — 30 руб
  • Резисторы 20 шт — 10 руб
  • Провода из пары старого Ethernet кабеля — 0 руб

Итого: 403 рубля.

Выводы


Всем удачи и успехов в освоении Arduino. Ну и, конечно, не врать и не воровать :)
Tags:
Hubs:
+40
Comments 46
Comments Comments 46

Articles