Прошу помощи по WS2812 и циклу for

Roman66683

✩✩✩✩✩✩✩
7 Июл 2022
4
0
Всем привет. Я программист 0 уровня, могу только повторять проекты.
Решил попробовать сделать сыну ночник из одного светодиода WS2812. Получилось, но не до конца правильно. Первых 3 режима отрабатывает нормально, а на 4 режиме (mode 3) после захода в цикл перестает реагировать кнопка и этот режим становится вечным. Пересмотрел кучу примеров, не помогло.
Пробовал переделать эту конструкцию на миллис, но не хватает знаний.
Помогите пожалуйста поправить код до рабочего или переписать эту конструкцию на миллис!
Nochnik:
//mAqua mYellow mRed mBlue mGreen mGray mWhite mSilver
//mMaroon mOrange mOlive mLime mTeal mNavy mMagenta mPurple

#define STRIP_PIN 3     // пин ленты
#define NUMLEDS 1      // кол-во светодиодов

#include <microLED.h>   // подключаем библу

microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2812, ORDER_GRB> strip;
//--------------------------кнопка-----------------------------
#include <EncButton.h>
EncButton<EB_TICK, 9> btn;
//---------------------------------------------------------------
int mode = 0 ;

void setup() {

  strip.setBrightness(100); // (0-255)
  strip.clear();  // .show() !
  strip.show(); // вывод
  delay(1);     // минимум 40 мкс




}
void loop() {
  btn.tick();
  if (btn.click()) {
    mode++;
  }
  if (mode > 3) {
    mode = 0;
  }
  if (mode == 0) {
    strip.set(0, mHEX(0xFF00FF));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 1) {
    strip.set(0, mHEX(0x00FF00));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 2) {
    strip.set(0, mHEX(0xFFFFFF));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 3) {
    for (uint8_t j = 0; j < 255; j = j + 40) {
      btn.tick();
      for (int i = 0; i < 255; i++) {
        strip.set(0, mWheel8(j, i));
        strip.show();
        delay(20);
      }
      for (int i = 255; i > 0; i--) {
        strip.set(0, mWheel8(j, i));
        strip.show();
        delay(10);
      }
    }
  }
}
 

Сотнег

★★★★★★★
15 Янв 2020
4,446
1,520
@Roman66683,
по задумке инженеров, функция loop() должна запускаться как можно чаще, и не реже, чем раз в 8 секунд.
Соответственно строчка
strip.show();
нужна в единственном экземпляре где-то в конце loop().
То есть никакие циклы for, содержащие delay и тормозящие работу loop(), применяться не должны.

Но вы можете вставить в свои for функцию, сообщающую контроллеру, что ваша программа не зависла, просто сделана через опу.
Погуглите watchdog arduino.

И, если вы хотите, чтобы ещё и кнопка работала, вместе с watchdog.reset нужно и кнопку опрашивать так же часто.
 
Изменено:

viktor1703

★★★✩✩✩✩
9 Дек 2021
631
150
Вот в этом месте
C++:
for (uint8_t j = 0; j < 255; j = j + 40)
и должно быть зависание, так как j=0, j+40=40; +40=80; +40=120;+40=...240; +40=25 это < чем 255. А теперь посчитай через какое время выпадет число большее, чем 255, при условии, что после 255 происходит займ переполнение и счёт начинается с нуля. И это всегда будет удовлетворять условие j<255. Определи сколько раз нужно повторить цикл и просто инкрементируй переменную j (j++) Например, 255 повторений
C++:
for (uint8_t j = 0; j <= 254; j++)
Но, наверно, удобнее использовать декрементирование переменной. 10 повторений
C++:
for (uint8_t j = 10; j > 0; j --)
 
Изменено:
  • Аррр! -2
Реакции: Xeybi

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

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
Вот тут для примера я избавился от цикла j.
Но этого не достаточно. Считайте сами:
Цикл в одну сторону от 0 до 255 с задержкой delay(20) и обратно с задержкой 10 это будет 7680 мс. Т.е. больше 7,5 секунд. Далее будет опрос кнопки, который займет .. 1/200 000 секунды, и опять пауза в 7,5 секунд. Ни одна кнопка не сработает в таком формате.
Что надо сделать
1) надо избавиться еще от циклов i
Для этого надо объявить 2 статические переменные i и f
i это будет такой же счетчик как и был, полная аналогия j
f это будет флаг смены направления счета i, в начале пусть будет true
j так и оставляем.
в начале имеем (повтор) i=0 ; f=true;
сначала просто рисуем ленту:
strip.set(0, mWheel8(j, i));
strip.show();
а потом делаем в зависимости от f
if (f)
{
if (i==255) f=!f; // если дошли до максимума , то меняем направление движения
else i++; // иначе увеличить i
delay(20) // это не много, можно и оставить.
}
else
{
if (i==0) f=!f; // если дошли до минимума , то меняем направление движения
else i--; // иначе увеличить i
delay(10) // это не много, можно и оставить.
}
в принципе вот так должно адекватно реагировать на кнопку .

Кстати да, вы поместили опрос кнопки в цикл, но мало. Как вариант (попробуйте сразу и отпишитесь) поместить опрос кнопки в оба цикла i - может сработать.

C++:
//mAqua mYellow mRed mBlue mGreen mGray mWhite mSilver
//mMaroon mOrange mOlive mLime mTeal mNavy mMagenta mPurple

#define STRIP_PIN 3     // пин ленты
#define NUMLEDS 1      // кол-во светодиодов

#include <microLED.h>   // подключаем библу

microLED<NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2812, ORDER_GRB> strip;
//--------------------------кнопка-----------------------------
#include <EncButton.h>
EncButton<EB_TICK, 9> btn;
//---------------------------------------------------------------
int mode = 0 ;

void setup() {

  strip.setBrightness(100); // (0-255)
  strip.clear();  // .show() !
  strip.show(); // вывод
  delay(1);     // минимум 40 мкс




}
void loop() {
  btn.tick();
  if (btn.click()) {
    mode++;
  }
  if (mode > 3) {
    mode = 0;
  }
  if (mode == 0) {
    strip.set(0, mHEX(0xFF00FF));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 1) {
    strip.set(0, mHEX(0x00FF00));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 2) {
    strip.set(0, mHEX(0xFFFFFF));
    strip.show(); // вывод изменений на ленту
    delay(1);
  }
  if (mode == 3) {
    static uint8_t j = 0;
    {
      for (int i = 0; i < 255; i++) {
        strip.set(0, mWheel8(j, i));
        strip.show();
        delay(20);
      }
      for (int i = 255; i > 0; i--) {
        strip.set(0, mWheel8(j, i));
        strip.show();
        delay(10);
      }
      j = j + 40;
    }
  }
}
 

Roman66683

✩✩✩✩✩✩✩
7 Июл 2022
4
0
Спасибо, все получилось!
Добавил только опрос кнопки в каждый цикл и и break по клику, а то не с первого раза кнопка срабатывала.
Вечером попробую на счетчиках как вы описали выше.
код:
static uint8_t j = 0;
    {
      for (int i = 0; i < 255; i++) {
        btn.tick();
        strip.set(0, mWheel8(j, i));
        strip.show();
        if (btn.tick())break;
        delay(20);
      }
      for (int i = 255; i > 0; i--) {
        btn.tick();
        strip.set(0, mWheel8(j, i));
        strip.show();
        if (btn.tick())break;
        delay(10);
      }
      j = j + 40;
    }
 
Изменено: