Пример Blink. Мигаем светодиодом

Понадобятся: Плата Arduino Uno или другая, светодиод, резистор 220ohm или используем светодиод, распаянный на плате

Простой пример с delay

void setup() {
  // Инициализируем выход LED_BUILTIN как output. 
  // на платах UNO, Mega, ZERO светодиод на плате подключен к пину 13
  // LED_BUILTIN имеет значение пина к которому подключен светодиод на плате 
  // независимо от используемой платы
  pinMode(LED_BUILTIN, OUTPUT);
}


void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // Включаем светодиод
  delay(1000);                      // пауза 1сек
  digitalWrite(LED_BUILTIN, LOW);   //выключаем светодиод
  delay(1000);                      // пауза 1сек
}

Пример без delay

const int ledPin = LED_BUILTIN;  
int ledState = LOW;  

unsigned long previousMillis = 0;  
const long interval = 1000;  

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  //проверяем если время мигать, как разницу между сохраненным временемe 
  //последнего мигания previousMillis и текущим временем
  // и если больше или равно interval в нашем случае 1000мс = 1 сек, то мигаем
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    //сохраняем время последнего мигания
    previousMillis = currentMillis;

    // включаем или выключаем в зависимости от текущего состояния:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // уставнавливаем значение в нужный пин/выход:
    digitalWrite(ledPin, ledState);
  }
}

Пример мигания по битовому шаблону.

const uint8_t ledPin = LED_BUILTIN; 
uint32_t previousMillis = 0; 
const uint32_t interval = 125;
uint16_t blinkMode = 0; // текущий режим свечения светодиода.
uint16_t  blinkLoop = 0;

// Массив шаблонов свечения светодиода.
const uint16_t modesBlink[] = {
   0B0000000000000000, // 0 светодиод постоянно выключен
   0B1111111111111111, // 1 светодиод постоянно включён
   0B1010101010101010, // 2
   0B1101101101101101, // 3
   0B0010010010010010, // 4
   0B0000000011110000, // 5
   0B1111000011110000, // 6
   0B1100000000000000, // 7
   0B1111111100111111, // 8
   0B1100110000000000, // 9
   0B1111111100110011, // 10
   0B1000100010001000, // 11
   0B1110111011101110, // 12
   0B0000011000000000, // 13
   0B1111111111111001, // 14
   0B0001111000011110, // 16
   0B1110000111100001, // 17
   0B0001111111100000, // 18
   0B0000000111111110  // 19
};

void setup() {
  pinMode(ledPin, OUTPUT); 
  blinkMode = modesBlink[12]; // выбор текущего шаблона моргания из массива шаблонов
}
 
void loop() {
   uint32_t currentMillis = millis();
   if(currentMillis - previousMillis >= interval) {
       previousMillis = currentMillis;
       if (blinkMode & 1 << (blinkLoop & 0xF)) // чтение бита из текущего шаблона
         digitalWrite(ledPin, HIGH); 
       else  
         digitalWrite(ledPin, LOW);
       blinkLoop++;
    }
}

Блинк с регулировкой частоты с помощью потенциометра

Задача разбивается на две - собственно, управление состоянием светодиода и получение нового интервала для блинка с потенциометра, подключенного к аналоговому входу A0

uint8_t const LED_PIN = 13; // пин для подключения светодиода

uint32_t const MAX_TIME = 5000; // максимальный период блинка, милисекунд
uint32_t const MIN_TIME = 100;  // минимальный период блинка, милисекунд
uint32_t BLINK_TIMEOUT = 0;     // текущий интервал блинка

// управление состоянием светодиода
void setLedState()
{
  static uint32_t timer = 0;
  if (millis() - timer >= BLINK_TIMEOUT)
  {
    static uint8_t ledState = LOW;
    timer = millis();
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);
  }
}

// получение нового интервала блинка в зависимости от положения потенциометра,
// подключенного к аналоговому входу A0
void getBlinkTimeout()
{
  // получаем значение с аналогового пина
  uint16_t x = analogRead(A0);
  // устанавливаем новое значение интервала
  BLINK_TIMEOUT = map(x, 0, 1023, MIN_TIME, MAX_TIME);
}

