Случайное моргание с millis()

я пытаюсь сделать скетч, в котором мой светодиод мигает со случайной задержкой. У меня есть 2 функции: ledBlink() и randomBlink(). вторые функции получают в качестве параметра задержки случайное число "r", сгенерированное от 1 до 499, и передают это значение функции ledBlink, чтобы светодиод мигал с задержкой в соответствии с сгенерированным случайным числом. Но проблема в том, что светодиод мигает очень быстро и, похоже, не учитывает значение blinkDelay. Любая помощь приветствуется, большое вам спасибо!

#include <JC_Button.h>

int ledPin = 11;

int ledState = LOW;
unsigned long blinkDelay;
unsigned long lastBlinkMillis = 0;


void setup() {

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void ledBlink()
{
  unsigned long currentMillis = millis();

  if (currentMillis - lastBlinkMillis >= blinkDelay)
  {
    // save the last time you blinked the LED
    lastBlinkMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    ledState = !ledState;
  

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
} 

void randomBlink()
{
  unsigned long r = random(500);
  blinkDelay = r;
  ledBlink();
  
} 


void loop() {
  randomBlink();
}

, 👍1

Обсуждение

вам может понравиться это https://github.com/jandrassy/SunriseClock/blob/6ad596040e6a87d569ffaacddd7988803fc5d376/SunriseClock/SunriseClock.ino#L687, @Juraj

установите флаг "занято в начале" ledBlink() ... очистите его внутри блока " если`... вызовите функцию "randomBlink ()" только в том случае, если она не занята, @jsotola


1 ответ


Лучший ответ:

4

Описание вашей проблемы немного неясно, хотя я думаю, что вижу вашу проблему.

На каждой итерации цикла() вы вызываете функцию randomBlink(), которая генерирует новое значение случайной задержки, а затем вызывает функцию ledBlink (), которая, в свою очередь, проверяет millis() на время переключения светодиода и быстро завершает работу. Таким образом, вы мигаете только тогда, когда текущий blinkDelay прошел, но вы генерируете новые случайные значения для blinkDelay на каждой итерации цикла () - так что действительно очень быстро. За время, необходимое даже для небольших задержек, вы, возможно, сгенерировали тысячи новых случайных значений, так что весьма вероятно, что некоторые из них являются довольно малыми значениями. Вы сверяетесь с ними, чтобы получить только короткие задержки.

Подумайте, как бы вы поступили так в реальной жизни. Допустим, вы используете кости, чтобы определить количество минут ожидания. Вы бросаете кости каждые несколько секунд, наблюдая за часами. Скорее всего, в какой-то момент вы получите 1 или 2 после ожидания 1 или 2 минут. Маловероятно, что вы не получите 6 баллов в течение 6 минут подряд. Вместо этого вы хотели бы пройти через кости только один раз за период ожидания.

Для кода это означает, что вам нужно его реструктурировать. Рассчитайте новое значение задержки только при переключении светодиода. Итак, что-то вроде этого:

void ledBlink()
{
  unsigned long currentMillis = millis();

  if (currentMillis - lastBlinkMillis >= blinkDelay)
  {
    // save the last time you blinked the LED
    lastBlinkMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    ledState = !ledState;
  

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

    // generate new random delay
    randomBlink();
  }
} 

void randomBlink()
{
  unsigned long r = random(500);
  blinkDelay = r;
} 


void loop() {
  ledBlink();
}

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

,

о, хорошо, попался! Спасибо!, @tommy