ARDUINO+WS2812

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
Привет коллеги. Сначала собрал схему на симуляторе всё работает. Собрал на стенде и нарисовалась проблема. При нажатии кнопки загорается цепочка из светодиодов определённого цвета. При отпускании кнопки цепочка не гаснет сразу вся, а поочерёдно каждый светодиод. Как устранить данную траблу. Код прилагается.
C++:
#include <Adafruit_NeoPixel.h>

#define Pin1 10


#define button1 4
#define button2 7
#define button3 8
#define Diody 60
#define led1 11
#define led2 10
#define led3 10
int NUMPIXELS1[]{1,2,3,4,5,6,7,8,9,10};
int NUMPIXELS2[]{7,13,19,25,31,37,43,49,55};
int NUMPIXELS3[]{3,8,15,21,27,33,39,45,51,59};
Adafruit_NeoPixel strip1(Diody,Pin1, NEO_GRB+NEO_KHZ800);



void setup() {
strip1.begin(); // put your setup code here, to run once:
strip1.setBrightness(255);






pinMode(4, INPUT);

pinMode(7, INPUT);
pinMode(8, INPUT);

}

void loop() {
if (digitalRead(4) == HIGH)

{
for(int i=0;i<led1;i++)

{

strip1.setPixelColor(NUMPIXELS1[i],strip1.Color(255,0,0));
strip1.show();
delay(5);



}
}
else
  {
  for(int i=0;i<led1;i++)

{

strip1.setPixelColor(NUMPIXELS1[i],strip1.Color(255,255,255));
strip1.show();
delay(5);

if (digitalRead(7) == HIGH)

{
for(int i=0;i<led2;i++)

{

strip1.setPixelColor(NUMPIXELS2[i],strip1.Color(0,255,0));
strip1.show();
delay(5);
}
}
else
  {
  for(int i=0;i<led2;i++)

{

strip1.setPixelColor(NUMPIXELS2[i],strip1.Color(255,255,255));
strip1.show();
delay(5);
if (digitalRead(8) == HIGH)

{
for(int i=0;i<led3;i++)

{

strip1.setPixelColor(NUMPIXELS3[i],strip1.Color(0,0,255));
strip1.show();
delay(5);
}
}
else
  {
  for(int i=0;i<led3;i++)

{

strip1.setPixelColor(NUMPIXELS3[i],strip1.Color(255,255,255));
strip1.show();
delay(5);
}
}

  }
  }
}
  }
  }
 
Изменено:

Сотнег

★★★★★★★
15 Янв 2020
4,357
1,493
@VictorArx,
имеете в виду, что строчки
strip1.show();
delay(5);
нужно ставить не перед фигурной скобкой },
а после неё?

И нажмите там опцию "привести код в красивый вид".
Чтобы отступы с фигурными скобками показали вам, как всё запущенно.
 

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
@Старик Похабыч, не так задумано. Нужно чтобы при нажатии кнопок загорались соответствующие пиксели, а при отпускании кнопок сразу тухли. На симуляторе что вы рекомендовали всё работает с этим кодом. Может проблема в else?

