Поворотники на ардуино нано пошаговая инструкция

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

Очень интересная конструкция которая позволяет сильно приобразить Ваши поворотники. Для питания нужен преобразователь 12 => 5 вольт.
Можно использовать обазную зарядку для мобилки.

Для меня лучше подойдет скрытый вариант, который оставит место для других потребителей.

Стоит меньше долара

Для построение чудо поворотника необходимо: 4 резистора 100 кОм и 4 резистора 47 кОм, сама ардуино, а также отрезки адресной светодиодной ленты ws2812b(обычная не подойдет)

Схема подключения

Для соединения вхес елементов в целое необходима пайка, я думаю с этим проблем не будет, схему подключить так чтобы напряжение на схему поступало от включения «зажигания».

Плюсовой провод от действующих поворотников подключаются к 5 и 6 контакту контроллера через делитель напряжения из резисторов. Аналогичным образом подключаются кнопки для дополнительных режимов работы контроллера

Прошивка контоллера
Для прошивки необходим usb кабель и компьютер, ноутбук.

НОВЫЙ скетч, в котором количество диодов меняется переменно count качайте тут.

Скачать готовый скетч в файле можете по этой ссылке.

Для работы с пиксельными светодиодами нужна будет библиотека <adafruit_NeoPixel.h>. Установить ее можно будет следующим образом: Скетч -> Подключить библиотеку -> Управлять библиотеками. Далее в меню поиска ввести название библиотеки Adafruit_NeoPixel.h и нажать кнопку установить.

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

