Измерение длины импульсов импульсов сервопривода.
- Войдите на сайт для отправки комментариев
Сб, 19/09/2020 - 17:21
Здравствуйте! Я хочу управлять устройством через радиаппаратуру, приёмник выдаёт на выходе сигнал как для сервопривода. Как я понял в сигнале сервопривода изменяется только длина импульсов, а частота неизменна. Вопрос в том как её измерить, прост нигде ничего подобного не нашёл.
Буду рад любой помощи.
Ищите тему " измерение частоты ШИМ" , хотя речь идет о частоте - принцип тот же
С помощью pulseIn
int duration; void setup(){ pinMode(3, INPUT); pinMode(4, OUTPUT); } void loop(){ duration = pulseIn(3, HIGH, 5); digitalWrite(4, LOW); if (duration > 1900) { digitalWrite(4, HIGH); } }https://fpv-freun.de/en/avr-projects/72-rc-schalter-mit-attiny-13
5 (или 10) там нужно добавить потому что на тини13 без него не компилится
int duration; void setup(){ pinMode(3, INPUT); pinMode(11, OUTPUT); pinMode(10, OUTPUT); digitalWrite(10, LOW); Serial.begin(9600); } void loop(){ duration = pulseIn(3, HIGH, 5); digitalWrite(11, LOW); Serial.println(duration); if (duration > 1900) { digitalWrite(11, HIGH); } }#2 У меня почему-то не работает. Я добавил вывод значения duration в консоль, и оно всегда равно нулю.
https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/
pulseIn(pin, value, timeout)
...
timeout (optional): the number of microseconds to wait for the pulse to start; default is one second. Allowed data types: unsigned long.
Поставьте ожидание 1000 для проверки
int duration; void setup(){ pinMode(3, INPUT);//к приёмнику pinMode(11, OUTPUT);//выход digitalWrite(10, LOW); Serial.begin(9600); } void loop(){ duration = pulseIn(3, HIGH);/* ожидает пока на заданном порту не появиться HIGH. Когда HIGH получен, включается таймер, который будет остановлен когда на порту будет LOW */ digitalWrite(11, LOW); Serial.println(duration); if (duration > 1900) { digitalWrite(11, HIGH); } }Заработало! Нужно было убрать таймаут.
Вы не "убрали" таймаут, а поставили его дефолтно 1 секунду. С вашим типом переменной duration это глупо, ведь у вас длина импульса не может быть больше 32 миллисекунд
И, кстати, если реальный импульс на вашей серве превысит 32.7 мс - ваш код начнет показывать погоду на марсе вместо длины импульса, подумайте об этом
У сервы импульс от 800 до 2400 мкс. Так что инт вполне для этой задачи.
Ну ок, инт нормально, но таймаут 1 сек будет тормозить программу
это надо делать правильно вот пример на два канала (для аппаратуры управления)
/* * Измерение PWM через micros() * Используется 0 прерывание (пин D2) */ volatile unsigned int rc1_data = 0; volatile unsigned long start_timeRC1 = 0; volatile byte flag_RC1 = 0; /******Обработчик прерывания по возрастанию и спаду сигнала с приёмника RC******/ void Rc1() { if(digitalRead(2) == HIGH && flag_RC1==0){ //сохраняем значение времени начала импульса start_timeRC1 = micros(); flag_RC1=1; } if(digitalRead(2) == LOW && flag_RC1==1){ //сохраняем значение длительности импульса канала 1 rc1_data = micros() - start_timeRC1; flag_RC1=0; } }//END RC1 void setup() { Serial.begin(115200); // Привязываем к Pin2 прерывание по фронту и спаду сигнала attachInterrupt(0, Rc1, CHANGE); } void loop() { Serial.println(rc1_data); delay(1000); }Нет, не будет. Пока идут импульсы таймаут вообще не при делах. Если импульсов нет, то нет разницы нет где висит программа. Приход первого импульса опять обнулит таймаут и программа сразу отреагирует. Тормозов не будет. Но для вообще универсальности таймаут всё же было бы хорошо установить где то как 30000. Особенно если в лупе будет ещё что то кроме светодиодиков.