Управляемая с кнопки светодиодная лента

Jensenaems

✩✩✩✩✩✩✩
7 Сен 2020
5
0
Добрый день! Занимаюсь своим первым проектом с ардуино и уже близок к завершению! Практически всё нормально работает, но есть одно "НО".
Решил сделать подсветку на кухню, чтобы была на ардуинке и можно было свои режимы какие хочешь вставлять и менять их с помощью кнопки по кругу. Всё спаял, всё работает, но периодически, когда пытаюсь поменять режимы нажатием на кнопку, то режим не меняется. То режимы быстро все меняются моментально реагируя на кнопку, то зависнет на каком-то. Эти "подтупливания" не позволяют нормально использовать кнопку и ленту. При этом код работает, но "тупит"...
Испытываю на фрагменте длиной в 18 светодиодов, а вообще будет штук 100. При этом, явно заметно, что при увеличении количества светодиодов "подтупливания" затягиваются гораздо сильнее. Проблема явно в коде и в моем слабом понимании его написания, но копания в интернете не помогли как минимум потому, что я даже приблизительно не понимаю в чем проблема. Прошу помощи.

C++:
#define BTN3 3   // кнопка подключена сюда (PIN --- КНОПКА --- GND)
#include "microLED.h"
#include "GyverButton.h"
#define ORDER_GRB
#define COLOR_DEBTH 2
#define NUMLEDS 18
#define LED_PIN 12
LEDdata leds[NUMLEDS];  // буфер ленты типа LEDdata (размер зависит от COLOR_DEBTH)
microLED strip(leds, NUMLEDS, LED_PIN);  // объект лента
GButton butt1(BTN3);
int value = 0;
byte counter;
int i = 0;
void setup() {
  Serial.begin(9600);
  pinMode(12, OUTPUT);
  butt1.setTickMode(AUTO);
  strip.setBrightness(255);    // яркость (0-255)
  strip.clear();   // очищает буфер
  strip.show(); // выводим изменения на ленту
}

void loop() {
  if (butt1.isClick()) {                  // одиночное нажатие
    value++;                              // инкремент
    Serial.println(value);                // для примера выведем в порт
    } 
    if (value == 0) {
      for (byte i = 0; i < NUMLEDS; i++) {  // Первая заливка белым светом
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 1){
          break;
        }
      }
    }
    if (value == 1) {                      // 1 клик
      for (byte i = 0; i < NUMLEDS; i++) {
      leds[i] = mHEX(0x0000ff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 2){
          break;
        }
      }
    }
    if (value == 2) {                     // 2 клика
        for (int i = 0; i < NUMLEDS; i++ ) {         // от 0 до первой трети
        leds[i] = mHSV(counter + i * 2, 255, 255);  // HSV. Увеличивать HUE (цвет)
        }
      counter++;        // counter меняется от 0 до 255 (тип данных byte)
      strip.show();
      delay(5);         // скорость движения радуги
    }
    if (value == 3) {
    value = 0;
    }
}
Когда дальше пытаюсь добавить ещё режим, то вообще зависает

C++:
    if (value == 3) {                      // 3 клик
  for (int i = 0; i < NUMLEDS / 2; i++ ) {   // от 0 до половины
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(5);         // скорость заполнения
        if (value == 4){
          break;
        }
  }
  for (int i = NUMLEDS; i == NUMLEDS, i > i/2; i-- ) {   // от конца до половины
      leds[i] = mHEX(0xfff000);             //
      strip.show();
      delay(5);         // скорость заполнения
        if (value == 4){
          break;
        }
      }   
    }
Также, буду признателен если у кого-то есть в "загашнике" ещё интересные режимы для ленты. Я смотрел Гаверовские проекты, но не смог в них разобраться даже близко...
 

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

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
А ты понимаешь, что выбрав режим 0 вот эта часть будет выполняться в каждом цикле loop . А пустой цикл крутиться до 200 000 раз в секунду.
C++:
if (value == 0) {
      for (byte i = 0; i < NUMLEDS; i++) {  // Первая заливка белым светом
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 1){
          break;
        }
      }
    }
Так вот если у тебя 100 светодиодов и задержка 10 мс, то в целом задержка будет 1 секунда на эффекте. Для переключения надо держать кнопку 1 секунду.
т.е. замедление работы составит 200 000 раз :D

И еще заметил. Вот этого
if (value == 1){
break;}
Никогда не произойдет.
А потом почему если 1 то прервать, а если 2 то нет ?
 
Изменено:
  • Ну такое -1
Реакции: Jensenaems

Jensenaems

✩✩✩✩✩✩✩
7 Сен 2020
5
0
А ты понимаешь, что выбрав режим 0 вот эта часть будет выполняться в каждом цикле loop . А пустой цикл крутиться до 200 000 раз в секунду.
C++:
if (value == 0) {
      for (byte i = 0; i < NUMLEDS; i++) {  // Первая заливка белым светом
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 1){
          break;
        }
      }
    }
Так вот если у тебя 100 светодиодов и задержка 10 мс, то в целом задержка будет 1 секунда на эффекте. Для переключения надо держать кнопку 1 секунду.
т.е. замедление работы составит 200 000 раз :D

