Контроллер для гирлянды "Роса"

Всем доброго времени суток и с наступившим новым годом! Я не имею большой опыт по программированию Arduino, однако решил создать контроллер для гирлянды. Собственно вылезла проблема - нажатие на кнопку контроллер не всегда обрабатывает. Писал все на millis(). В чем проблема и есть ли варианты как ее решить? Заранее всем спасибо

int num = 0;

bool flag = false;
uint32_t btnTimer = 0;

const int ledCount = 4;                        // Количество светодиодов
const int ledPins[ledCount] = { 5, 6, 7, 8 };  // Пины светодиодов
unsigned long previousMillis1 = 0;             // Время последнего переключения
const unsigned long interval1 = 500;           // Интервал в мс между переключениями
int currentLed = 0;

unsigned long previousMillis2 = 0;    // Время последнего переключения
const unsigned long interval3 = 500;  // Интервал в мс между переключениями
int currentLed1 = 0;
bool allOn1 = true;

bool allOn = true;
const unsigned long interval2 = 100;

int brightness = 0;                // начальное значение яркости
int fadeAmount = 1;                // величина изменения яркости за один шаг
unsigned long previousMillis = 0;  // хранит последнее время обновления яркости
const long interval = 10;
int button;

unsigned long time = 0;

int j = 0;
int jj = 255;
unsigned long timer = 0;

int i1 = 0;
int j1 = 255;
void setup() {
  pinMode(2, INPUT_PULLUP);
  for (int i = 5; i <= 8; i++) {
    pinMode(i, OUTPUT);
  }

  /*digitalWrite(6, LOW);
  digitalWrite(7, LOW);*/
  Serial.begin(9600);
}
void ef1() {  //плавное затухание и включение

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    analogWrite(8, brightness);
    analogWrite(5, brightness);
    analogWrite(6, brightness);
    analogWrite(7, brightness);
    brightness = brightness + fadeAmount;
    if (brightness <= 0 || brightness >= 255) {
      fadeAmount = -fadeAmount;
    }
  }
}
void ef2() {  //постоянное горение
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
}
void ef3() {  //поочередное включение
  unsigned long currentMillis1 = millis();

  if (currentMillis1 - previousMillis1 >= interval1) {
    previousMillis1 = currentMillis1;

    // Выключаем предыдущий светодиод
    digitalWrite(ledPins[currentLed], LOW);

    // Переходим к следующему светодиоду
    currentLed = (currentLed + 1) % ledCount;

    // Включаем текущий светодиод
    digitalWrite(ledPins[currentLed], HIGH);
  }
}
void ef4() {  //круговая
  unsigned long currentMillis2 = millis();

  if (currentMillis2 - previousMillis1 >= interval2) {
    previousMillis1 = currentMillis2;

    if (allOn) {
      // Зажигаем следующий светодиод
      digitalWrite(ledPins[currentLed], HIGH);

      currentLed = (currentLed + 1) % ledCount;

      // Проверяем, завершилось ли зажигание всех светодиодов
      if (currentLed == 0) {
        allOn = false;
      }
    } else {
      // Тушим текущий светодиод
      digitalWrite(ledPins[currentLed], LOW);

      currentLed = (currentLed + 1) % ledCount;

      // Проверяем, завершилось ли тушение всех светодиодов
      if (currentLed == 0) {
        allOn = true;
      }
    }
  }
}
void ef5() {  //мигалка
  time = millis();
  while (i1 != 255 && j1 != 0) {
    if (millis() - time >= 1) {
      time = millis();

      analogWrite(5, i1);
      analogWrite(6, j1);
      analogWrite(7, i1);
      analogWrite(8, j1);
      i1++;
      j1--;
    }
  }
  while (i1 != 0 && j1 != 255) {
    if (millis() - time >= 1) {
      time = millis();
      analogWrite(5, i1);
      analogWrite(6, j1);
      analogWrite(7, i1);
      analogWrite(8, j1);
      i1--;
      j1++;
    }
  }
}
void ef6() {  //круговая медленная
  for (int i = 5; i <= 8; i++) {
    j = 0;
    timer = millis();
    while (j != 255) {
      if (millis() - timer >= 10) {
        timer = millis();
        analogWrite(i, j);
        j++;
        
      }
    }
  }
  for (int i = 5; i <= 8; i++) {
    timer = millis();
    jj = 255;
    while (jj != 0) {
      if (millis() - timer >= 10) {
        timer = millis();
        jj--;
        analogWrite(i, jj);

       
      }
    }
  }
}
void loop() {
  //--------------------кнопка----------------------------------
  bool btnState = !digitalRead(2);
  if (btnState && !flag && millis() - btnTimer > 100) {
    flag = true;
    btnTimer = millis();
    num++;
    if (num == 8) num = 0;
    Serial.print("press");
    Serial.println(num);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
  }
  if (!btnState && flag && millis() - btnTimer > 100) {
    flag = false;
    btnTimer = millis();
    //Serial.println("release");
  }

  /*-----------------------------------------------------------------------------*/
  if (num == 1) ef1();
  /*-----------------------------------------------------------------------------*/
  if (num == 2) ef2();
  /*-----------------------------------------------------------------------------*/
  if (num == 3) ef3();
  /*-----------------------------------------------------------------------------*/
  if (num == 4) ef4();
  /*-----------------------------------------------------------------------------*/
  if (num == 5) ef5();
  /*-----------------------------------------------------------------------------*/
  if (num == 6) ef6();
  /*-----------------------------------------------------------------------------*/
}

Этого мало.
Надо еще избавляться от while.

получается все на for менять?

А что, for перестал быть циклом?
Вот это новогодние чудеса!!!…

ок а эффект 5 как реализовать без while

Я тебе, может быть, секрет огромный открою (ты меня не сдавай только), но loop() и есть огромный цикл. Вот в нём всё и выполняй.

ЗЫ: В школе сейчас разве не учат в конце вопросительного предположения вопросительный знак ставить? И с большой буквы начинать его?

1 лайк

Отнюдь.
От for тоже надо избавляться. В программе должен быть один единственный цикл, из которого вызывается loop. Все!
И, кстати, millis по-хорошему должна вызываться один единственный раз в loop. У Вас же она вызывается десятки раз.

Структуру программы менять надо. Вот эти блоки analogWrite в строках 117-120 и 128-131 выполняются не более одного раза внутри loop, и loop не должен ждать, пока выполнится условие в строке 113 или 125. Если наступило время - условие выполняется, а нет - loop проходит дальше.

Типам данных не учили? Лучше применить uint8_t.
Как выше сказали:

Блокирует код на 0.25 сек. Потом появляется “окошко” в несколько микросекунд и снова блокируется.
Вместо while используйте флаги: быстренько зашли, проверили флаги. Если флаги говорят “надо Федя, надо”, то проверяем не настало ли время. Если да, то делаем. Всё, никаких циклов.

А петля?))

Петля лесом))) Не ссы, я сто раз так делал!))))

Не рановато для опохмела? Или ещё не ложились?)))

Это нестандартные способы программирования Ардуино?

@BOOM ну ЛУП не считаем. Хотя у меня заЛУПом всё. Точней в прерываниях. А ЛУП пустой.

Ну так тоже не дело.

Кто как хочет, так и дро… Вариантов масса. Что проще?

ну конечно, луп нужно использовать для опроса кнопок и прочей ерунды

А у некоторых то и луп не луп вовсе… Ибо, после sleep-а в loop-е происходит reboot. Не знали?)

Всех благодарю за помощь. Если кому интересен проект, то вот ссылка на гитхаб