Libraries

May 22, 2024

Суброзділ Libraries

WD.Easy

WD.Easy

Ця бібліотека призначена для керування режимами роботи сторожового таймера, поки тільки мікроконтролерів серії AVR.

Особливості

Я не писав її в стилі класу синглтон (сторожовий таймер то один). Все рівно скільки об’єктів не було б створено всі вони працюватимуть з одним регістом. Перед собою поставив завдання, щоб бібліотека була максимально легкою та можна використовувати для будь якої ардуїни та не тільки.

Основна вимога щоб ТАЙМЕР МАЄ ПОЧАТИ ВІДЛІК ЩЕ ДО СТАРТУ ФУНКЦІЇ setup, а ще краще до початку main.

Здається вийшло

Методи доступні у таймеру

МетодОПИСрезультат
setTimeOut(uint8_t)Задає інтервал спрацьовувань таймеруvoid
setMode(uint8_t)Задає дію при спрацьовуванні таймеруvoid
setTask(ptr*)Задати функцію обробник перериванняvoid
getTimeOut()Отримати періодичність спрацьовуаньuint8_t
getMode()Отримати режим роботи таймеруuint8_t
isEnable()Чи активний таймерbool
reset()Почати новий відлікvoid

Інтервали

У таблиці наведені параметри які приймає метод setTimeOut(uint8_t) та повертає getTimeOut().

defineчас c
WD_15MS0.015
WD_30MS0.030
WD_60MS0.060
WD_120MS0.120
WD_250MS0.250
WD_500MS0.500
WD_1S1
WD_2S2
WD_4S4
WD_8S8

Примітка Час приблизний і не підходить для вимірювання точних інтервалів, оскільки сторожевий таймер тактується від внутрішнього низькочатоного генератора, який “пливе” при зміні напруги живлення та температури

Дії

defineОзначення
DISABLEDТаймер зупинено
INTERRUPTПри спрацьовуванні буде викликано обробник переривання
SYSTEMRESETПри спрацьовуванні буде виконано перезавантаження мікроконтроллера
INTERUPTANDRESETПри спрацьовуванні буде викликано обробник переривання через такий же інтервали виконається перезавантаження контролеру

Обробник переривань

За замовчуванням обробникпереривань не вказаний (nullptr).

Приклади

Приклад перший

void WD_tick() {
Serial.print("WD_tick()");
Serial.println(millis());
}

WatchDogEasy WD(WatchDogEasy::WD_1S, WatchDogEasy::INTERRUPT, WD_tick);

void setup() { Serial.begin(115200); }
void loop() {}

Тут ми ініціюємо таймер на спрацьовування кожну секунду, при спрацьовуванні генеруватиметься переривання, яке буде оброблятися функцією WD_tick().

В цьому прикладі таймер починає відлік ще до початку роботи функції setup(). Це зручно якщо при ініціації контролеру є ризик завиcнути

Приклад другий

void WD_tick() {
Serial.print("WD_tick()");
Serial.println(millis());
}

WatchDogEasy WD;

void setup() {
Serial.begin(115200);
WD.setTimeOut(WatchDogEasy::WD_1S);
WD.setMode(WatchDogEasy::INTERRUPT);
WD.setTask(WD_tick);
}
void loop() {}

Тут все те саме, але таймер починає відлік після останнього сеттера.

Всі сетери скидають таймер на новий відлік. Геттери цього не роблять (Будьте уважні). Під час виконання геттеру може збігти час і виконатися дія запрограмованна у таймері.

Приклад третій

WatchDogEasy WD(WatchDogEasy::WD_1S, WatchDogEasy::SYSTEMRESET, nullptr);

int main(){
for(;;){

}
}

Тут таймер ініціалізується ще до входження у main(). На мій погляд це супер зручно

“Системні вимоги”

Таймер працюватиме на будь якому мікроконтролери серії Ардуїно та AVR

Місця в флеш займе додаткових 198 байт та 2 байти в оперативній пам’яті

