DShot receiver on STM32
Приймання сигналу DShot 150/300/600 з використанням DMA. Приклад для STM32.
Якщо в мікроконтролері є DMA, який можна використати, його обов'язково треба використати, навіть, коли здається, що в конкретному випадку можна обійтися без DMA. Використання DMA звільнює ядро мікроконтролера від рутинних операцій.
Що таке DShot?
DShot - це простий протокол передачі цифрової інформації по одному дроту. Використовується для керування ESC. Передача інформації пакетна. Тобто передається певна кількість біт, після чого витримується пауза, яка розділяє пакети. Детекція бітів, нуль або один, відбувається за шириною імпульсів. Якщо імпульс коротший за певне значення - це "0", якщо довший за певне значення - то це "1".
Приблизний вигляд протоколу DShot:
Як видно передаються 16 біт.
Протоколи DShot150, DShot300, DShot600 мають однакову структуру і відрізняються лише швидкістю. DShot150 - передає 150 пакетів за секунду, DShot300 - триста, DShot600 - відповідно 600 пакетів за секунду.
Приймання DShot
Нам треба прийняти 16 біт, які передаються по одному входу, а потім обробити їх. Якщо конкретизувати задачу - нам потрібно вимірювати довжину кожного з 16 імпульсів і вирішувати це 0 чи 1. По завершенню приймання 16 біт, обробити весь пакет - перевірити контрольну суму, витягти дані тощо.
1. Рішення #1. Таймер + переривання
Найпростіше, але не найкраще рішення - використовувати для вимірювання ширини імпульсів звичайний таймер, а показання його знімати по перериванню від входу GPIO. Коли переривання спрацьовує при наростанні сигналу запам'ятовувати показник лічильника таймера, коли переривання спрацьовує на спад сигналу запам'ятовувати показник лічильника таймера, вираховувати різницю між запам'ятованими показниками таймера і якщо різниця менша за порогове - це був 0, якщо більша, тоді це 1.
Та у цьому підході є одна вада - це переривання. На справді переривання не виконуються негайно. Спочатку виставляється прапорець переривання, який означає, що трапилась певна подія, яку треба обробити. І коли мікроконтролер перевірить цей прапорець, тоді він почне підготовку до обробки переривання. Коли мікроконтролер обробляє більш пріоритетне переривання, він не буде перериватися на обробку вашого переривання, а завершить поточне, а потім перейде до наступного. Сам перехід до обробки переривання теж потребує "підготовки". Мікроконтролер запам'ятає те місце, на якому його перервали, збереже всю необхідну інформацію, яка потрібна буде при поверненні до виконання поточної задачі. Весь цей час таймер продовжує працювати, тому похибка вимірювань неминуча. Коли сигнал достатньо розтягнутий у часі - це не критично. В нашому випадку довжина імпульсів така мала, що може статися так, що наступне переривання відбудеться ще до того, як контролер встигне обробити поточне переривання. З таким підходом реально обробити хіба що DShot150. При роботі зі швидшими протоколами будуть виникати проблеми.
2. Рішення #2. Захоплення сигналу таймером + переривання
Трохи ліпше ситуація при використанні таймера у режимі захоплення сигналу. Коли таймер сам вимірює довжину сигналу. Нам залишається лише скопіювати значення у буфер кожного разу коли завершився імпульс. Це теж доводиться робити по перериванню таймера, пов'язаному з захопленням сигналу. Це краще ніж перший варіант, але не достатньо швидко через занадто коротку тривалість імпульсів DShot, яка вимірюється десятками імпульсів тактування мікроконтролера. Мікроконтролер так само не встигає обробляти переривання і трапляються пропуски бітів, які ведуть до втрати цілого пакета.
3. Рішення #3. Захоплення сигналу таймером + DMA
Найефективнішим рішенням є використання режиму захоплення таймером + відправляти результати у масив за допомогою DMA. А переривання від DMA обробляти, коли буде прийнято всі 16 біт. Часу між пакетами достатньо, щоб обробити прийняті дані.
Таким чином всі 16 біт будуть залітати у масив і при цьому мікроконтролер не буде відволікатися на ці операції. А після приймання всіх 16 біт виникне переривання від DMA і можна спокійно обробляти прийняті дані.
В прикладі реалізовано захоплення DShot150, DShot300, DShot600. Можливе автоматичне визначення швидкості протоколу DShot. Також в прикладі реалізовано захоплення PWM сигналу.
Завантажити приклад для STM32F030 можна тут: https://git.avislab.com/andre/STM32G030_Dshot
використання HAL - це дань моді? Якось StdPeriph звичніше....
З HAL дещо простіше перетаскувати проєкти на інші серії мікроконтролерів. Це, мабуть, єдина причина, чому я зі скрипом перейшов на HAL.
Tags
bme280 bmp280 gps mpu-6050 options stm32 ssd1331 ssd1306 eb-500 3d-printer soldering tim mpu-9250 dma watchdog piezo exti web raspberry-pi docker ngnix solar bluetooth foc html css brushless flask dc-dc capture gpio avr rs-232 mpx4115a atmega mongodb st-link barometer pwm nvic git java-script programmator dht11 hih-4000 pmsm encoder max1674 smd sensors rtc adc lcd motor timer meteo examples i2c usb flash sms rfid python esp8266 servo books bldc remap eeprom bkp battery ethernet uart usart displays led websocket nodemcu wifi
Архіви