@Сотнег, дружище забыл, где эта опция красивого вида. На симуляторе работает нормально.
 

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
C++:
#include <Adafruit_NeoPixel.h>
#define Pin1 10
#define button1 6
#define button2 7
#define button3 8
#define Diody 5
#define led1 1
#define led2 2
#define led3 2
int NUMPIXELS1[]{0};
int NUMPIXELS2[]{1,2};
int NUMPIXELS3[]{3,4};
Adafruit_NeoPixel strip1(Diody,Pin1, NEO_GRB+NEO_KHZ800);
void setup() {
strip1.begin(); // put your setup code here, to run once:
strip1.setBrightness(255);
pinMode(6, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);
}
void loop() {
if (digitalRead(6) == HIGH)
{
for(int i=0;i<led1;i++)
{
strip1.setPixelColor(NUMPIXELS1[i],strip1.Color(255,0,0));
strip1.show();
delay(5);
}
}
else
  {
  for(int i=0;i<led1;i++)
{
strip1.setPixelColor(NUMPIXELS1[i],strip1.Color(255,255,255));
strip1.show();
delay(5);
if (digitalRead(7) == HIGH)
{
for(int i=0;i<led2;i++)
{
strip1.setPixelColor(NUMPIXELS2[i],strip1.Color(0,255,0));
strip1.show();
delay(5);
}
}
else
  {
  for(int i=0;i<led2;i++)
{
strip1.setPixelColor(NUMPIXELS2[i],strip1.Color(255,255,255));
strip1.show();
delay(5);
if (digitalRead(8) == HIGH)
{
for(int i=0;i<led3;i++)
{
strip1.setPixelColor(NUMPIXELS3[i],strip1.Color(0,0,255));
strip1.show();
delay(5);
}
}
else
  {
  for(int i=0;i<led3;i++)
{
strip1.setPixelColor(NUMPIXELS3[i],strip1.Color(255,255,255));
strip1.show();
delay(5);
}
  }
}
  }
}
  }
}
2024-07-19_20-48-48.png
 
Изменено:

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
Верно, если на симуляторе нарисовать столько пикселей , а именно 60, то работает точно также, как и на стенде. Это с парой диодов вроде работало правильно. Так , что в коде подправить, где косяк?
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
464
134
Поворчу.
Бывает, так себя ведут определенного склада характера новички.
A- Помогите найти ошибку
В- У вас код не отформатирован, читать неудобно.
А- Да я не разобрался, как здесь форматировать. Вы мне ошибку найдите.
В- Дайте ссылку, где нормально отформатировано.
А- Ссылку давать нет смысла. Вы мне ошибку найдите.

Если бы был хотя бы комментарий в соответствующей строчке - "Здесь должно происходить то-то, а происходит то-то".
Но нет. "Так , что в коде подправить, где косяк? "
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,262
1,300
Москва
Вообще не понял ничего. Тут значит так. Если нажать кнопку , то постепенно одним цветом (красным) загорится вся лента и будет так загораться много раз пока кнопка нажата. Но т.к. очищения ленты нет, то этого не будет видно, просто код будет выполняться. Своего рода стробоскоп. Если отпустить эту кнопку, то лента не потухнет, а так же попиксельно будет загораться белым цветом, точно так же как красным - это в коде 33 и далее. странное решение.И в этом же цикле идет проверка на нажатие кнопки.
Если надо что бы сразу тухла, 1) цикл в строке 33 убрать 2) строку 35 заменить на
strip1.fill(strip1.Color(255, 255, 255),0,led1);

Такую же фигню сделать с остальными кнопками
 

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
В моём проекте кнопок не будет. Это я проверяю работу ленты. Нужно при высоком уровне загорался красный свет, при низком белый. Потом при высоком уровне загорался зелёный при низком белый. При высоком синий при низком белый. Это происходит, но при отпущеных кнопках красный сигнал не сразу выключается , а поочерёдно по одному диоду. Нужно сразу отключение основного цвета и затем загорается белый. Он всегда должен быть при отпущеной кнопке при низком сигнале.Также не сразу происходит с отключением зелёного и синего цветов, отключаются по одному светодиоду.
 
Изменено:

poty

★★★★★★✩
19 Фев 2020
3,228
939