И еще заметил. Вот этого
if (value == 1){
break;}
Никогда не произойдет.
А потом почему если 1 то прервать, а если 2 то нет ?
Собирал код из разных программ. Режим "0" срабатывает при включении контроллера. Логично, что при включении должен быть какой-то стартовый эффект. Стеб принят, но помощи никакой я не услышал.
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
Стеб принят, но помощи никакой я не услышал.
Вы не поняли, никакого стеба не было.
На самом деле @Старик Похабыч четко ответил на ваш вопрос, почему у вас кнопка переключения подтупливает.
Вам указали на причину ошибки - это не помощь?
 
  • Аррр! -2
Реакции: Jensenaems

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

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Основная МНЕ непонятная хрень туту:

C++:
for (byte i = 0; i < NUMLEDS; i++) {  // Первая заливка белым светом
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 1){
          break;
        }
После установки цвета КАЖДОГО светодиода делается задержка в 10 мс. Это эффект такой ? Похоже, что эффект, т.к. после установки делается strip.show();

Если же это сделано по незнанию, то 1) убрать задержку, 2) strip.show(); делать после установки цвета ВСЕХ светодиодов. 3) if (value == 1) break; убрать совсем, 4) добавить логическую переменную о том, что при value ==0 уже сделана установка цвета всех светодиодов. 5) в начале блока сделать проверки установки всех светодиодов.
Для начала можно ограничится первыми 3-мя пунктами. Но при этом при значении value==0 будет всегда вход в эту часть и новая установка всех светодиодов, несмотря на то, что они уже установлены. А это задержка кода.
Тоже самое для всех эффектов.
Если же это эффект, то надо сделать так, что бы устанавливался 1 светодиод и выходить из блока. в сл. раз надо установить уже сл. светодиод. что то типа
все светодиоды установлены ?
если да то выход
если нет то:
10 миллисекунд прошло ?
если нет, то выход
если да то:
Запомнить время
Установить светодиод N
увеличить N на 1.
Если это последний светодиод, то выставить флаг, что все светодиоды установлены.
выход из блока
 
  • Лойс +1
Реакции: b707_2

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
@Старик Похабыч, а мне больше всего непонятен другой цикл, см ниже

@Jensenaems, чтоб ты так не бесился. могу тебе другие ошибки подсказать
Когда дальше пытаюсь добавить ещё режим, то вообще зависает
C++:
for (int i = NUMLEDS; i == NUMLEDS, i > i/2; i-- ) {   // от конца до половины
      leds[i] = mHEX(0xfff000);
условие цикла for в первой строке - это просто "что-то с чем-то". Ты явно запутался, сравнивать i нужно не c i/2. а c NUMLEDS/2
а зависает оно потому, что ты начинаешь цикл с присваивания i = NUMLEDS, а потом
C++:
      leds[i] = mHEX(0xfff000);
А теперь подумай, как считаются индексы в массивах в языке Си и найди ошибку
 

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

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
А я дальше смотреть не стал если честно. Но условие да. Причем по логике i будет всегда больше i/2, кроме как если i рано 0 , тогда i будет равно i/2. Тогда почему бы не написать просто i>0 ?

Автору предлагаю этот кусок вообще забрать в комментарии, что бы разобраться с ним потом.
ЗЫ. Половина будет NUMLEDS/2. Ну и последнюю строку
А теперь подумай, как считаются индексы в массивах в языке Си и найди ошибку
не игнорируйте ни в коем случае!
 

Jensenaems

✩✩✩✩✩✩✩
7 Сен 2020
5
0
Основная МНЕ непонятная хрень туту:

C++:
for (byte i = 0; i < NUMLEDS; i++) {  // Первая заливка белым светом
      leds[i] = mHEX(0xffffff);             // белый
      strip.show();
      delay(10);         // скорость заполнения
        if (value == 1){
          break;
        }
После установки цвета КАЖДОГО светодиода делается задержка в 10 мс. Это эффект такой ? Похоже, что эффект, т.к. после установки делается strip.show();

Это эффект такой. После включения каждого светодиода на ленте происходит задержка в 10 мс. Лента постепенно зажигается полностью.
Не совсем понял зачем нужно делать внутри цикла проверку на выполнение условия прохождения 10мс если её можно просто задать, как сделано у меня? Если я правильно понял, то в результате цикл прервется тоже ровно тогда, когда вся лента заполнится, т.е. когда вся задержка будет выдержана.
Может есть способ прервать цикл, когда нажимается кнопка в следующий раз, сделать чтобы вне зависимости от этапа выполнения цикла он прерывался и начинался следующий цикл?
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
@Jensenaems, цитируй сообщения правильно, чтобы твой ответ не попадал в цитирование, а то тебе даже ответить нельзя
В предыдущем своем сообщении нажми "Изменить", найди в конце слово QUOTE в кавадратных скобках и перенеси его выше своего ответа

Jensenaems написал(а):
Не совсем понял зачем нужно делать внутри цикла проверку на выполнение условия прохождения 10мс если её можно просто задать, как сделано у меня?
Ты не понял, задержку надо делать не внутри цикла. а снаружи. читай Похабыча внимательно
 
Изменено:

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

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Проверка нужна для того, что бы не делать задержку. Я внизу полностью расписал алгоритм этого эффекта без цикла for и задержки. Любая 10мс которые тратятся на задержку не обрабатывают кнопку. А вы то сказали , что поняли то, что я написал.
 

Jensenaems

✩✩✩✩✩✩✩
7 Сен 2020
5
0
Я не говорил, что я понял, то, что я написал. Я сказа "если я правильно понял". И было бы проще понять, если бы ты знаками препинания пользовался. В любом случае мне уже на другом форуме подсказали как сделать всё на таймерах и у меня всё заработало. Так что спасибо за помощь...