Весь код я оставлю ниже
#include <adafruit_NeoPixel.h> // подключаем библиотеку
Adafruit_NeoPixel strip = Adafruit_NeoPixel(7, 7, NEO_GRB + NEO_KHZ800); //Инициализируем первый поворотник 7 диодов на 7 цифровом выходе
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(7, 8, NEO_GRB + NEO_KHZ800);//Инициализируем второй поворотник 7 диодов на 8 цифровом выходе
void setup()
{
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
strip.begin();
strip.show();
strip2.begin();
strip2.show();
}
void loop()
{
{
if ((digitalRead(5) == HIGH) and (digitalRead(6) == HIGH))
{
//Режим аварийной сигнализации, если на 5 и 6 пин приходит плюс
for(int k = 0; k < 3; k++)
{
// цикл до трех — сигнал «перестроения», при кратковременном включении мигает 3 раза,
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < i; j++)
{
if ((digitalRead(5) == HIGH) and (digitalRead(6) == HIGH))
{
k = 0; // если во время мигания поворотника получаем еще плюcовой сигнал, то обнуяем счетчик, чтобы поворотник мигал еще как минимум 3 раза
}
strip.setPixelColor(j, strip.Color(255, 69, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j, strip2.Color(255, 69, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip.show();
strip2.show();
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < i; j++)
{
// в этом цикле плавно тушим предыдущий светодиод, делаем его наполовину тусклее, чтобы движение было плавнее
strip.setPixelColor(j-2, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip.setPixelColor(j-1, strip.Color(63, 17, 0)); // R=255, G=0, B=0 — цвет светодиода
strip.setPixelColor(j, strip.Color(127, 34, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j-2, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j-1, strip2.Color(63, 17, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j, strip2.Color(127, 34, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip.show();
strip2.show();
}
}
}

if (digitalRead(5) == LOW and digitalRead(6) == HIGH)
{
// включается один поворотник
for(int k = 0; k < 3; k++)
{
// цикл до трех — сигнал «перестроения», при кратковременном включении мигает 3 раза,
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < i; j++)
{
if ((digitalRead(5) == LOW) and (digitalRead(6) == HIGH))
{
k = 0;
}
strip.setPixelColor(j, strip.Color(255, 69, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip.show();
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < i; j++)
{
// в этом цикле плавно тушим предыдущий светодиод, делаем его наполовину тусклее, чтобы движение было плавнее
strip.setPixelColor(j-2, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip.setPixelColor(j-1, strip.Color(63, 17, 0)); // R=255, G=0, B=0 — цвет светодиода
strip.setPixelColor(j, strip.Color(127, 34, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip.show();
}

}
}
if (digitalRead(5) == HIGH and digitalRead(6) == LOW)
{ // включаем второй поворотник
for(int k = 0; k < 3; k++)
{
// цикл до трех — сигнал «перестроения», при кратковременном включении мигает 3 раза,
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < i; j++)
{
if ((digitalRead(5) == HIGH) and (digitalRead(6) == LOW))
{
k = 0;
}
strip2.setPixelColor(j, strip2.Color(255, 69, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip2.show();
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < i; j++)
{
// в этом цикле плавно тушим предыдущий светодиод, делаем его наполовину тусклее, чтобы движение было плавнее
strip2.setPixelColor(j-2, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j-1, strip2.Color(63, 17, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(j, strip2.Color(127, 34, 0)); // R=255, G=0, B=0 — цвет светодиода
}
delay(60);
strip2.show();
}
}
}
if (digitalRead(3) == HIGH)
{
// режим спецсигналов, если на 3 пин подаем плюс
for(int j = 0; j < 16; j++)
{
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(255, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 255)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(20);
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(20);
}
for(int j = 0; j < 16; j++)
{
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 255)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(255, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(20);
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(20);
}
}
if (digitalRead(4) == HIGH)
{
// Режим стробоскова, если на 4 пин подаем питание
for(int j = 0; j < 24; j++)
{
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(255, 255, 255)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(15);
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(15);
}
for(int j = 0; j < 24; j++)
{
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(255, 255, 255)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(15);
for(int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
strip2.setPixelColor(i, strip2.Color(0, 0, 0)); // R=255, G=0, B=0 — цвет светодиода
}
strip.show();
strip2.show();
delay(15);
}
}
if( digitalRead(3) == LOW and digitalRead(5) == LOW and digitalRead(6) == LOW and digitalRead(9) == LOW)
{
for(int i = 0; i < 8; i++)
{
// Зажигаем ходовые огни, если нетниодного сигнала
strip.setPixelColor(i, strip.Color(255, 255, 255));
strip2.setPixelColor(i, strip2.Color(255, 255, 255));
}
strip.show();
strip2.show();
}
}
}

Я думаю что лучше будет смотрется с силиконовыми каналами

По типу таких

Поворотник станет еще более плавным и приятным.
Осталось дело за страшным сном — разборка фары )
Если вам понравится думаю иногда выкладывать подобные посты.
Ну а на сегодня у меня все. Всем добра)
Видео работы:

Ссылка на первоисточник: тыц

  • AliExpress
  • Автомобилистам

  1. Цена: $13.52
  2. Перейти в магазин

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

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

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

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

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

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

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

Теперь переходим к электронной начинке.
Я использовал Arduino Nano 3, но не так давно открыл для себя Wemos D1 mini на ESP8266

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

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

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

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

#include <Adafruit_NeoPixel.h>
#include <Adafruit_ADXL345_U.h>

//несколько общих комментариев
// я отключил по одному крайнему светодиоду, т.к. они отсвечивали на декоративные панели стоек
//видно на примере этого цикла 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. Скетч с демо-режимом сделал специально, чтобы в одно короткое видео вместить все.
Стоп-сигнал мигает только при резком торможении (об этом писалось выше), при плавном и стоянии в пробках просто горит, не раздражая водителей сзади.
Яркость в темное время суток не чрезмерная, т.к. светики из-за наклона стекла направлены больше вверх, чем назад.
Штатные фонари работают как обычно, эта полоса их дублирует.



Планирую купить

+101


Добавить в избранное



Обзор понравился


+89
+191

Дубликаты не найдены

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

я как водитель с двадцатилетним стажем скажу больше — похуй абсолютно, лишь бы оранжевый

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

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

а на инфинити? или вообще на всех американцах? там один красный и он за всю хуйню отвечает вот это бесит а не это всё

Ну как, типо ауди )

Пошло это еще с американских машин

Оп! Айди-да-да-ген) Я кстати переделал всю свою программу. Сменил библиотеку на FastLed. Лево и право теперь независимы,стоп сигнал не перекрывает поворот и на оборот. Скоро на канале выложу.

Подключение ленты на базе WS2812B к Arduino Uno (Nano)

На первом этапе достаточно простых плат Arduino Уно или Ардуино Нано. В дальнейшем для построения более сложных систем можно будет использовать более сложные платы. При физическом подключении адресной светодиодной ленты к плате Arduino надо следить за соблюдением нескольких условий:

  • из-за низкой помехоустойчивости соединительные проводники линии данных должны быть как можно короче (надо постараться сделать их в пределах 10 см);
  • подключать проводник данных надо к свободному цифровому выходу платы Arduino – он потом будет указан программно;
  • из-за высокого энергопотребления не надо запитывать ленту от платы – для этой цели предусматриваются отдельные источники питания.

Общий провод питания светильника и Ардуино надо соединить.

Схема подключения WS2812B.

Особенности установки и настройки бегущих указателей поворота

Можно установить динамические поворотники вместо обычных светодиодов. Для этого извлекаются , демонтируется плата со светодиодами и токоограничительными резисторами. На повторителе нужно оторвать стекло от корпуса. Затем следует аккуратно вырезать отражатель и удалить его.

На место удаленного отражателя устанавливается плата SMD 5730, на которой расположены желтые светодиоды. Так как у повторителя изогнутая форма, то плату придется расслоить и немного изогнуть. У старой платы нужно отрезать часть с разъемом и припаять ее для подключения контроллера. Далее все компоненты возвращаются на место.

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

Цена вопроса

Можно изготовить поворотник бегущий огонь из дневных ходовых огней. Их стоимость составляет 600 рублей. В качестве источников света в этом случае можно взять «пиксельные» RGB светодиоды в количестве 7 штук на каждый бегущий поворотник. Стоимость одного элемента составляет 19 рублей. Для управления светодиодами необходимо приобрести Arduino UNO стоимостью 250 рублей. Таким образом, общая стоимость составит 1060 рублей.

Рассмотрим создание бегающего поворотника как на ауди, на примере фары от автомобиля Рено Клио. Сделаем поворотники и ДХО в одном устройстве.

Arduino DIY Блог, для электронщиков-самодельщиков.

Бегущие поворотники своими руками

Заметил что тема про динамические поворотники, довольно популярная в интернете. Вот и я решил приобщится к ней и внести свой вклад. Выбор пал на контроллер arduino Digispark так как он не дорого стоит, имеет маленькие габариты, минимум обвязки и не прихотлив. К тому же у меня уже есть опыт работы с Digispark ATtiny85 В качестве светодиодной ленты для тестов я использовал светодиодное кольцо на 24 пикселя, на нем установлены такие же как и на ленте светодиоды ws2812b.

Схема бегущих, динамических поворотников

Я думаю что рано или поздно, все производители автомобилей перейдут на светодиодную индикацию. Так как она имеет много преимуществ 1 — Почти не греется 2 — Мало потребляет энергии 3 — Имеет меньшие габариты 4 — Не требует специфической оптики 5 — Можно использовать один светосигнальный элемент для всех световых сигналов

Скетч для Arduino Digispark

В директивах #define можно менять настройки таймингов, если не нравятся предустановленные настройки.
#include /* #define pause_dark 17 // задержка между пикселями при затухании #define pause_light 17 // задержка между пикселями при загорании #define delay_dark 200 // задержка затухания всей ленты #define delay_light 200 // задержка свечения всей ленты #define pause_dark 0 // задержка между пикселями при затухании #define pause_light 20 // задержка между пикселями при загорании #define delay_dark 250 // задержка затухания всей ленты #define delay_light 100 // задержка свечения всей ленты */ #define pause_dark 10 // задержка между пикселями при затухании #define pause_light 20 // задержка между пикселями при загорании #define delay_dark 300 // задержка затухания всей ленты #define delay_light 50 // задержка свечения всей ленты #define num_pixel 24 // число пикселей в ленте #define led_pin 4 // пин к которому подключена светодиодная лента #define brightness 255 //яркость ленты Adafruit_NeoPixel pixelink = Adafruit_NeoPixel(num_pixel, led_pin, NEO_GRB + NEO_KHZ800); void setup() { pinMode(0, INPUT_PULLUP); //Пин для подключения кнопки pinMode(1, INPUT_PULLUP); //Пин для подключения кнопки pinMode(2, INPUT_PULLUP); //Пин для подключения кнопки pixelink.begin(); pixelink.setBrightness(brightness); pixelink.show(); } void loop() { if(digitalRead(0) == LOW) turn_light(); if(digitalRead(1) == LOW) stop_light(); if(digitalRead(2) == LOW) police_light(); if(analogRead(3) < 30 ) parking_light(); //test_port(analogRead(3)); } //================================================ void turn_light() { fill_strip(255,92,0,pause_light); delay(delay_light); fill_strip(0,0,0,pause_dark); delay(delay_dark); } //================================================ void stop_light() { set_strip(255,0,0); fill_strip(92,0,0,60); fill_strip(255,0,0,20); if(digitalRead(1) == HIGH) { fill_strip(0,0,0,10); } } //================================================ void police_light() { for (int j = 0; j < 4; j++) { set_strip(255,0,0); delay(50); set_strip(0,0,0); delay(50); } delay(200); for (int j = 0; j < 4; j++) { set_strip(0,0,255); delay(50); set_strip(0,0,0); delay(50); } delay(200); } //================================================ void parking_light() { fill_strip(255,255,255,30); while(analogRead(3) < 30){} fill_strip(0,0,0,30); } //================================================ void fill_strip(uint8_t red, uint8_t green, uint8_t blue, uint8_t pix_pause) { for (uint8_t i = 0; i < num_pixel; i++) { pixelink.setPixelColor(i, red, green, blue); pixelink.show(); delay(pix_pause); } } //================================================ void set_strip(uint8_t red, uint8_t green,uint8_t blue) { for (uint8_t i = 0; i < num_pixel; i++) { pixelink.setPixelColor(i, red, green, blue); } pixelink.show(); } /* реверс for (int i = num_pixel-1; i > -1 ; i—) { pixelink.setPixelColor(i, 0, 0, 0); pixelink.show(); delay(5); } */ //================================================ void test_port(int analog) { if(analog < 10) analog=1; else analog=analog/10; for (int i = 0; i < analog; i++) { pixelink.setPixelColor(i, 64, 64, 64); } pixelink.show(); delay(100); set_strip(0,0,0); }
Видео будет позже. Если у вас остались вопросы, то можете их задать в комментарии под статьей.

Немного инструкции по установке

1. Если это ваше первое знакомство с Аrduino, внимательно изучите гайд для новичков и установите необходимые для загрузки прошивки программы на сайте разработичика по ссылке в описании.

Скачиваем архив

2. Скачайте архив со страницы проекта, нажав кнопку скачать архив. Если же вы зашли на GitHub – тогда кликните справа вверху на кнопку Clone or download, затем на Download ZIP. Это тот же самый архив! Скачивайте версию как на фото ниже!

Программа ардуино

3. Извлеките архив. Содержимое папки Библиотека (libraries) нужно поместить в пустое место папки с библиотеками Arduino по этому пути: C:/Program Files (x86)/Arduino/libraries/ как на фото ниже!

Ардуино установка

4. Папку с прошивкой Arduino из firmware положите по пути без русских букв.

Установка программ

Если в папке с прошивкой несколько файлов – то это вкладки, и они откроются автоматически. Список файлов на фото ниже, они все откроются при открытии программы перед прошивкой.

Вкладки программы

5. Подключите Arduino к компьютеру. Для подключения Arduino к компьютеру нужен специальный ДАТА кабель, простой USB кабель не подойдет. Его можно купить там же в магазинах по ссылке в конце статьи.

Шнур для прошивки

Подготовка к прошивке Arduino

6. Запустите программу и настройте прошивку (если нужно), для этого нужно выбрать свою плату Arduino.

выбираем Ардуино

Затем выберите процессор Arduino. У меня заработал как на фото. Нижний выдавал ошибку, но у вас может быть по другому. Поэтому пробуйте и тот, и тот процессор.

Выбираем процессор Ардуино

Затем выберите COM порт подключения Arduino, и нажмите загрузить.

Выбор порта Ардуино

7. У меня загрузилось все почти сразу, выпадала ошибка отсутствия папки FHT.

Ошибка компеляции прошивки

Ее в этой библиотеке не было, я закачал ее из другой библиотеки, фото справа. У меня по ссылке с яндекс диска, она лежит в моем архиве. Папка FHT должна находится у вас в библиотеках как у меня на фото слева.

Папка FHT

Что нужно еще сделать

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

Гирлянда на бабине

Если все сделали правильно, то все будет работать отлично.

Термоусадочная трубка

Что бы сделать свет более рассеиваемым, я купил прозрачную термоусадочную трубку. Нарезал ее отрезками по 2 см и обжал кусочками каждый светодиод. Так свет стал более мягким и рассеиваемым. И к тому же можно так смело можно закатывать ленту в бабину и подключать, не боясь замыкания контактов.

Термоусадка нарезанная

Так же в этих схемах можно использовать блоки питания на 12 вольт, но подключать их через преобразователь напряжения на 5 вольт. Или использовать ленты других типов, но там нужно смотреть настройки, так как в них отличается схема работы светодиодов. И корректировки нужно вносить в прошивку. Приятных вам праздников и хорошего нового года!

Так же я подключил Arduino Nano V 3.0 с такой же прошивкой к другой адресной ленте, которую использовал в проекте цветомузыка. И получился довольно таки неплохой эффект. И из него можно тоже что то сделать. Я например приклеил ее к столу и сделал подсветку стола, смотрится так же довольно не плохо. Об этом посмотрите в видео на youtube внизу статьи.

Лента адресная

23.03.2021 14 451 Световые и звуковые приборы

Автор:Иван Баранов

Многие автолюбители, чтобы улучшить внешний вид своей машины, тюнингуют свою «Ласточку» светодиодными огнями. Одним из вариантов тюнинга является бегущий поворотник, который обращает внимание на себя других участников движения. В статье приводится инструкция по установке и настройке поворотников с бегущими огнями.

[ Скрыть]

Инструкция по сборке

Светодиодные лампы – это полупроводниковые элементы, светящиеся под воздействием электрического тока. Основной элемент в них – кремний. В зависимости от того, какие примеси используются, меняется цвет лампочек.

Фотогалерея «Возможные варианты динамических указателей поворотов»

Инструменты и материалы

Чтобы изготовить бегущий поворотник своими руками, понадобятся следующие инструменты:

  • паяльник;
  • бокорезы или плоскозубцы;
  • паяльник и материал для пайки;
  • тестер.

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

Последовательность выполнения работы

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

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

Сборка состоит из последовательности действий:

  1. Сначала следует обесточить авто, отключив отрицательную клемму от АКБ.
  2. Далее необходимо снять старые указатели поворотов и аккуратно их разобрать.
  3. Старые лампочки следует выкрутить.
  4. Места стыков следует очистить от клея, обезжирить, вымыть и дать просохнуть.
  5. На место каждого старого элемента устанавливается новый поворотник бегущий огонь.
  6. Далее сборка и установка фонарей производится в обратном порядке.
  7. После установки подключаются провода.

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

При подключении светодиодов необходимо следить, чтобы анод был подключен к плюсу источника питания, а катод – к минусу. Если подключение будет выполнено неправильно, полупроводниковые элементы не будут светиться и даже могут сгореть.

Лента на базе ws2812b

Лента на базе ws2812b
Лента на чипе ws2812b является более совершенствованной, чем ее предшественник. ШИМ драйвер в адресной ленте компактен, и размещается прямо в корпусе светоизлучающего диода.

Основные преимущества ленты на основе ws2812b:

  • компактные размеры;
  • легкость управления;
  • управление осуществляется всего по одной линии + провода питания;
  • количество включенных последовательно светодиодов не ограничено;
  • невысокая стоимость – покупка отдельно трех светодиодов и драйвера к ним выйдет значительно дороже.

Лента оснащена четырьмя выходами:

  • питание;
  • выход передачи данных;
  • общий контакт;
  • вход передачи данных.

Максимальный ток одного адресного светодиода равняется 60 миллиамперам. Рабочие температуры лежат в пределах от -25 до +80 градусов. Напряжение питания составляет 5 В +-0,5.

ШИМ драйверы ленты 8-мибитные – для каждого цвета возможно 256 градация яркости. Для установки яркости нужно 3 байта информации – по 8 бит с каждого светодиода. Информация передается по однолинейному протоколу с фиксированной скоростью. Нули и единицы кодируются высоким и низким уровнем сигнала по линии.

1 бит передается за 1,25 мкс. Весь пакет из 24 бит для одного светодиода передается за 30 мкс.

Особенности установки и настройки бегущих указателей поворота

Можно установить динамические поворотники вместо обычных светодиодов. Для этого извлекаются повторители из зеркал, демонтируется плата со светодиодами и токоограничительными резисторами. На повторителе нужно оторвать стекло от корпуса. Затем следует аккуратно вырезать отражатель и удалить его.

На место удаленного отражателя устанавливается плата SMD 5730, на которой расположены желтые светодиоды. Так как у повторителя изогнутая форма, то плату придется расслоить и немного изогнуть. У старой платы нужно отрезать часть с разъемом и припаять ее для подключения контроллера. Далее все компоненты возвращаются на место.

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

Цена вопроса

Можно изготовить поворотник бегущий огонь из дневных ходовых огней. Их стоимость составляет 600 рублей. В качестве источников света в этом случае можно взять «пиксельные» RGB светодиоды в количестве 7 штук на каждый бегущий поворотник. Стоимость одного элемента составляет 19 рублей. Для управления светодиодами необходимо приобрести Arduino UNO стоимостью 250 рублей. Таким образом, общая стоимость составит 1060 рублей.

Загрузка …

Урок 9 — Бегущие огни на Arduino UNO

Продолжаем уроки в которых мы используем Arduino, резисторы и светодиоды. Мы уже делали Светофор, полицейский стробоскоп, отправляли сигнал sos и пр. Сегодня мы будем делать бегущие огни. Бегущие огни уже были в другом блоке уроков на Arduino: Урок 2 — Подключаем сдвиговый регистр 74НС595 к Arduino. «Бегущие» огни При подключении к сдвиговому регистру всего при подключении по 3 проводам мы можем управлять 8 светодиодами. Но вот чтобы подключить 10 светодиодов, нужно подключать 2 сдвиговых регистра и использовать всего 2 выхода из 8 доступных в регистре. Это не очень логично. Иногда бывает проще подключить к плате Arduino нужное количество светодиодов. Что я и планирую сделать. В примере будет 5 самых простых режимов бегущих огней на Arduino.

Для урока нам понадобится:

  • Arduino UNO или Arduino Nano
  • Плата макетная беспаечная
  • Резисторы 220 ОМ
  • Соединительные провода папа-папа
  • Светодиоды 3 или 5 мм.

Для урока нам понадобится

Подключим наши 10 светодиоды вот по такой схеме.

Подключим наши 10 светодиоды вот по такой схеме

В живую будет выгладить так.

режимов бегущих огней на Arduino

Вы наверное скажите что схема не правильная и к пинам 0 и1 подключать не желательно. Вот именно не желательно, но можно если не использовать Serial port. А для облегчения кода нам будет очень удобно использовать данные пины. При загрузки кода в Ардуину светодиоды подключенные к 0 и 1 выходам будут мигать. Также при работе нашего скетча. Вместе с данными светодиодами на плате Arduino UNO буду включаться светодиода RX и TX. Но как я говорил в данном случаи ни чего старшного в этом нет.

Описывать все режимы не буду. В видео немного поясняю. Немного корява и может не совсем понятно. Но я думаю по комментариям к коду можно разобраться.

Первый пример бегущих огней на Arduino, последовательное включение одного светодиода с 1 по 10. По пинам на ардуино будет с 0 по 9. Это нужно учитывать при написании кода.

int last_pin = 10; //Кол-во светодиодов //блок для инициализации входов-выходов и других исходных данных void setup() { for (int i = 0; i < last_pin; i++) // цикл pinMode(i, OUTPUT); // инициализируем пины как выходы } // Основной цикл void loop() { for (int j = 0; j < last_pin; j++) { //перебираем пины с 0 до last_pin digitalWrite(j, HIGH); //зажигание следующего светодиода delay(300); //задержка 300мсек digitalWrite(j, LOW); //гасим все светодиоды } }

Немного изменим данный пример и сделаем 2 цикла. Получим включение всех светодиодов и выключение в обратном направлении.

int last_pin = 10; //Кол-во светодиодов //блок для инициализации входов-выходов и других исходных данных void setup() { for (int i = 0; i < last_pin; i++) // цикл pinMode(i, OUTPUT); // инициализируем пины как выходы } // Основной цикл void loop() { for (int j = 0; j < last_pin; j++) { //перебираем пины с 0 до last_pin digitalWrite(j, HIGH); //зажигание следующего светодиода delay(300); //задержка 300мсек } for (int j = last_pin-1; j >= 0; j—) { //перебираем пины с 0 до last_pin digitalWrite(j, LOW); //гасим все светодиоды delay(300); //задержка 300мсек } }

Объединив код первого и второго примера получим включение одного светодиода в прямом и обратном направлении. Во втором цикли ставим j-2, потому что у нас пины начинаются с 0, а число светодиодов с 1 до 10. Также чтобы 10 светодиод не включался 2 раза вычитаем еще 1.

int last_pin = 10; //Кол-во светодиодов //блок для инициализации входов-выходов и других исходных данных void setup() { for (int i = 0; i < last_pin; i++) // цикл pinMode(i, OUTPUT); // инициализируем пины как выходы } // Основной цикл void loop() { for (int j = 0; j < last_pin; j++) { //перебираем пины с 0 до last_pin digitalWrite(j, HIGH); //зажигание следующего светодиода delay(300); //задержка 300мсек digitalWrite(j, LOW); //гасим все светодиоды } for (int j = last_pin-2; j > 0; j—) { //перебираем пины с 0 до last_pin digitalWrite(j, HIGH); //зажигание следующего светодиода delay(300); //задержка 300мсек digitalWrite(j, LOW); //гасим все светодиоды } }

Сходящиеся огни. Тут все по аналогии. Добавим переменную в которой будим рассчитывать половину светодиодов. Поэтому количество светодиодов должно быть четным. Либо что-то делать с центральным светодиодом. Можно оставить его постоянно включенным или наоборот всегда включенным.

int last_pin = 10; //Кол-во светодиодов //блок для инициализации входов-выходов и других исходных данных void setup() { for (int i = 0; i < last_pin; i++) // цикл pinMode(i, OUTPUT); // инициализируем пины как выходы } // Основной цикл void loop() { int half = last_pin/2; //last_pin должгно быть четным числом for (int j = 0; j < half; j++) { //перебираем пины с 0 до last_pin int k = last_pin-j-1; digitalWrite(j, HIGH); //зажигание следующего светодиода digitalWrite(k, HIGH); //зажигание следующего светодиода delay(300); //задержка 300мсек digitalWrite(k, LOW); //гасим все светодиоды digitalWrite(j, LOW); //гасим все светодиоды } }

И по аналогии делаем расходящиеся огни.

int last_pin = 10; //Кол-во светодиодов //блок для инициализации входов-выходов и других исходных данных void setup() { for (int i = 0; i < last_pin; i++) // цикл pinMode(i, OUTPUT); // инициализируем пины как выходы } // Основной цикл void loop() { int half = last_pin/2; //last_pin должгно быть четным числом for (int j = half; j > 0; j—) { //перебираем пины с 0 до last_pin int k = last_pin-j; digitalWrite(j-1, HIGH); //зажигание следующего светодиода digitalWrite(k, HIGH); //зажигание следующего светодиода delay(500); //задержка 300мсек digitalWrite(k, LOW); //гасим все светодиоды digitalWrite(j-1, LOW); //гасим все светодиоды } }

Как видно без использования сдвигового регистра код получается намного проще и меньше строчек. Один минус количество ограничено. Максимум 20 светодиодов можно подключить к Arduino Uno и 22 к Arduino NANO. Думаете что я ошибся с цифрами. Подписывайтесь на канал. И в следующем уроке в данном блоке уроков я покажу как можно это реализовать.

Подписывайтесь на мой канал на Youtube и вступайте в группы в Вконтакте и Facebook.

Спасибо за внимание!

Понравилась статья? Поделитесь ею с друзьями:

Адресная светодиодная лента Ардуино

Адресные ленты отличаются плотностью — от 30 до 144 светодиодов на метр, изготавливаются разном защитном исполнении: IP30, IP65, IP67, IP68. Все варианты исполнения, кроме IP30, могут применяться на улице в диапазоне температур от -25 до +80°C. Еще одна, более надежная лента — WS2813 отличается возможностью передавать сигналы дальше по цепочке даже через сгоревший чип.

Светодиодная лента WS2812B характеристики

  • Размер светодиода — 5 х 5 мм
  • Частота ШИМ — 400 Гц
  • Скорость передачи данных — 800 кГц
  • Размер данных — 24 бита на светодиод
  • Напряжение питания — 5 Вольт
  • Потребление при нулевой яркости — 1 мА на светодиод
  • Потребление при максимальной яркости — 60 мА на светодиод
  • Цветность: RGB, 256 оттенков на канал, 16 миллионов цветов

Характеристики WS2812B

Как проверить адресную ленту без Ардуино

WS2812B светодиоды

Если под рукой нет платы Ардуино, то можно использовать для проверки специальный контроллер. В крайнем случае, просто потрогать цифровой провод, чтобы понять будут гореть светодиоды на ленте или нет. Другого надежного способа проверить работу ws2812b ленты нет, поэтому рассмотрим далее управление и программирование адресной светодиодной ленты на микроконтроллере Ардуино Нано или Уно.

( 2 оценки, среднее 5 из 5 )

Сказал в прошлом еще году «Гоп» — пришла пора прыгать 🙂

Вернее, делать обещанный обзор бегущих поворотников.

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

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

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

такой

.

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

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

Видео, к сожалению, нет — свободных рук для съемки не было, да и машины у всех разные.

Если что непонятно — спрашивайте в комментариях.

Проверка летней жарой прошла успешно — ничего не отклеилось и не поплыло.

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

Как сделать динамические поворотники на WS2812B и Ардуино

Теперь переходим к электронной начинке.

Я использовал

Arduino Nano 3

, но не так давно открыл для себя

Wemos D1 mini на ESP8266

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

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

Для реализации мигающего режима при резком торможении был куплен

такой датчик ускорения

В скетче отслеживается уровень замедления при нажатии педали тормоза, если он превышает 0,5G (резкое замедление, но без визга тормозов), то для привлечения дополнительного внимания на несколько секунд включается мигающий режим.

Управляющие сигналы на входы Arduino с «плюса» стопов, поворотников и заднего хода подаются через гальванические развязки — оптопары с ограничивающими ток резисторами, которые в итоге формируют уровень LOW на входах Arduino (постоянно притянуты к плюсу через резисторы 10кОм).

Питание — 5 вольт через понижающий преобразователь DC-DC.

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

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

#include <Adafruit_NeoPixel.h>
#include <Adafruit_ADXL345_U.h>

//несколько общих комментариев
// я отключил по одному крайнему светодиоду, т.к. они отсвечивали на декоративные панели стоек
//видно на примере этого цикла 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. Скетч с демо-режимом сделал специально, чтобы в одно короткое видео вместить все.
Стоп-сигнал мигает только при резком торможении (об этом писалось выше), при плавном и стоянии в пробках просто горит, не раздражая водителей сзади.
Яркость в темное время суток не чрезмерная, т.к. светики из-за наклона стекла направлены больше вверх, чем назад.
Штатные фонари работают как обычно, эта полоса их дублирует.

Многие рыбаки задаются вопросом, как же эта снасть умеет так мастерски отдаляться от берега. На самом деле здесь все просто и это обычное физическое явление. В первую очередь снасть должна быть плавучей, поэтому ее изготавливают из дерева или пенопласта. А секрет, почему же кораблик плывет, кроется в его геометрии.

За счет углов на бортах кораблика (или это может быть руль) течением создается давление воды, оно то и толкает кораблик от берега. Если кораблик развернуть на 180 градусов, то он наоборот будет плыть к берегу.Ловить при помощи кораблика можно и с лодки. Важным моментом здесь является наличие течения. И чем сильнее будет течение, тем дальше кораблик сможет заплыть.

Также такой кораблик может плыть при наличии волн.

— две дощечки, 12 и 14 см (желательно бук или дуб);- линейка;- две шпильки с гайками диаметром 6 мм;- строительный кронштейн;- дрель;- шурупы;- две свинцовые пластины для огрузки.Как сделать снасть «Кораблик» своими рукамиШаг первый. Вырезаем основу корабликаОсновой кораблика будут являться две доски, в итоге они образуют два борта кораблика. Доски нужно вырезать таким образом, чтобы образовались две одинаковые трапеции. Боковые грани бортов должны обязательно иметь срезы. Именно благодаря этим срезом будет образовываться разница в давлении, и кораблик будет отплывать от берега.Как сделать снасть «Кораблик» своими рукамиШаг первый. Вырезаем основу корабликаОсновой кораблика будут являться две доски, в итоге они образуют два борта кораблика. Доски нужно вырезать таким образом, чтобы образовались две одинаковые трапеции. Боковые грани бортов должны обязательно иметь срезы. Именно благодаря этим срезом будет образовываться разница в давлении, и кораблик будет отплывать от берега.Шаг второй. Соединение бортовНа следующем этапе в обеих досках следует просверлить по два отверстия. Лучше всего положить одну доску на другую и просверлить таким образом отверстия. В этом случае они будут симметричны, и кораблик будет ровным. Для соединения бортов автор использовал шпильки. Важно, чтобы диаметр шпилек четко совпадал с диаметром сверла или сверло было даже немного меньше. В этом случае не будет люфта в соединении, и конструкция будет крепкой.Далее в обе доски вставляется шпилька и с обеих сторон наворачиваются гайки. При соединении досок важно, чтобы срезы на их торцевых частях смотрели в одну сторону. Это рули корабля.Как сделать снасть «Кораблик» своими руками

Шаг третий. Огрузка кораблика

Кораблик обязательно нужно огрузить, иначе он не будет работать должным образом. Нужно добиться того, чтобы из воды было видно не более 2-3 см кораблика. Для огрузки можно использовать свинцовые пластины. Они крепятся к торцевой части бортов при помощи саморезов, гвоздей, шурупов или клея.Как сделать снасть «Кораблик» своими рукамиШаг четвертый. Запуск корабликаЛучше всего отправлять кораблик путь при помощи старого спининга из дюралюминия, а в качестве катушки отлично подходит «невская». Леска используется монофильная диаметром 0.3 см, а длина может быть порядка 150 метров. Леска привязывается к кронштейну, отлично для этих целей подходит карабин с вертлюжком. Далее, на расстоянии порядка 5-6 метров от кораблика можно вязать поводки, их дискретность должна быть 2.5 м.Длина первого поводка должна быть в пределах 35 см, а второго 50 см. Длина поводков регулируется в зависимости от того, какова высота берега в месте ловли. Что касается крючков, то здесь уже зависит от рыбы, в среднем это 7-8 номер.Как ловить при помощи корабликаНа крючки следует насадить мух, жуков или же наживку можно заменить искусственными мушками. Далее нужно подойти к реке и опустить кораблик в воду. Сразу же после небольшого натяжения судно начнет отплывать. Теперь останется лишь отматывать леску, пока кораблик не отплывет на нужную дистанцию от берега. Поклевка определяется визуально, также она ощущается как удар на спиннинге. Сделав подсечку, можно приступать к постепенному вываживанию. Чтобы привлекать внимание рыбы, наживку нужно периодически поднимать с воды, а затем опускать.

Для успешной рыбалки останется лишь правильно определить место стоянки рыбы и преподнести ей наживку.

Становитесь автором сайта, публикуйте собственные статьи, описания самоделок с оплатой за текст. Подробнее здесь.

Меня зовут Дмитрий Дударев. Я занимаюсь разработкой электроники и очень люблю создавать различные портативные девайсы. Еще я люблю музыку.

Давным-давно – в апреле или около того, когда весь мир сотрясался от ударов страшного карантина, я решил научиться играть на гитаре. Я взял у друга акустическую гитару и стал осваивать инструмент по урокам из ютуба и табулатурам. Было тяжело. То ли я неправильно что-то делал, то ли плохо старался, то ли в обществе моих предков мелкая моторика вредила размножению. Короче, ничего кроме звуков дребезжащих струн у меня не выходило. Мое негодование усиливала постоянная расстройка струн. Да и окружающим тысячный раз слушать мою кривую Nothing else matters удовольствия не доставляло.

Но в этих муках про главное правило электронщика я не забыл. Если что-то существует, значит туда можно вставить микроконтроллер. Или, хотя бы, сделать портативную электронную модификацию.

Электронная гитара? Хм, интересная идея, подумал я. Но еще лучше, если на этой гитаре я сам смогу научиться играть. В тот же день акустическая гитара отправилась на свалку обратно к другу, а я стал придумывать идею.

Поскольку я у мамы инженер, то первым делом я составил список требований к девайсу.

Что я хочу от гитары?

1)  Я хочу что-то максимально похожее на гитару, т.е. шесть струн и 12 ладов на грифе.

2)  Хочу компактность и портативность. Чтобы можно было брать девайс с собой куда угодно, не заказывая газель для транспортировки.

3)  Устройство должно без плясок с бубном подключаться к чему угодно, от iOS до Windows. Окей-окей, ладно, будем реалистичными – ко всем популярным осям.

4)  Работа от аккумулятора.

5)  Подключение должно производиться без проводов (но раз уж там будет USB разъем для зарядки, то и по проводу пусть тоже подключается)

6)  Ключевой момент – на гитаре должно быть просто учиться играть, без необходимости в долгих тренировках по адаптации кистевых связок. Как это реализовать? Сразу пришла идея оснастить струны и лады светодиодами. Типа, загрузил табулатуры в гитару, а она уже сама показывает, куда ставить пальцы. Т.е. нет такого, что смотришь на экран, потом на гитару, снова на экран, снова на гитару. Вот этого вот всего не надо. Смотришь только на гитару. И там же играешь. Все. Это прям мое.

7)  Хотелось бы поддержки разных техник игры на гитаре: hummer on, pull off, slide, vibrato.

8) Без тормозов. По-научному – чтобы задержка midi-команд не превышала 10мс.

9)  Все должно собираться из говна и палок легко доступных материалов без сложных техпроцессов и дорогой электроники.

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