@VictorArx, ответ на вопрос разделяется на 2:
  • логика обработки команд (сигналов, кнопок, как ни назови) неверная (по крайней мере - неточная); из описания мне лично так и непонятно, что хотелось получить;
  • для изменения состояния целой ленты существует отдельный метод, приведённый @Старик Похабыч в своём ответе; использовать псевдоплавное заполнение ленты с помощью массивов и оператора for, а потом спрашивать, почему оно плавно включается - как по мне - несколько странно.

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

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
@poty, постараюсь объяснить что я хочу получить. Имею фильтры на ОУ разных частот и пиковые детекторы. Эти сигналы высокого уровня будут подаваться на Arduino. Поэтому решил написать код в котором я не смыслю особо бо не программист, насколько Вы знаете. На симуляторе с помощью кнопок решил проверить работу кода. Работает, но проблема в том, что после нажатия кнопки загорается линейка из диодов красного цвета. Нормально. Затем я отпускаю кнопку и линейка из диодов красного цвета не тухнет сразу моментально , а по очереди один за другим диодов. Конечно для Вас это простое решение и видно в чём проблема, но я её пока не могу решить.
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@VictorArx, опять ЦМУ? ОК.
Ошибка возникает из-за того, что по логике выключения внутри цикла выключения первого цвета (красного, который strip1.Color(255, 0, 0)) попали 2 (причём вложенных) цикла выключения зелёного и синего. На эту ошибку Вам указал @Старик Похабыч, но Вы её не исправили. В результате, между отдельными итерациями цикла красного проходит 10 + 10*10 = 110 итераций вложенных циклов. При длительности чуть больше 5мс на итерацию это будет 550мс. Эту задержку Вы и видите. Т.е., Вы должны сделать три независимых блока проверки нажатия кнопок, а не зависимую проверку, тем более, вставленную в цикл.
У Вас также есть несоответствие между длинной массивов и define, которые Вы используете в цикле (led1==11, а в массиве NUMPIXELS1 у Вас 10 элементов; led2=10, в массиве NUMPIXELS2 - 9 элементов; с третьим массивом всё в порядке).
Кроме того, следуя Вашей логике, загорающиеся пиксели разного цвета не должны пересекаться. В Вашем случае, допустим, пиксели №3, 7, 8 присутствуют в нескольких массивах. Так как пиковые сигналы могут приходить одновременно, последний обрабатываемый сигнал будет затирать в этих пикселях предыдущие. Если цветовое отображение сигналов нужно миксовать, то нужно менять логику.
Если Вам не требуется зажигать светодиоды плавно, то стоит уйти от delay(5). При наличии 10 элементов в массиве больше 50 мс, которые тратятся на плавное зажигание светодиодов, никакие другие входы не проверяются, значит можно легко пропустить пиковое значение сигнала в другой полосе. Если требуется, то нужно переписать на millis. Оно вообще лучше переписать. Плюс заодно перейти на "события", поддержанные флагами.
 

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
@poty, дружище то что Вы написали поняли бы Старина Хотабыч или Эд или товарищ с Санкт Петербурга. Для меня это выше моих умственных способностей. Спасибо за желание помочь, но буду искать по немного в инете. Это точно цветомузыка на фильтрах. Она проверена все частоты и пиковые детекторы и даже тактовый генератор. Осталось сварганить код. Буду искать в инете. Я читаю книгу, что мне советовали по программированию. Я её не понимаю, хотя всё написано на русском языке. Может возраст даёт о себе знать, есть такое понятие : не моё это .
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@VictorArx, проще тогда просто попросить кого-нибудь причесать код. Этот код, по-факту, линейный и если наступить на горло правильному написанию, то всего-то и требуется, что перенести пару блоков:
Поправлено:
#include <Adafruit_NeoPixel.h>
#define Pin1      10              // подключение ленты светодиодов
#define Diody     60              // количество светодиодов
#define led1      20              // количество красных светодиодов
#define led2      20              // количество зелёных светодиодов
#define led3      20              // количество синих светодиодов

#define button1    4              // кнопка включения красного
#define button2    7              // кнопка включения зелёного
#define button3    8              // кнопка включения синего

#define DELON   5000              // мкс включения цвета попиксельно
#define DELOFF    10              // мкс выключения цвета попиксельно

