Другие языки программирования и технологии

Возможно ли выполнить действие 1 раз внутри функции, вызываемой в бесконечном цикле, с помощью её аргумента?

Такой вопрос у меня родился в связи с попыткой написать функцию, которая мигает одним цветом RGB светодиода с заданным интервалом. Однако иногда мне нужно не мигать, а просто зажечь светодиод, а значит выполнить действие лишь один раз. Первое что пришло в голову - передать при вызове некое булево значение runOnce. Но поскольку функция вызывается бесконечно много раз, то она будет вызываться с runOnce равным единице, то есть не будет флажок опускаться никогда.

Есть какой-то вариант сделать такое без использования (глобальных переменных/переменных более высокого уровня относительно функции) или нет?

Код условный. И он отражает мои мягко говоря несовершенные навыки программирования. Приведён лишь в качестве примера.

boolean LEDrunOnce = 1;
unsigned long blinkMillis = 0;

void setup(){

}

void loop(){
blinkFunction(0, 0, 0, 1); // intervalTime,R,G,B
}

void blinkFunction(int intervalTime, bool R, bool G, bool B) {

if (intervalTime != 0) {
if (millis() - blinkMillis > intervalTime) {
blinkMillis = millis();
if (R) {
rState = !rState;
digitalWrite(RED, rState);
}
if (G) {
gState = !gState;
digitalWrite(GREEN, gState);
}
if (B) {
bState = !bState;
digitalWrite(BLUE, bState);
}

}
}

else {
if (LEDrunOnce) {
digitalWrite(RED, R);
digitalWrite(GREEN, G);
digitalWrite(BLUE, B);
LEDrunOnce = 0;
if (massage)Serial.print(F("Светодиодам задано состояние один раз."));
}
}
}
Как я понимаю у вас будет несколько состояний программы на которые должен указывать светодиод. Ну я конечно не совсем себе представляю почему цикл не должен крутиться именно в этом состоянии и делать то что нужно как с светодиодами, так и с другими вещами пока не программа не перейдет в другое состояние. Ну да ладно. Например можно использовать указатель на функцию.

void(*p_state)(); //указатель на функцию типа void

void blinkFunction(int intervalTime, bool R, bool G, bool B) {

if (millis() - blinkMillis > intervalTime) {
blinkMillis = millis();
if (R) {
rState = !rState;
digitalWrite(RED, rState);
}
if (G) {
gState = !gState;
digitalWrite(GREEN, gState);
}
if (B) {
bState = !bState;
digitalWrite(BLUE, bState);
}

}

void blink500()
{
blinkFunction(500, 1, 1, 0);
}

void nop() {}

void led_on()
{
digitalWrite(RED, 1);
digitalWrite(GREEN, 1);
digitalWrite(BLUE, 1);
p_state = nop;
}

void led_off()
{
digitalWrite(RED, 0);
digitalWrite(GREEN, 0);
digitalWrite(BLUE, 0);
p_state = nop;
}

void setup(){
p_state = blink500;
}

void loop(){
p_state();
...
...
if(other_state) p_state = led_on;
if(another_state) p_state = led_off;
}

не самый лучший но как вариант
Jeeper Проходимец
Jeeper Проходимец
15 408
Лучший ответ
Jeeper Проходимец if (massage) - А кто у вас там масаж то делает и зачем об этом нужно говорить через последовательный порт!? Может имелось в виду message?
Эм... в этом микроконтроллере нет таймеров? Так понимаю, вы постоянно берете текущее время и сравниваете сколько прошло? Мягко говоря, нецелесообразная трата аппаратных ресурсов...
Есть вариант - использовать для мигания и постоянного зажигания разные функции, и не повторять в цикле одно и то же независимо от всего.
Сергей Шубин Хорошо. Я понял что Вы имеете в виду. Это Arduino Nano (ATmega328) и вроде бы там есть таймеры и по ним даже доступны прерывания. Но мой уровень пока что находится на другой отметке. Я только-только отошёл от delay и стал осознавать, что некоторые действия нужно выполнять единожды и стал использовать флажки для этого.

Но мой вопрос-то был не про тайминги или про трату аппаратных ресурсов.

Я уверен Вы уже можете знать ответ на основной вопрос. То есть есть ли возможность выполнить функцию единожды в бесконечном цикле, передав ей в качестве аргумента просьбу выполниться один раз (без использования глобальной переменной)?

Хорошо. Вы предложили использовать разные функции для этих задач. Я понял. Спасибо.