Разумеется, для мобильных платформ потребуется написать приложение, в котором можно будет выбрать табулатуру для обучения светодиодами, выбрать инструмент (акустика, классика, электрогитара с различными пресетами фильтров, укулеле и т.д.), и воспроизводить звуки.

Существующие аналоги

А надо ли изобретать велосипед? Ведь на всякую гениальную идею почти наверняка найдется азиат, который уже давно все реализовал в «железе», причем сделал это лучше, чем ты изначально собирался. Иду гуглить.

Оказывается, первая цифровая гитара была создана еще в 1981 году, но в народ сильно не пошла из-за хилой функциональности.

Варианты посовременнее, конечно, тоже нашлись.

Вот, например, с айпадом вместо струн или еще одна в форме моллюска:

Однако такого, чтобы выполнялись все мои хотелки – в первую очередь компактность и режим обучения «жми на лампочки» – такого нет. Кроме того, такие midi-гитары нацелены все же на более профессиональную аудиторию. И еще они дорогие.

Значит, приступаем!

Первый прототип

Чтобы проверить жизнеспособность концепции, нужно сначала определиться с элементной базой.

Контроллер берем STM32F042. В нем есть все, что нужно, при стоимости меньше бакса. Кроме беспроводного подключения, но с этим позже разберемся.

