Постепенно включать RGB led
Почему я не могу использовать "timeA = delay", чтобы свет включался постепенно. Проблема в том, что задержка не работает, и светодиодный индикатор переходит непосредственно к последнему цвету. Что мне нужно сделать в своем коде, чтобы исправить это?
Вот мой код ↓
// C++ code
//
void setup()
{
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop(){
static unsigned long timeA = 10;
const long interval = 10;
static unsigned long timeB = 10;
const long interval2 = 10;
static unsigned long timeC = 10;
const long interval3 = 10;
unsigned long delay = millis();
static unsigned long state = 0;
int i = 0;
if(delay - timeA >= interval && state == 0){
state += 1;
for(i=0;i<=255;i++){
analogWrite(3, i);
analogWrite(5, 0);
analogWrite(6, 0);
timeA = delay;
}
}
if(delay - timeB >= interval2 && state == 1){
state += 1;
for(i=0;i<=255;i++){
analogWrite(3, 0);
analogWrite(5, i);
analogWrite(6, 0);
timeB = delay;
}
}
if(delay - timeC >= interval3 && state == 2){
state += 1;
for(i=0;i<=255;i++){
analogWrite(3, 0);
analogWrite(5, 0);
analogWrite(6, i);
timeC = delay;
}
}
}
@Ian Rapini, 👍1
2 ответа
Я думаю, что ниже приведено то, к чему вы стремились. Я удалил цикл for и использовал статическую переменную i, чтобы каждое состояние занимало 256 интервалов. Обратите внимание, что вам не нужно иметь отдельные переменные timeA/B/C. Использование одного из них также гарантирует, что первая "задержка" действительно произойдет. Это не так уж критично для выцветания светодиода, но в других случаях это возможно.
void setup()
{
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop(){
static unsigned long timeA = 10;
const long interval = 10;
static unsigned long timeB = 10;
const long interval2 = 10;
static unsigned long timeC = 10;
const long interval3 = 10;
static unsigned long state = 0;
static int i = 0;
unsigned long delay = millis();
if(delay - timeA >= interval && state == 0){
analogWrite(3, i);
analogWrite(5, 0);
analogWrite(6, 0);
timeA = delay;
i++;
if( i==256 )
{
i=0;
state++;
}
}
if(delay - timeB >= interval2 && state == 1){
analogWrite(3, 0);
analogWrite(5, i);
analogWrite(6, 0);
timeB = delay;
i++;
if( i==256 )
{
i=0;
state++;
}
}
if(delay - timeC >= interval3 && state == 2){
analogWrite(3, 0);
analogWrite(5, 0);
analogWrite(6, i);
timeC = delay;
i++;
if( i==256 )
{
i=0;
state++; // вы, вероятно, хотите использовать `state=0;`, поэтому все начинается сначала
}
}
}```
Ваш код millis()
структурирован неправильно. Давайте посмотрим, что происходит:
timeA
и co инициируются со значением 10. Таким образом, как только программа пробежит 10 мс, будет выполнен первый оператор if (тот, что для состояния 0). Сначала вы увеличиваете состояние
, чтобы можно было достичь следующего состояния. Тогда у вас есть цикл for без какого-либо временного кода. Он будет выполняться очень быстро, не давая аппаратному обеспечению PWM возможности фактически выводить значения analogWrite ()
. Затем вы обновляете timeA
(который обычно не входит в цикл for). Мы оставляем оператор if и переходим к следующему. Почти не прошло времени с тех пор, как мы ввели первый оператор if. И теперь мы выполняем следующий оператор if, так как состояние
теперь равно 1, а программа работала более 10 мс. Здесь то же самое, что и выше.
Таким образом, программа мчится через вызовы analogWrite ()
, заканчивающиеся последним, так как состояние
никогда не сбрасывается, давая последнему значению analogWrite()
изменение, которое будет выведено на вывод.
Вся структура кода на самом деле не имеет смысла. Я предполагаю, что вы хотели сделать это неблокирующим, таким образом, используя millis()
. Циклы For на самом деле не соответствуют этому, и значение millis()
должно быть сравнено с правильными значениями, чтобы получить правильный порядок.
Что теперь делать: с переменной состояния
у вас почти есть то, что называется конечным автоматом (FSM). Это мощная концепция программирования. В основном состояние программы решает, какой блок кода должен выполняться на каждой итерации цикла ()
. Лучше всего это сделать с помощью оператора switch. Затем в каждом случае мы используем оператор if, использующий значение millis ()
, чтобы решить, пришло ли время выполнить новую analogWrite()
:
void setup()
{
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop(){
static unsigned long timeA = 10;
const long interval = 10;
static unsigned long timeB = 10;
const long interval2 = 10;
static unsigned long timeC = 10;
const long interval3 = 10;
unsigned long delay = millis();
static unsigned long state = 0;
static int i = 0;
switch(state){
case 0:
if(delay - timeA >= interval){
analogWrite(3, i);
analogWrite(5, 0);
analogWrite(6, 0);
i++;
timeA = delay;
}
if(i > 255){
state = 1;
i = 0;
}
break;
case 1:
if(delay - timeB >= interval2){
analogWrite(3, 0);
analogWrite(5, i);
analogWrite(6, 0);
i++;
timeB = delay;
}
if(i > 255){
state = 2;
i = 0;
}
break;
case 2:
if(delay - timeC >= interval3){
analogWrite(3, 0);
analogWrite(5, 0);
analogWrite(6, i);
i++;
timeC = delay;
}
if(i > 255){
state = 0;
i = 0;
}
break;
}
}
Установив переменную state
, мы можем выбрать, что должно быть выполнено дальше. Переменная i
обрабатывает затухание каждого светодиода, в то время как интервальные
переменные устанавливают скорость затухания. Этот принцип кодирования может быть использован в самых разных ситуациях, так что изучение его действительно стоит того.
Примечание:
- Я не тестировал приведенный выше код.
- Код все еще может быть оптимизирован/обобщен.
Спасибо тебе, братан! Но еще одно сомнение: не могу ли я использовать "для" в этом случае? Потому что это работа в колледже, которую мне нужно использовать., @Ian Rapini
Если вы используете цикл for
, вам также нужно будет использовать " delay ()", чтобы создать правильное время затухания. Я предположил, что вы не хотите использовать delay()
(что хорошо для добавления дополнительных функций в будущем). циклы for
- это всего лишь один из способов создания циклов. Есть и другие, и вышеприведенный принцип кода также должен работать. Это зависит от вас, хотите ли вы использовать " for "(и, следовательно, " delay ()", создавая блокирующий код) или вышеприведенную структуру кода (и, следовательно, неблокирующий код)., @chrisl
- Улучшенное циклическое переключение цветов RGB.
- Библиотека FastLED: Как настроить яркость одного пикселя в абсолютном масштабе?
- Управление цифровой адресной светодиодной лентой RGB 12 В с помощью Arduino
- Как управлять встроенными светодиодами Arduino Nano 33 BLE Sense?
- Адресная RGB-полоса работает по отдельности, но не может настроить все светодиоды на полностью белый цвет.
- Как изменить яркость светодиодного освещения?
- Нужна помощь в подключении светодиодной матрицы 64х32.
- Моргнуть всей светодиодной лентой
Спасибо! Но у меня все еще есть сомнения, могу ли я использовать "для", потому что это работа в колледже, и мне нужно ее использовать., @Ian Rapini