Функция светодиодного фейдера зависает и перестает реагировать после нескольких циклов
У моего светодиодного контроллера есть режим изменения цвета, который я создаю. Функция контроллера loop() захватывает входящие последовательные данные, чтобы установить количество цветов, скорость затухания, режим и другую информацию, а затем запускает правильный режим с цветами, которые она считывает из последовательного порта
В режиме изменения цвета контроллер «зависает» на определенном цвете и перестает реагировать на ввод данных до тех пор, пока я не отключу его и снова не включу или не загружу код повторно (последнее означает, что он по-прежнему на что-то реагирует).
В целях тестирования я использую красный, зеленый и синий цвета в указанном порядке. Этот остановившийся цвет может произойти где угодно: от середины перехода от красного к зеленому в первом цикле до прохождения нескольких циклов и остановки на синем в зависимости от скорости затухания. Это стало проблемой только после того, как я переключился с использования delay() на millis(). Почему это так и что я могу сделать, чтобы это исправить?
Причина, по которой я перешел на использование миллиса, заключается в том, что задержки будут складываться бесконечно, и Arduino перестанет реагировать на команды
Вот мой соответствующий код:
#include <Adafruit_DotStar.h>
#include <SPI.h>
#define NUMPIXELS 60
#define DATAPIN 4
#define CLOCKPIN 5
Adafruit_DotStar strip(NUMPIXELS, DOTSTAR_BRG);
// Переменные
int mode;
int numColors;
int fadeSpeed;
int BBCC;
int R[100];
int G[100];
int B[100];
int Bright[100];
int currColor;
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1); // Включить 16 МГц на Trinket
#endif
strip.begin(); // Инициализируем выводы для вывода
strip.show(); // Выключить все светодиоды как можно скорее
currColor = 0;
}
void loop() {
strip.show(); // Обновить полосу
delay(20); // Пауза 20 миллисекунд (~50 FPS)
getData();
switch (mode)
{
case 1: // Режим 1: Сплошной цвет
{
for (int i = 0; i < NUMPIXELS; i++)
{
if (i % 2 == 0)
strip.setPixelColor(i, G[0], R[0], B[0]);// Устанавливает для всей полосы цвет 1
}
strip.setBrightness(Bright[0]);
strip.show();
break;
}
case 2: // Режим 2: Многоцветный фейдер
{
colorFade();
break;
}
case 3: // Режим 3: Многоцветный шаблон
{
int j = 0;
for (int i = 0; i < NUMPIXELS; i++)
{
if (i % 2 == 0)
{
strip.setPixelColor(i, G[j], R[j], B[j]); // устанавливает повторяющийся шаблон
if (j == (numColors - 1))
j = 0;
else
j++;
}
}
strip.setBrightness(Bright[0]);
strip.show();
break;
}
case 4: // Mode 4: Music-Reactive Wave Form
{
break;
}
case 5: // Mode 5: Music-Reactive Color Jump
{
break;
}
default: // Режим по умолчанию: Симуляция накаливания
{
for (int i = 0; i < NUMPIXELS; i++)
{
if (i % 2 == 0)
strip.setPixelColor(i, 150, 200, 40); // Устанавливает для всей полосы значение по умолчанию
}
strip.setBrightness(255);
strip.show();
break;
}
}
}
void colorFade()
{
int del = 100; // 100 миллисекунд
if (currColor >= numColors - 1)
{
int steps = fadeSpeed * del;
int Rdiff, Gdiff, Bdiff, BrightDiff;
Rdiff = R[0] - R[currColor];
Gdiff = G[0] - G[currColor];
Bdiff = B[0] - B[currColor];
BrightDiff = Bright[0] - Bright[currColor];
for (int i = 0; i <= steps + 5; i++)
{
for (int j = 0; j < NUMPIXELS; j++)
{
if (j % 2 == 0)
strip.setPixelColor(j, (G[currColor] - (Gdiff * i)), (R[currColor] - (Rdiff * i)), (B[currColor] - (Bdiff * i))); // Устанавливает всю полосу в значение
}
//strip.setBrightness((Bright[currColor] - (BrightDiff * i)));
strip.show();
// задержка (удаление);
int timer = millis() + del;
while(millis() < timer)
{
}
}
currColor = 0;
}
else
{
int steps = fadeSpeed * del;
int Rdiff, Gdiff, Bdiff, BrightDiff;
Rdiff = R[currColor + 1] - R[currColor];
Gdiff = G[currColor + 1] - G[currColor];
Bdiff = B[currColor + 1] - B[currColor];
BrightDiff = Bright[currColor + 1] - Bright[currColor];
for (int i = 0; i <= steps + 5; i++)
{
for (int j = 0; j < NUMPIXELS; j++)
{
if (j % 2 == 0)
strip.setPixelColor(j, (G[currColor] - (Gdiff * i)), (R[currColor] - (Rdiff * i)), (B[currColor] - (Bdiff * i))); // Устанавливает всю полосу в значение
}
//strip.setBrightness((Bright[currColor] - (BrightDiff * i)));
strip.show();
// задержка (удаление);
int timer = millis() + del;
while(millis() < timer)
{
}
}
currColor++;
}
}
@BoatHouse, 👍0
Обсуждение1 ответ
Лучший ответ:
Проблема с приведенным выше кодом связана с переполнением. timer должен быть unsigned long, потому что millis() выводит unsigned long. Это вызывает зависание, потому что после того, как таймер достигает своего верхнего предела, эта настройка работает лучше:
unsigned long timer = (unsigned long)millis() + del;
while((unsigned long)millis() < timer)
{
//ждем пока del скажет
}
Эта установка должна работать в течение длительного времени без переполнения
- Библиотека FastLED: Как настроить яркость одного пикселя в абсолютном масштабе?
- Адресная RGB-полоса работает по отдельности, но не может настроить все светодиоды на полностью белый цвет.
- FastLED fill_rainbow - Неожиданный красный пиксель
- Как читать текстовый файл построчно
- Быстродействующий массив fill_solid
- Управление светодиодной лентой с помощью ИК-контроллера с помощью Arduino
- Что сделать, чтобы увеличить количество светодиодов, которые можно запитать с помощью pro micro?
- RGB светодиодная лента 100м.
начните отладку, запустив только выбор затухания... предустановленный режим до 2.... закомментируйте
getData();
в цикле(), @jsotolaкак мне отладить это в arduino IDE? Я не могу найти команду для точек останова, и я не знаю, что мне нужно было бы посмотреть, если бы я использовал serial.println() для чтения значений, @BoatHouse
В обычной встроенной прошивке нет отладки в смысле программирования WRT Arduino. Именно поэтому нужно начинать с малого и не добавлять ничего более сложного, пока мелочь не заработает., @st2000
это не "Arduino" ... это "C++" .... вставьте
mode = 2;
в setup() ... заменитеgetData();
на// getData();
, @jsotolaПосмотрев в другом месте, вы можете отладить arduino, отправив что-то на последовательный монитор через Serial.println(). Было бы полезно упомянуть об этом, так как я мог проверить значения таймера и millis() с помощью этой команды. timer переполнялся из-за типа данных int, и millis() в конечном итоге переворачивался и останавливался на верхнем пределе. Это было причиной проблемы, @BoatHouse
@BoatHouse Пожалуйста, напишите ответ на свой вопрос, чтобы другие могли извлечь из этого пользу. Спасибо, @chrisl