Далее. Струны на деке. Для первого концепта решил напечатать пластиковые язычки, закрепить их на потенциометрах с пружинками и измерять углы отклонения.

Так выглядит 3D-модель:

А так живьем:

Тактильное ощущение приятное. Должно сработать.

Для ладов на грифе я заказал на Али вот такие тензорезистивные датчики.

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

Плюс нужен АЦП, чтобы считывать инфу с датчиков и передавать на контроллер.

Пока ждал датчики из Китая, развел плату:

Прежде чем заказывать печать платы, решил дождаться тензорезисторов. И, как оказалось, не зря. Из 80-ти датчиков рабочими оказались только несколько, и то с разными параметрами.

Выглядит, мягко говоря, не так, как заявлено. И чего я ожидал, покупая электронику на Али?..

И тут меня осенило.

Можно ведь применить другой метод детектирования — измерение емкости, как в датчиках прикосновения. Это гораздо дешевле и доступнее. А если правильно спроектировать механику, то можно и усилие определять.

Что ж. Удаляю все, что было сделано

Второй прототип

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

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

Решив вопрос подключения множества микросхем измерителя емкости к контроллеру, приступаю к разводке платы.

На этот раз плату удалось заказать и даже дождаться ее изготовления.

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

Чтобы подключить свое приложение к виртуальному синтезатору я сэмулировал виртуальный порт midi, который подключен ко входу синтезатора RealGuitar через эмулятор midi-кабеля. Такая вот многоуровневая эмуляция.