void setup()
{
  pinMode(LED_PIN, OUTPUT);
}

void loop()
{
  getBlinkTimeout();
  setLedState();
}

См. также Fade. Плавное разгорание и затухание светодиода. (analogWrite, PWM/ШИМ)

Хороший пример, теперь нужно без дэлэй добавить пример)
(Прошу прощения, я с планшета - не удобно добавлять, если никто не добавит - завтра вывернусь!)

Ага согласен, пример очень интересный, эксперт (по моему мнению очень хороший) Ардуино щас отпишет куда двигаться :slight_smile:

Ну, если только приучать к красивому.))) (Влад, привет!)

#define LED               LED_BUILTIN
#define LED_PERIOD        1000

#define out(x)            pinMode(x, OUTPUT)
#define toggle(x)         digitalWrite(x, !digitalRead(x))
#define every(x)          for (static uint16_t t; (uint16_t)millis() - t >= (x); t += x)

void setup() {
  out(LED);
}

void loop() {
  every(LED_PERIOD / 2)
    toggle(LED);
}

2 лайка

Огромная просьба не засорять тему (и раздел в целом). Если хочется обсудить что-то не по делу - есть «отвлеченные» и ЧЧ

Обратите внимание, что мое первое сообщение можно редактировать другим участникам. Это так называемое вики-сообщение

Такое только для первого сообщения в ветке возможно? не нашел, как добавить такое же.

Согласен, а вот Green красиво написал :slight_smile:, ладно всем удачи пойду делом заниматься :slight_smile:

Первое сообщение/тема в этом разделе автоматически становится вики-сообщением. Автор темы может редактировать чужие комментарии

1 лайк

Не желаете define выкинуть и переписать на constexpr с нужным размером переменных.

1 лайк

В чем проблема? Перепиши. Доступно к редактированию жо! О, жО! Раньше было жэ…)

Да че то не подумал (
Завтра с компа, или автор сам перепишет.

Специально не использую ++ фишки, где это возможно.
В данном случае можно было бы const, но с define зачастую нужны свои выверты, типа, #define LED 12, LOW или B,4,L например. Понятно, что c constexpr дополнительная защита, но если всё аккуратненько, то и с препроцессором никаких проблем. К тому же, не все компиляторы с плюсами.

Здесь размещен “классический” вариант blink without delay, который всегда вызывал у меня чувство протеста: во-первых, не следует плодить лишних глобальных переменных, а во-вторых, эта громоздкая конструкция переключения состояния просто чудовищна.

const byte ledPin = LED_BUILTIN;  
const long interval = 500;  

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  static byte ledState = LOW;  
  static unsigned long previousMillis = 0;  
  //проверяем если время мигать, как разницу между сохраненным временемe 
  //последнего мигания previousMillis и текущим временем
  // и если больше или равно interval, то мигаем
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    //сохраняем время последнего мигания
    previousMillis = currentMillis;
    // переключаем нужный пин/выход, запоминая его состояние:
    digitalWrite(ledPin, ledState = !ledState);
  }
}

Можно еще полностью избавиться от legState и заменить последнюю строку на

digitalWrite(ledPin, !digitalRead(ledPin));

Чем (в данном случае) глобальные переменные отличаются от локальных в луп? И чем чревато использование глобальных переменных в принципе?

Глобальные переменные следует использовать только там, где они нужны.
Злоупотребление глобальными переменными чревато возникновением труднообнаруживаемых ошибок.

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

Как обычно - лучшее враг хорошего. В данном случае увеличится время исполнения. Для этого примера абсолютно безразлично, но если код критичен ко времени то лучше пожертвовать 1 байт ОЗУ. Ну или читать регистр напрямую, но это уже не Ардуино.

Поэтому я и включил это в качестве варианта, а не в качестве основного кода.

Вот и получается, что вроде банальность, blink, а вариантов реализации вагон :frowning: и каждый тянет одеяло на себя, примеряет на свои примеры реализации.
To Green - а зачем обрезать / считать millis в пределах uint16?