Найголовніше

Встановлення

  1. Можна завантажити zip архів WD.Easy v1.0 І розпакувати вміст у потрібний каталог
  2. Бібліотека доступна для встановлення через менеджер бібліотек Arduino IDE. Шукайте в категрії
  3. Можна завантажити zip архів WD.Easy prerelise. Це гілка з тестовим не відлагодженим та найсвіжішім кодом. Встанволюється як перший пункт даного списку

Потрібно підключити

 #include <WD.Easy.hpp>

та не забувати скадати таймер, щоб він не скинув програму

CRSF

/**
 *  Для того щоб почативикористовувати мінімальний функціонал бібліотеки
 * Потрібно її заінклюдити
 */
#include <CrsfSerial.h>
/**
 *  В даному прикладі розглядається підключення приймача CRSF до Serial3
 * Arduino Mega 2560 або до  Serial якщо у вас інша "доска".
 * 
 * Будь ласка не використовуйте програмні реалізації серійного порту.
 * Використовуйте тільки апаратні серійні інтерфейси оскільки протокол 
 * CRSF використовує нестандартну швидкість передачі даних яка визначена
 * в константі CRSF_BAUDRATE. Якщо користуєтесь редактором Arduino IDE 
 * то ви не знайдете у моніторі серійного порту значення швидкості 420000
 * boud.
 *
 * По друге. Переконайтеся що ваша плата може працювати на такій швидкості
 * послідовного інтерфейсу. Ваш мікроеонтролер можливо не може працювати на
 * такій високій частоті через апаратні обмеження (не достатня частота тактового
 * генератора), софтверні обмеження (Не можливість вказати нестандартну швидкість)
 */
#if defined(__AVR_ATmega2560__)
/**
 * Тут ми створюємо об'єкт crsf класу CrsfSerial, який слухатиме Serial3.
 * 
 * В конструкторі можна задати іншу швидкість роботи, але для цього потрібно
 * переналаштовувати приймач, якщо він підтримує таку кастомізацію. Перевірте
 * ваш модуль на наявність такої опції
 */
CrsfSerial crsf(Serial3, CRSF_BAUDRATE);
#else
/**
 * Для плат які зібрані не на ATmega2560
 */
// CrsfSerial crsf(Serial, CRSF_BAUDRATE); ///< Цей
// CrsfSerial crsf(Serial);                ///< і цей записи тотожні
                                           /// за замовчуванням crsf працює 
                                           /// на швидкості 420000 бод
#error NOT MEGA2560
#endif


void packetChannels(); ///< Тут ми оголошуємо функцію яку реалізуємо пізніше
                       /// Ця функція буде виконуватися коли на порт "прилетить"
                       /// пакет з командами

/**
 *  Цей приклад написано для Ардуїно Мега і призначений для тестування пульта та
 * роботи скетчу.
 *
 * Скетч очікує що модуль приймача вісить на Serial3 а вся інформація для відладки
 * вилітає у стандартний серійний порт у монітор порта
*/

void setup() {
  Serial.begin(115200);                    ///< Ініціюємо черійний порт для відладкт
  crsf.begin();                            ///< Починаємо слухати приймач
  crsf.onPacketChannels = &packetChannels; ///< Вказуємо яка функція "витягає" команди
}


void loop() { crsf.loop(); }  ///< Тут живе програма

void packetChannels() {                              ///< Функція яка обробляє пакет
  for (auto ch{1}; ch <= CRSF_NUM_CHANNELS; ++ch) {  ///< Проходимо по всіх каналах
    Serial.print(crsf.getChannel(ch));               ///< Друкуємо
    if (ch != CRSF_NUM_CHANNELS) Serial.print(", "); ///< Ствимо розділові знаки
  }                                                  ///< Повторюємо
  Serial.println();                                  ///< Починаємо з нового рядка
}
Деталі

При виявленні неточностей чи помилок буду вдячний за фітбек