*Мем с ДиКаприо с прищуренными глазами*

В интерфейсе программы я сделал графическое отображение уровня измеряемой емкости для каждого сенсора. Так будет проще подстраивать звучание. Также на будущее добавил элементы управления светодиодами, вибромотором (пока не знаю зачем, но он тоже будет в гитаре), визуализации работы акселерометра и уровня заряда аккумулятора.

Для того чтобы удары по струнам гитары вызывали проигрывание правильных нот, нужно замапить все 72 сенсора на грифе на соответствующую ноту.

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

Проверяем работу

Похоже, все готово для первого теста. Пилить прутки и паять все 12 ладов мне было лень, поэтому ограничился 8-ю. Момент истины:

IT’S ALIVE! Жизнеспособность концепта подтверждена. Счастью не было предела! Но нельзя расслабляться.

Следующий этап – добавление светодиодов, акселерометра, вибромотора, аккумулятора, беспроводной связи, корпуса и возможности работы без драйверов или программ эмуляции midi на всех популярных платформах.

Светодиоды

По плану гитара должна подсказывать пользователю, куда ставить пальцы, зажигая в этом месте светодиод. Всего нужно 84 светодиода. Тут все просто. Я взял 14 восьмибитных сдвиговых регистров и соединил в daisy chain. STM-ка передает данные в первый регистр, первый – во второй, второй – в третий и т.д. И все это через DMA, без участия ядра контроллера.

