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
watchdog motor css flask max1674 dht11 hih-4000 ngnix bmp280 servo bldc ssd1306 mpu-6050 3d-printer eeprom rfid brushless mongodb meteo timer i2c pwm websocket esp8266 tim nvic st-link encoder dma rs-232 exti displays pmsm flash bkp raspberry-pi rtc usart piezo ethernet gps sensors capture atmega bluetooth barometer eb-500 battery lcd led web ssd1331 gpio programmator avr mpx4115a stm32 java-script python remap wifi uart usb bme280 examples books sms smd html git nodemcu soldering options adc dc-dc solar foc docker mpu-9250
Архіви
