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

Главное - чтобы у гайвера и с этого форума не тырил. А то конец человечеству.

1 лайк

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

#include <Arduino.h>
#define TICKER_UPDATE ISR(TIMER2_COMPA_vect)
#define out(x)            pinMode(x, OUTPUT)
#define toggle(x)         digitalWrite(x, !digitalRead(x))

class TickerAVR
{
private:
  void (*callback)();
  uint32_t interval_ms, uint32_t nexttTime;

public:
  TickerAVR(void (*callback)(), uint32_t interval_ms) : 
                    callback(callback),
                    interval_ms(interval_ms),
                    nexttTime(interval_ms + millis()) {
    cli();                                             // Настраиваем таймер каждую милисекунду
    OCR2A = 249;                                       // Устанавливаем значение для сравнения (249 + 1 = 250 циклов; 250 циклов * 4 мкс = 1000 мкс = 1 мс)
    TCCR2A |= (1 << WGM21);                            // Выбираем режим CTC (Clear Timer on Compare Match) для таймера 2
    TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Устанавливаем предделитель на 1024
    TIMSK2 |= (1 << OCIE2A);                           // Разрешаем прерывание по совпадению с OCR2A (TIMER2_COMPA)
    sei();                                             // Включаем прерывания
  }

  void update() {
    if (nexttTime <= millis()) {
        callback();
        nexttTime += interval_ms;
    }
  }

  ~TickerAVR(){
      TCCR2A = TCCR2B = 0;
      TIMSK2 &= ~(1 << OCIE2A);
  }
};

TickerAVR ticker_1s([]{ toggle(LED_BUILTIN); }, 1000);
TICKER_UPDATE { ticker_1s.update(); }

void setup() { out(LED_BUILTIN); }
void loop() { delay(100000); }

Дружище Ученик, ты бы создал отдельную тему где-нибудь в подходящем разделе… что бы не засорять Wiki.
Хотя нет. Она и так уже достаточно засорена.( Продолжай!)

1 лайк

Ну, тренировка в С++ это да. Но, зачем такие сложности для блинка? В чём его такой сакральный смысл?)
Обычно, ведь пишешь что то, типа blink(500); и ниочём не думаешь.
Тогда как #define blink(x) every(x) и всё. А every(x) тоже одна строка. И пофигу С++ там или просто Си. Ну ведь просто же! А тогда зачем усложнять, заради чего?

Правильный блинк масштабируется на сколько угодно светодиодов.
А на таймере - сколько ты светодиодов запустишь?

подсказываю - прерывания лишние

Попробую и я кинуть свой вариант

/*Blink  через автомат qwone*/
const byte Led1_Pin =/*пин*/13;
const byte Led1_init = 0;
const byte Led1_ON = 10;
const byte Led1_OFF = 20;
void (*events)() = {};
uint32_t past;
void go(byte s) {
  past = millis();
  switch (s) {
    case Led1_init:
      pinMode(Led1_Pin, OUTPUT);
    case Led1_ON:
      digitalWrite(Led1_Pin, HIGH);
      events = {[]()
      {
        if (millis() - past >= 1000) go(Led1_OFF);
      }
             };
      break;
    case Led1_OFF:
      digitalWrite(Led1_Pin, LOW);
      events = {[]()
      {
        if (millis() - past >= 1000) go(Led1_ON);
      }
             };
      break;
  }
}

void setup() {
  go(Led1_init);
}


void loop() {
  events();
}

Тема лямбд недостаточно раскрыта.

Если бы мне, в начале пути, показали такой пример блинка, я сказал, да идите вы … с вашей ардуиной и С/С++сами этими.

3 лайка

вроде обычное дело - пойди туда не знаю куда и спроси там куда идти дальше )))
PS то ли дело ассемблер …

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сек
}

Да я на это долгооо… смотрел. Думал будет типа : svetodiod (migai!!!);

во во, а дальше понеслись вариации

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


void loop() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  // Переключаем светодиод
  delay(1000);                      // пауза 1сек
}

и т.д.
видим к чему это приводит, в конечном итоге))

1 лайк
Скетч использует 1016 байт (3%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.

Когда классический блинк на миллис:

Скетч использует 860 байт (2%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.

Конечно, ведь определение еще одной функции “подтягивается”…

он про код от qwone1 говорит)
я так думаю…

Так тот код еще и не блокирующий. Но когда в лямду воткнуть еще ассемблер, то мир станет еще красивее.

… и розовые единороги увезут нас в мир молочных рек и кисельных берегов )))

Он же тебя цитировал…
Или только я цитатами не правильно пользуюсь?

на катушку скидку делай))
цитировал меня, а код занимающий 1016 байт , от @qwone1

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

// блинк 1 секунда
uint16_t n = 3032;

ISR( TIMER1_OVF_vect )
{
  PORTB ^= 1 << 5;
  TCNT1 = n; 
}

void setup() {
  DDRB = DDRB | 1 << 5;
  TCCR1A = 0;
  TCCR1B = B00000100;
  TIMSK1 = 1 << TOIE1;
  TCNT1 = n;
  sei();    
}

void loop() {
}
1 лайк