Акселерометр

Самый простой акселерометр LIS3D позволит гитаре определить угол своего наклона. В будущем буду это использовать для наложения звуковых фильтров во время игры в зависимости от положения гитары.

Беспроводное соединение

Для беспроводной передачи данных решил поставить ESP32. Оно поддерживает различные протоколы Bluetooth и WI-FI, будет с чем поэкспериментировать (на тот момент я еще не знал, что в моем случае существует только один правильный способ подключения).

Корпус

Одно из ключевых требований к гитаре – портативность. Поэтому она должна быть складной, а значит, электронику деки и грифа нужно разнести на две платы и соединять их шлейфом. Питание будет подаваться при раскрытии корпуса, когда магнит на грифе приблизится к датчику Холла на деке.

Доработка прототипа

Что ж, осталось облачить девайс в приличную одежку.

Я много экспериментировал с различными конструкциями тактильных элементов грифа и рассеивателями для светодиодов. Хотелось, чтобы равномерно светилась вся поверхность элемента, но при этом сохранялась возможность детектирования прикосновения и нажатия на кнопки.

Вот некоторая часть этих экспериментов:

Еще я обратился к другу, который профессионально занимается промышленным дизайном. Мы придумали конструкцию узла сгибания гитары, после чего он спроектировал и напечатал прототип корпуса.