// матрицы пикселей (плохая идея, напрасная трата памяти, либо нужно перенести в progmem)
int NUMPIXELS1[] { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 13, 16, 19, 22, 36, 39, 42, 45, 48 };
int NUMPIXELS2[] {11, 14, 17, 20, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 37, 40, 43, 46, 49 };
int NUMPIXELS3[] {12, 15, 18, 21, 24, 35, 38, 41, 44, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };

Adafruit_NeoPixel strip1(Diody, Pin1, NEO_GRB + NEO_KHZ800);

void setup() {
  strip1.begin();
  strip1.setBrightness(255);
  pinMode(4, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  // выключение матрицы
  strip1.fill(strip1.Color(0, 0, 0), 0, led1);
}

void loop() {
  if (digitalRead(4) == HIGH) {
    for (int i = 0; i < led1; i++) {
      strip1.setPixelColor(NUMPIXELS1[i], strip1.Color(255, 0, 0));
      strip1.show();
      delayMicroseconds(DELON);
    }
  } else {
    for (int i = 0; i < led1; i++)
      strip1.setPixelColor(NUMPIXELS1[i], strip1.Color(0, 0, 0));
    strip1.show();
  }
  if (digitalRead(7) == HIGH) {
    for (int i = 0; i < led2; i++) {
      strip1.setPixelColor(NUMPIXELS2[i], strip1.Color(0, 255, 0));
      strip1.show();
      delayMicroseconds(DELON);
    }
  } else {
    for (int i = 0; i < led2; i++)
      strip1.setPixelColor(NUMPIXELS2[i], strip1.Color(0, 0, 0));
    strip1.show();
  }
  if (digitalRead(8) == HIGH) {
    for (int i = 0; i < led3; i++) {
      strip1.setPixelColor(NUMPIXELS3[i], strip1.Color(0, 0, 255));
      strip1.show();
      delayMicroseconds(DELON);
    }
  } else {
    for (int i = 0; i < led3; i++)
      strip1.setPixelColor(NUMPIXELS3[i], strip1.Color(0, 0, 0));
    strip1.show();
  }
}
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Вместо того чтобы учится самому - раскрутил форум на готовый код...
А задачка-то элементарная была.
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@bort707, рано или поздно проблемы вылезут. И всё равно переписывать придётся. Против блокирующего кода не попрёшь.
 
  • Лойс +1
Реакции: bort707

poty

★★★★★★✩
19 Фев 2020
3,228
939
@VictorArx, поясню. Памяти у Вас, судя по коду - это Nano, всего 2кб. Каждый пиксель, при нормальной обработке, будет занимать 3 байта, соответственно, при, допустим, 250 пикселях, 750 байт из общего объёма будет изъято (по факту - больше, накладные расходы в библиотеке тоже немаленькие). Если будете распределять пиксели в массивах, то это займёт ещё 250 байт (а при Вашем объявлении элементов массива как int = 500 байт). Итого, больше половины памяти будет просто занята всяческими буферами. Если оставшейся части хватит - тогда работать будет, но приведённые мной цифры - довольно жёсткие ограничения.
Чем лучше заменить?... Ну, тут вариантов много. Один из них - сделать какой-либо алгоритм распределения, либо регулярный, либо псевдослучайный, который бы занимал только программную память по большей части. Ну не верю я, что Вы собираетесь какие-то сложные распределения пикселей делать.
Другой вариант, если уж никак не обойтись без сложных распределений... Можно упаковать необходимость зажигания пикселя определённым цветом в биты. Допустим, 250 пикселей вполне можно упаковать в 8 байт (для трёх цветов - 24 байта). Здесь, правда, я бы переписал ещё библиотеку вывода на ленту, так как буфер для всех 250 пикселей не потребуется, "цвета" можно формировать на лету. Но опасаюсь, что с таким объёмом Вы не справитесь, поэтому можно остановиться на упаковке в биты.
Ну, есть ещё ряд вариантов, нужно ли их озвучивать - не знаю...