Суброзділ 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_15MS | 0.015 | |
WD_30MS | 0.030 | |
WD_60MS | 0.060 | |
WD_120MS | 0.120 | |
WD_250MS | 0.250 | |
WD_500MS | 0.500 | |
WD_1S | 1 | |
WD_2S | 2 | |
WD_4S | 4 | |
WD_8S | 8 |
Примітка Час приблизний і не підходить для вимірювання точних інтервалів, оскільки сторожевий таймер тактується від внутрішнього низькочатоного генератора, який “пливе” при зміні напруги живлення та температури
Дії
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 байти в оперативній пам’яті
Найголовніше
Встановлення
- Можна завантажити zip архів WD.Easy v1.0 І розпакувати вміст у потрібний каталог
- Бібліотека доступна для встановлення через менеджер бібліотек Arduino IDE. Шукайте в категрії
- Можна завантажити 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(); ///< Починаємо з нового рядка
}
Деталі
При виявленні неточностей чи помилок буду вдячний за фітбек