Развожу финальный вариант плат и собираем гитару:

Выглядит почти круто. Но девайс все еще подключается к компу через цепочку эмуляторов, эмулирующих другие эмуляторы.

Превращаем гитару в MIDI-устройство

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

Оказалось, сделать это не так сложно. Все спецификации есть на официальном сайте usb.org. Но все алгоритмы, которые выполнялись на стороне python-приложения, пришлось переписывать на C в контроллер.

Я был удивлен, что оно сразу заработало на всех устройствах. Windows 10, MacOS, Debian 9, Android (через USB переходник). Достаточно просто воткнуть провод и в системе появляется MIDI-устройство с названием «Sensy» и распознается всеми синтезаторами. С айфоном пока протестировать не удалось т.к. нет переходника. Но должно работать так же.

Беспроводной интерфейс

Осталось избавиться от проводов. Правильное решение пришло не сразу, потому что я поленился как следует погуглить. Но в итоге я использовал протокол BLE MIDI, который поддерживается всеми новыми операционками и работает без всяких драйверов прямо как по USB MIDI. Правда, есть вероятность, что на более старых операционках решение не заработает в силу отсутствия поддержки BLE MIDI. Но все тесты с доступными мне девайсами прошли успешно.

Переписанный функционал приложения – т.е. трансляция данных сенсоров в MIDI-данные – занял точнехонько всю память контроллера. Свободными осталось всего 168 байт. Очевидно, кремниевые боги мне благоволили, значит иду в правильном направлении.

