Включение светодиодных лент последовательно

Опытные пользователи, данного форума, отправили с моим вопросом в этот раздел форума.
С ардуино только начинается знакомство и моих знаний не хватает, чтобы понять что нужно изменить и добавить в ранее выложенном, пользователе Andycat ( Fade. Плавное разгорание и затухание светодиода. (analogWrite, PWM/ШИМ) - #2 от пользователя andycat ), коде плавного разгорания и затухания двух светодиодных лент.
Нужно сделать плавное включение и выключение лент не друг за другом, а включение и выключение второй ленты на середине яркости первой ленты.

Подскажите пожалуйста, что нужно подправить в этом коде.

static constexpr unsigned char pin_PWM_1out = 9; // Nano PB1 OC1A // пин 9 подключения драйвера светодиодной ленты 1
static constexpr unsigned char pin_PWM_2out = 11; // Nano PB3 OC2A // пин 11 подключения драйвера светодиодной ленты 2

static constexpr unsigned long stepChange = 10; // период изменения яркости, миллисекунд, фактически скорость повышения/понижения яркости, чем меньше число - тем быстрее
static constexpr unsigned long periodWait = 10000; // время ожидания движения при максимальной яркости лент, миллисекунд

enum tStatusWork { lStart = 0 /*начало*/, lToUP /*повышение яркости*/, 
	lToDOWN /*понижение яркости*/, lWaitMove /*ожидание движения при макс.яркости*/ }; // режимы работы

void setPWMout(unsigned char out1 /*яркость ленты 1*/, unsigned char out2 /*яркость ленты 2*/) { // функция установки яркости лент
	analogWrite(pin_PWM_1out, out1); // установца ШИМ ленты 1
	analogWrite(pin_PWM_2out, out2); // установца ШИМ ленты 2
}

void initPins(void) { // начальная инициализации пина датчика движения
	pinMode(pin_RIP_in, INPUT); // режим пина - вход (по умолчанию, при включении МК, все пины и так в режиме входа)
	digitalWrite(pin_RIP_in, LOW); // отключаем подтягивающий резистор (по умолчанию он и так отключен)
}

unsigned char readRIP(void) { // чтение пина датчика движения
	static unsigned char lastLevel = 0; // хранение предыдущего значения пина - нет движения
	unsigned char currLevel = digitalRead(pin_RIP_in); // читаем текущее состояние пина
	if (currLevel != lastLevel) { // если прочитанное состояние пина не равно предыдущему
		Serial.println(currLevel); // выведем в монитор порта (для отладки) текущее значение пина
		digitalWrite(LED_BUILTIN, currLevel); // установим встроенный светодиод МК в состояние пина датчика движенния (удобно при отладке на реальном устройстве - видно работает датчик движения или нет)
		lastLevel = currLevel; // присваиваем предыдущему значению пина текущее
	}
	return currLevel; // функция возвращает текущее значение пина датчика движения HC-SR501
}

// the setup function runs once when you press reset or power the board
void setup() { // стартовая функция при включении или сбросе МК
	Serial.begin(115200); // инициализируем HW UART МК
	pinMode(LED_BUILTIN, OUTPUT); // установка режима пина встроенного МК - выход
	initPins(); // инициализируем пин датчика движения
	setPWMout(0, 0); // гасим обе ленты
}

void workKitchenL(void) { // основная рабочая функция
	static tStatusWork currentMode = lStart; // храним текущее значение режима работы
	static unsigned char pwm1 = 0, pwm2 = 0; // текущая яркость лент
	static unsigned long timerLastChange = 0; // таймер изменения яркости
	static unsigned long timerWaitMove = 0; // таймер ожидания движения при максимальной яркости
	switch (currentMode) { // работаем с логикой в зависимости от текущего режима
		case lToUP: { // режим повышение ярккости
			if ((millis() - timerLastChange) >= stepChange) { // если прошел шаг изменения яркости
				timerLastChange = millis(); // обновим таймер изменения яркости
				if (pwm1 < 255) { // если яркость первой ленты меньше максимальной
					++pwm1; // увеличиваем яркость первой ленты
				} else { // если яркость первой ленты максимальная - начинаем увеличивать яркость второй ленты
					if (pwm2 < 255) { // если яркость второй ленты меньше максимальной
						++pwm2; // увеличиваем яркость второй ленты
					} else { // если яркость второй ленты максимальная
						timerWaitMove = millis(); // обновляем таймер ожидания движения при максимальной яркости
						currentMode = lWaitMove; // переходим в режим ожидания движения при максимальной яркости
					}
				}
				setPWMout(pwm1, pwm2); // устанавливаем яркость лент
			}
			break;
		}
		case lToDOWN: { // режим понижения аркости
			if (readRIP()) { // если есть движенние
				currentMode = lToUP; // переходим в режим повышения аркости
			} else { // если нет движения
				if ((millis() - timerLastChange) >= stepChange) { // если прошел шаг изменения яркости
					timerLastChange = millis(); // обновим таймер изменения яркости
					if (pwm2) { // если яркость второй ленты больше нуля
						--pwm2; // уменьшаем яркость второй ленты
					} else { // если вторя лента не светится
						if (pwm1) { // если яркость первой ленты больше нуля
							--pwm1; // уменьшаем яркость первой ленты
						} else { // если первая лента не светится
							currentMode = lStart; // переходим в начальный режим
						}
					}
					setPWMout(pwm1, pwm2); // устанавливаем яркость лент
				}
			}
			break;
		}
		case lWaitMove: { // режим ожидания движения при максимальной яркости лент
			if (readRIP()) { // если есть движение
				timerWaitMove = millis(); // обновляем таймер ожидания
			} else { // если нет движения
				if ((millis() - timerWaitMove) >= periodWait) currentMode = lToDOWN; // если вышло время ожидания движения - переходим в режим уменьшения яркости лент
			}
			break;
		}
		default: { // lStart // начальный режим
			if (readRIP()) { // если произошло движение
				currentMode = lToUP; // переходим в режим повышения яркости лент
			}
		}
	}
}

// the loop function runs over and over again until power down or reset
void loop() { // бесконечный цикл
	workKitchenL(); // работаем
}

Не, не так, отправили учить хоть немножко учебник, алгоритмы, разобраться с текущим кодом, хоть что то попытаться исправить.
Вы нашли место где идёт повышение яркости первой ленты и условие что происходит когда яркость максимум?
Дальше догадаетесь какое условие добавить?
ЗЫ. Ну реально, если совсем плохо с программированием, начните с чего попроще, все мы начинали с минимума.

@2913090 , если нужно как в названии темы - именно последовательно, то дождаться завершения цикла одной ленты, после чего точно так же запускать вторую.

Мне предложили создать тему для новичков и там спросить.

С вашим кодом я разбирался как мог, не занимаясь до этого програмированием, паралельно изучая язык програмирования в других примерах и переделал его практически под свою задачу.

Не хотел просто развернуто описывать, что мне в общем нужно, но видимо стоит это сделать.

Задача состоит в том чтобы сделать подсветку шести реек. Алгоритм должен быть такой:
Рейки должны постоянно светиться. При подходе к светящимся рейкам, подсветка каждой постепенно гаснет и через некоторое время плавно разгорается снова. И потом не реагирует на датчик движения какое-то время.

Код получился такой, может немного и криво, но логика как мне нужна.

static constexpr unsigned char pin_RIP_in = 4; // Nano D5 // пин 4 подключения датчика движения HC-SR501
static constexpr unsigned char pin_PWM_1out = 9; // Nano PB1 OC1A // пин 9 подключения драйвера светодиодной ленты 1
static constexpr unsigned char pin_PWM_2out = 11; // Nano PB3 OC2A // пин 11 подключения драйвера светодиодной ленты 2
static constexpr unsigned char pin_PWM_3out = 10; // Nano PB2 OC3A // пин 10 подключения драйвера светодиодной ленты 3
static constexpr unsigned char pin_PWM_4out = 6; // Nano PD6 OC4A // пин 6 подключения драйвера светодиодной ленты 4

static constexpr unsigned long stepChange = 10; // период изменения яркости, миллисекунд, фактически скорость повышения/понижения яркости, чем меньше число - тем быстрее
static constexpr unsigned long periodWait = 10000; // время ожидания движения при максимальной яркости лент, миллисекунд

enum tStatusWork { lStart = 0 /*начало*/, lToUP /*повышение яркости*/, 
	lToDOWN /*понижение яркости*/, lWaitMove /*ожидание движения при макс.яркости*/ }; // режимы работы

void setPWMout(unsigned char out1 /*яркость ленты 1*/, unsigned char out2 /*яркость ленты 2*/, unsigned char out3 /*яркость ленты 3*/, unsigned char out4 /*яркость ленты 4*/) { // функция установки яркости лент
	analogWrite(pin_PWM_1out, out1); // установца ШИМ ленты 1
	analogWrite(pin_PWM_2out, out2); // установца ШИМ ленты 2
        analogWrite(pin_PWM_3out, out3); // установца ШИМ ленты 3
        analogWrite(pin_PWM_4out, out4); // установца ШИМ ленты 4
}

void initPins(void) { // начальная инициализации пина датчика движения
	pinMode(pin_RIP_in, INPUT); // режим пина - вход (по умолчанию, при включении МК, все пины и так в режиме входа)
	digitalWrite(pin_RIP_in, LOW); // отключаем подтягивающий резистор (по умолчанию он и так отключен)
}

unsigned char readRIP(void) { // чтение пина датчика движения
	static unsigned char lastLevel = 0; // хранение предыдущего значения пина - нет движения
	unsigned char currLevel = digitalRead(pin_RIP_in); // читаем текущее состояние пина
	if (currLevel != lastLevel) { // если прочитанное состояние пина не равно предыдущему
		Serial.println(currLevel); // выведем в монитор порта (для отладки) текущее значение пина
		digitalWrite(LED_BUILTIN, currLevel); // установим встроенный светодиод МК в состояние пина датчика движенния (удобно при отладке на реальном устройстве - видно работает датчик движения или нет)
		lastLevel = currLevel; // присваиваем предыдущему значению пина текущее
	}
	return currLevel; // функция возвращает текущее значение пина датчика движения HC-SR501
}

// the setup function runs once when you press reset or power the board
void setup() { // стартовая функция при включении или сбросе МК
	Serial.begin(115200); // инициализируем HW UART МК
	pinMode(LED_BUILTIN, OUTPUT); // установка режима пина встроенного МК - выход
	initPins(); // инициализируем пин датчика движения
	setPWMout(0, 0, 0, 0); // гасим xtnsht ленты
}

void workKitchenL(void) { // основная рабочая функция
	static tStatusWork currentMode = lStart; // храним текущее значение режима работы
	static unsigned char pwm1 = 0, pwm2 = 0, pwm3 = 0, pwm4 = 0; // текущая яркость лент
	static unsigned long timerLastChange = 0; // таймер изменения яркости
	static unsigned long timerWaitMove = 0; // таймер ожидания движения при максимальной яркости
	switch (currentMode) { // работаем с логикой в зависимости от текущего режима
		case lToUP: { // режим понижения яркости
			if ((millis() - timerLastChange) >= stepChange) { // если прошел шаг изменения яркости
				timerLastChange = millis(); // обновим таймер изменения яркости
				if (pwm1 > 0) { // если яркость первой ленты больше нуля
					--pwm1; // уменьшаем яркость первой ленты
				} else { // если первая лента не светится
					if (pwm2 > 0) { // если яркость второй ленты больше нул
						--pwm2; // уменьшаем яркость второй ленты
					} else { // если вторая лента не светится

					if (pwm3 > 0) { // если яркость третей ленты больше нуля
						--pwm3; // уменьшаем яркость второй ленты
					} else { // если третья лента не светится

          if (pwm4 > 0) { // если яркость четвертой ленты больше нуля
						--pwm4; // уменьшаем яркость четвертой ленты
					} else { // если четвертая лента не светится
                                        currentMode = lToDOWN; // переходим в режим повышения яркости лент
                                        

						timerWaitMove = millis(); // обновляем таймер ожидания движения при максимальной яркости
					
					}
          }
				}
        }
				setPWMout(pwm1, pwm2, pwm3, pwm4); // устанавливаем яркость лент
			}
			break;
		}
		case lToDOWN: { // режим понижения аркости
			
				if ((millis() - timerLastChange) >= stepChange) { // если прошел шаг изменения яркости
					timerLastChange = millis(); // обновим таймер изменения яркости
					if (pwm4 < 255) { // если яркость четвертой ленты меньше максимальной
						++pwm4; // увеличиваем яркость четвертой ленты
					} else { // если яркость четвертой ленты максимальная
						if (pwm3 < 255) { // если яркость третей ленты меньше максимальной
							++pwm3; // увеличиваем яркость третей ленты
						} else { // если яркость третей ленты максимальнаяя
            if (pwm2 < 255) { // если яркость второй ленты меньше максимальной
							++pwm2; // увеличиваем яркость второй ленты
						} else { // если яркость второй ленты максимальная
            if (pwm1 < 255) { // если яркость первой ленты меньше максимальной
							++pwm1; // увеличиваем яркость первой ленты
						} else { // если яркость первой ленты максимальная


            delay(10000);
								currentMode = lWaitMove; // переходим в режим ожидания движения при максимальной яркости

						
            }
					}
          }
					setPWMout(pwm1, pwm2, pwm3, pwm4); // устанавливаем яркость лент
				}
			}
			break;
		}
    
		case lWaitMove: { // режим ожидания движения при максимальной яркости лент
			if (readRIP()) { // если есть движенние
				currentMode = lToUP; 

			} 
			break;
		}
		default: { // lStart // начальный режим
			if (readRIP()) { // если произошло движение
				currentMode = lToUP; 
			}
		}
	}
}

// the loop function runs over and over again until power down or reset
void loop() { // бесконечный цикл
	workKitchenL(); // работаем
}

Но встал вопрос, что из-за относительно большого количества лент, все это происходит достаточно долго. И если каждая последующая лента будет тухнуть и разгораться на середине предыдущей, то понадобится в два раза меньше времени на весь цикл.

Но как я не старался применить полученные знания у меня не получилось это реализовать. Поэтому я и решил узнать на форуме как это сделать.
Но почему то вместо помощи получил только порецание…

Временной шаг изменения яркости уменьшите - и будет быстрее.

Абсолютно логично. Как вы думаете, что можно сказать про новичка, который не научившись еще с места трогаться, уже хочет в гонках участвовать?
Ваш проект для человека, который никогда не программировал - это как выступление на конкурсе поваров для того, кто не умеет даже пельмени из пачки сварить.
Я не знаю, на какую помощь вы тут рассчитываете. Обучение - это процесс, и процесс длительный. Не ждите, что кто-то станет вместе с вами штудировать учебник с самого начала. Если есть КОНКРЕТНЫЕ ВОПРОСЫ - спрашивайте.

это не конкретный вопрос

1 лайк

Тогда, конкретный вопрос. Почему первая лента в моем пределаном коде загорается резко, а остальные плавно?

покажите “переделанный” код

В 7 сообщении я его вставил

Там на четыре ленты и логика как я в том сообщении написал

сообщение 7 - это моя просьба к вам “покажите код”.
Имеете в виду сообщение 4?

Да, точно. В пути, через телефон отвечаю, промазал

105 строка не на том месте.
Надо вниз на одну скобку, аналогично как в режиме понижения яркости.

1 лайк