Уверен, можно оптимизировать, но это отложу для следующей версии. Хотя, возможно, проще не тратить время и просто взять контроллер потолще. Разница по деньгам – 5 центов. Посмотрим. Все равно нужно будет место для новых фич – обрабатывать техники игры, например. В первую очередь, хочу реализовать slide. Это когда начинаешь играть ноту с определенным зажатым ладом и проскальзываешь рукой по грифу, перескакивая с лада на лад.

Теперь можно проверить работу по беспроводу:

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

Недостатки прототипа

На текущий момент у конструкции есть следующие минусы:

1) На сенсорах нигде не измеряется усилие нажатия. Это влечет за собой три проблемы:

• Постоянно происходят случайные задевания соседних струн как на деке, так и на грифе. Это делает игру очень сложной.

• Все играемые ноты извлекаются с одинаковой громкостью. Большинство подопытных этого не замечают, но хотелось бы более приближенной к настоящей гитаре игры

• Невозможность использовать техники hammer on, pull off и vibrato

2) Светодиоды одноцветные. Это ограничивает наглядность при игре по табулатурам. Хочется иметь возможность разными цветами указывать на различные приемы игры.

3) Форма корпуса не подходит для левшей. С точки зрения софта – я уже реализовал инверсию струн по акселерометру. Но механический лепесток, необходимый для удержания гитары рукой во время игры, поворачивается только в сторону, удобную правшам.

4) Отсутствие упора для ноги. Сейчас при игре сидя нижняя струна почти касается ноги, а это неудобно.

5)  Сустав сгибания гитары требует осмысления и доработки. Возможно, он недостаточно надежен и стабилен.

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

Переезжаю на контроллер серии STM32F07. На нем уже 128КБ флэша – этого хватит на любой функционал. И даже на пасхалки останется.

Использовать ESP32 в финальной версии гитары было бы слишком жирно, поэтому я пошел искать что-то более православное. Выбор пал на NRF52 по критериям доступности, наличию документации и адекватности сайта.

Конечно, будут реализованы и три главных нововведения:

– светодиоды теперь RGB,

– на каждом сенсоре грифа будет измерение усилия (тактовые кнопки больше не нужны),

– струны на деке станут подвижными.

На данный момент плата деки выглядит так (футпринт ESP на всякий случай оставил):

Уже есть полная уверенность в том, что весь задуманный функционал будет реализован, поэтому было принято решение о дальнейшем развитии. Будем пилить стартап и выкладываться на Kickstarter 🙂

Проект называется Sensy и сейчас находится в активной разработке. Мы находимся в Питере, сейчас команда состоит из двух человек: я занимаюсь технической частью, мой партнер – маркетингом, финансами, юридическими вопросами.

Скоро нам понадобится наполнять библиотеки табулатур и сэмплов различных инструментов. Если среди читателей есть желающие в этом помочь – пожалуйста, пишите мне в любое время.

Кому интересно следить за новостями проекта – оставляйте почту в форме на сайте и подписывайтесь на соцсети.

Очень надеюсь на обратную связь с комментариями и предложениями!

Спасибо за внимание!

Забавный эпизод из процесса разработки

Сижу отлаживаю NRF52, пытаюсь вывести данные через UART. Ничего не выходит. Проверял код, пайку, даже перепаивал чип, ничего не помогает.

И тут случайно нестандартным способом перезагружаю плату – в терминал приходит буква «N» в ascii. Это соответствует числу 0x4E, которое я не отправлял. Перезагружаю еще раз – приходит буква «O». Странно. Может быть проблема с кварцевым резонатором и сбился baud rate? Меняю частоту в терминале, перезагружаю плату – опять приходит «N». С каждой новой перезагрузкой приходит по новой букве, которые в итоге составляют повторяющуюся по кругу фразу «NON GENUINE DEVICE FOUND».

Что эта NRF-ка себе позволяет? Прошивку я обнулял. Как она после перезагрузки вообще помнит, что отправлялось в предыдущий раз? Это было похоже на какой-то спиритический сеанс. Может, я и есть тот самый NON GENUINE DEVICE?

Залез в гугл, выяснил, что производители ftdi микросхем, которые стоят в USB-UART донглах, придумали способ бороться с китайскими подделками. Виндовый драйвер проверяет оригинальность микросхемы и на лету подменяет приходящие данные на эту фразу в случае, если она поддельная. Очевидно, мой донгл оказался подделкой и переход на другой решил эту проблему.

Снова спасибо китайцам.

Понравилась статья? Поделить с друзьями:
  • Вай фай роутер билайн смарт бокс инструкция
  • Джаноме 744д оверлок инструкция по применению
  • Как разместить аудиторское заключение на федресурсе пошаговая инструкция
  • Фунгицид топаз инструкция по применению препарата
  • Как сделать самому кастинговую сеть пошаговая инструкция