Rc управление ардуино

Тема в разделе "Проводная и беспроводная связь", создана пользователем vlad123419, 25 мар 2016.

  1. vlad123419

    vlad123419 Нерд

    Доброго времени суток! Я хотел бы сделать катер на радиоуправлении с помощью пульта(фото прилагаю) от вертолёта, но возник вопрос: Как передавать данные с пульта на ардуино, а от ардуино уже моторам и сервоприводам по радиосигналу? Там какой то передатчик- приёмник нужен? Заранее спасибо! DSC_0021.JPG
     
  2. Alex19

    Alex19 Гуру

    Когда-то пробежался по данной теме, но отказался от такого джойстика по ряду своих причин. Поэтому смогу указать лишь направление.

    Для подключения Вам нужно сам пульт и совместимый с ним приемник, не знаю как называют их моделисты, говорю об этом.
    [​IMG]

    Не самый лучший подход, но им можно быстро проверить, прочесть о нем можно тут - https://www.sparkfun.com/tutorials/348.

    Правильный подход реализован к примеру в проекте Multiwii - https://github.com/multiwii/multiwii-firmware/blob/upstream_shared/RX.cpp, https://github.com/multiwii/multiwii-firmware/blob/upstream_shared/RX.h.

    Другой человек описывал, саму работу - http://rcarduino.blogspot.com.by/, увы на английском. Есть какая-то библиотека - https://github.com/scottjgibson/RCArduinoFastLib, не проверял, написана тем же человеком.
     
  3. Megakoteyka

    Megakoteyka Оракул Модератор

    А зачем там ардуино? Поставьте приемник от RC-модели и к нему все подключайте, он для этого и придуман.
     
  4. Возможно, имелось ввиду "дальнейшая обработка" сигнала одного канала, для управления несколькими нагрузками или модификация самого сигнала для одного ус-ва.
    Сейчас мучает (от незнания принципов программирования) подобный вопрос.
    Например, такая задача :
    Серва поворота камеры управляется через приёмник по одному радиоканалу. Однако из-за "высокой отзывчивости" сервы на 180* при управлении джойстиком, плавно повернуть камеру невозможно - кадрррр дёргается и трясётся.
    Если "пропустить" через ардуинку входной ШИМ (от 1000 до 2000 мс), но замедлить скорость реакции и не просто, а "по синусоиде" - плавное нарастание до необходимой скорости поворота и плавное торможение скорости сервы ?
    Причём, с точки зрения оператора (для удобства работы), управление джойстиком имеет два варианта :
    1. поворот пропорционально углу отклонению джойстика (на пульте это гораздо нагляднее, чем на "шильдоджойстике") ;
    2. поворот в сторону наклона джойстика (лево или право от середины) с плавным нарастанием (и торможением) скорости поворота до величины, соответствующей степени наклона джойстика - чем сильнее завален, тем выше скорость "в сторону" наклона. Т.е. поворачивается, пока джойстик на пульте не верётся в середину.
    Servo library позволяет это сделать "на выходе" ардуинки, а как подключить и считать входной сигнал с приёмника (как на рисунке выше), что бы затем "обрабатывать" его?
     
    Последнее редактирование: 30 апр 2016
  5. ANV

    ANV Гуру

    Сложность зависит от того, какая у вас аппаратура. Самое простое получается если аппаратура Spektrum/JR. Тогда вместо самого приемника можно купить сателлит приемника (это не сам приемник, а дополнительный модуль приемника, который на модельке вешается подальше от основного для надежности приема, если основной в "тени" модельки). У сателлита Spektrum на выходе банально UART (т.е. serial). http://diydrones.com/profiles/blogs/orange-rx-satellite-receiver-and-lemon-rx-uart-enabled-receiver

    Для обыкновенного приемника надо измерять ширину импульса на каждом канале, но количество проводов - это количество используемых каналов.

    Есть еще sum-PPM, это когда все каналы "смешаны" в один провод
     
  6. Подскажите, будет ли работать библиотека FreqCounter Library с Ардуино Уно и где почитать её описание ? Можно ли при помощи её измерить входной ШИМ с обычного PPM приёмника для дальнейшей обработки ?
    http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/
     
  7. ANV

    ANV Гуру

    Для начала подключите один канал и читайте его через https://www.arduino.cc/en/Reference/PulseIn
    В FreqCounter не вникал, но если он возвращает частоту, то я вам ее и так скажу - 50 Герц :)))
     
  8. ANV

    ANV Гуру

  9. 2,4ГГц "обычный" передатчико-приёмник PPM. На джойстике канала - средняя точка 1500 мсек.
    Для настройки думаю использовать сервотестер.
    Само-Унка.
    http://forum.amperka.ru/threads/Самодельная-Унка.8200/
    и пара сервочек на пан-тилт (по 100 руб за кг). Собственно, для 100гр камеры - вполне справятся.

    Главное придумать алгоритм - синтаксис (т.е. объяснить задумку контроллеру) - дело наживное.
    Думается так:
    постоянно опрашиваем вход и сохраняем в переменную - в диапазоне от 1000 до 2000 мсек.
    если сигнал пропадает - она становится 1500 ("эмитируя" джойстик в середину)
    небольшие изменения (частота может "чЮть" плыть около 1-3%) игнорируем

    Далее "сама реакция замедления" :

    Вариант первый - когда поворот сервы (в любую сторону) пропорционален наклону джойстика, но повторяет его с замедленной (может регулировать скорость замедления ?) скоростью. Причём старт до максимальной скорости и торможение в конечной точке должно быть плавным.
    Тут (наверное) надо вычислить разницу между истинным углом (помнится, читал о функции, возвращающей положение сервы) и углом джойстика.
    Затем наращивать скорость сервы первые 10-15% этой разницы
    до ограничения и скорости (заданной заранее или регулируемой "внешним" потенциометром )
    и за 10-15% до "конечной точки" её снижать до ноля.

    Вариант второй - когда отклонение джойстика поворачивает серву до тех пор, пока джойстик отклонён (как бы указывая направление вращения) по тем же "алгоритмам" замедления с "мягким" стартом и "мягким" торможением. Тут максимальную скорость можно считать (т.е. задать) с угла отклонения джойстика - сильнее наклонён - быстрее поворот.
    ... Собственно, ничего невозможного нет - надо только всё подробно "спроецировать" на язык, только ....
    не торопится и последовательно и члено-раздельно :). Буду думать ...:oops:
     
  10. С вашей неоценимой помощью (мне сложно с разбегу понять - просто справочные данные в описании языка ) -
    - подключённый на седьмой пин сервотестер выдаёт на монитор от почти 900 мксек до чЮть больше 2000 мксек, что вполне соответствует "эмитации" приёмо-передатчика.
    Теперь надо разобраться с "волшебной формулой" передающей от 0* до 180* на серву и можно думать про варианты с "замедлением времени" :) .
     
  11. Странное дело - серва трясётся!...:eek:
    Монитор показывает конвульсии ШИМ во всём диапазоне измерения - в пределах от единиц до десятков.
    Думаю, это связано со способом (принципом) измерения, а не с сервотестером (напрямую подключённая серва - стабильна, как Пи (3.14...). Как быть ? :(
     
  12. ANV

    ANV Гуру

    "Монитор показывает конвульсии ШИМ" - это в serial выводите измеренные значения?
    Если так, то попробуйте "черную магию" - измерять ширину испульса через прерывания
     
  13. Да. Надо же хоть кака-то контролировать процесс - я ещё Делей на 100мксек в конце поставил, чтобы строчки не бежали.
    Думаю - может "фильтр" какой приписать - несколько рррраз замерить и ср\арифметическое снять.
    Или "шумодав" - через ИФ : если сравнивать два замера и изменять конечную переменную, только если значение отличается на величину "фильтра" - допустим 2-3%. Костыли, конечно ...
    ....Читает пульс (высокий или низкий) на булавку. Например, если значение HIGH, pulseIn () ждет штифт, чтобы высокоуровневым, начинается отсчет времени, затем ожидает штифт идти LOW и останавливает отсчет времени. Возвращает длину импульса в микросекундах или 0, если не полный импульс не был получен в течение тайм-аута....
    Собственно, чО ещё ей надо ? Есть "1", далее "0" - по фронту ведь считает (прошедшее время между именно фронтами "вниз"). Правда.....:
    Выбор времени этой функции была определена эмпирически и, вероятно, покажут ошибки в более коротких импульсов. Работы по импульсов от 10 микросекунд до 3 минут в длину.

    А у меня от 890 до 2100 мксек - и выпендривается на трёх разных севах и двух сервотестрах , серва от отдельного БП с общей землёй, Шайтан-Арба !! :oops:
    ... А
    замерить пока не умею - где почитать ? Понимаю так - будет считать относительно опорной частоты Ар-душки ?
     
  14. ANV

    ANV Гуру

    Попробуйте так:
    Код (C++):
    #define RXPIN 2

    volatile uint32_t ChannelIn;

    void setup() {
     
      pinMode(RXPIN, INPUT);
      attachInterrupt(digitalPinToInterrupt(RXPIN), calcChannel, CHANGE);
     
    }

    void calcChannel()
    {
      static uint32_t Start;
     
      if(digitalRead(RXPIN))
      {
        Start = micros();  
      }
      else
      {
        ChannelIn = (uint32_t)(micros() - Start);
      }
    }

    void loop() {
      // put your main code here, to run repeatedly:

    }
    В loop вставьте отображение переменной ChannelIn
    И в Uno прерывания есть тольно на пине 2 и 3. Соответственно RXPIN может быть только 2 или 3.
     
  15. Угу... Т.е. в блоке
    void calcChannel()
    условие на ожидание "1" на пине #define RXPIN 2
    и тогда он начинает считать время
    Start = micros();
    а кака только "0" -
    на переменной ChannelIn получатся "накопленное за это время" значение, а потом переменной Start присваивается "0" в ожидании "следующего прохода-цикла" всей программы ? :eek:
     
  16. ANV

    ANV Гуру

    Нет. Так было в варианте с PulseIn
    В этом варианте в setup вызовом attachInterrupt(digitalPinToInterrupt(RXPIN), calcChannel, CHANGE); указывается что при изменении с LOW -> HIGH или HIGH -> LOW будет вызываться функция calcChannel
    Внутри этой функции если пришел передний фронт сигнала, то запоминается время его начала. Если задний, то из текущего времени вычитается сохраненное и кладется в глобальную переменную ChannelIn.
    В этом и смысл прерываний. В loop у вас может выполняться что угодно, но когда на RXPIN изменится уровень, то выполнение loop приостановится и выполнится calcChannel
     
  17. Вах !! Сейчас я перечитаю несколько раззз ... :D

    ... "для и на" время
    выполнения блока calcChannel, так как он входит общий "бесконечный" цикл перед void loop(),
    а так "он проскакивает сквозняком" и тратит ресурс только на проверку условия ...

    - о, сколько нам открытий ...
    Надо поискать справочник... на русском :rolleyes: ...
    Не кстати :
    По первому варианту, с PulseIn, уже "типА прокатит" - там "лишь бы" вышел из зоны серединки джойстика - 1500 мксек с небольшой "мёртвой зоной реакции" - от дрожания руки или случайного прикосновения. И конвульсии "датчика" не так страшны. Но работает, конечно очень ... непредсказуемо:
    "поставил" среднее арифметическое 5-ти опросов подряд PulseIn - ну... может "чуть и отпустило", но ... чувствуется, что принцип не очень подходит для данной задачи. :oops:
     
  18. Городушки :
    Код (C++):

    #include <Servo.h>

    #define POT_MAX_ANGLE 180.0 // макс. угол поворота потенциометра

    Servo myServo;

    int pin = 7;// шим

    unsigned long duration;
    unsigned long duration0;
    unsigned long duration1;
    unsigned long duration2;
    unsigned long duration3;
    unsigned long duration4;

    void setup()
    {
      // прикрепляем (англ. attach) нашу серву к 9-му пину.
      myServo.attach(9);

       pinMode(pin, INPUT);// шим
     
       Serial.begin(9600);
       Serial.println("PPM  \  Angle");
    }

    void loop()
    {
       // Фильтр среднее арифметическое от пяти замеров пульса

       duration0 = pulseIn(pin, HIGH);// шим
       duration1 = pulseIn(pin, HIGH)+ duration0;// шим
       duration2 = pulseIn(pin, HIGH)+ duration1;// шим
       duration3 = pulseIn(pin, HIGH)+ duration2;// шим
       duration4 = pulseIn(pin, HIGH)+ duration3;
       duration = duration4 / 5;
     
         
      int val = duration-870;
      int angle = int(val / 1024.0 * POT_MAX_ANGLE);

      // углы от 0° до 180°. Ограничиваем угол соответствующе
      angle = constrain(angle, 5, 175);
      myServo.write(angle);

      Serial.print(duration);Serial.print("\t");

      Serial.print(angle);Serial.print("\t");

      Serial.println(val);

      delay(100);

    }
    Но что-то с углами (диапазоном регулирования) на... путал - иногда серва бросается в край и там засыпает намертво ... А если медленно с-тестер вращать - вроде отпускает.
    Могу видео снять - посмеяться :) .
     
  19. Ура. Работает значительно "стабильнее" - измерение частоты гуляет +- 2.
    В предыдущем варианте с пульсом +-10 ! :)

    Код (C++):
    #define RXPIN 2
    volatile uint32_t ChannelIn;

    #define POT_MAX_ANGLE 180.0 // макс. угол поворота потенциометра

    #include <Servo.h>
    Servo myServo;

    void setup() {
       pinMode(RXPIN, INPUT);
       attachInterrupt(digitalPinToInterrupt(RXPIN), calcChannel, CHANGE);
       Serial.begin(9600);
       Serial.println("PPM  \  Angle");
     
       myServo.attach(9);
     
    }

    void calcChannel()
    {
      static uint32_t Start;
      if(digitalRead(RXPIN))
      {
        Start = micros();
      }
      else
      {
        ChannelIn = (uint32_t)(micros() - Start);
      }
    }

    void loop() {
      //  main code :
     
       int val = ChannelIn-870;
       int angle = int(val / 1024.0 * POT_MAX_ANGLE);
       angle = constrain(angle, 5, 175);
     
      myServo.write(angle);
     
      Serial.print(ChannelIn);Serial.print("\t");
      Serial.print(angle);Serial.print("\t");
      Serial.println(val);
      delay(100);
    }
    Серва подрагивает на один-два градуса, но... значительно реже !
    Единственная неразбериха - диапазон поворота сервы привязан к отношению 1024 (диапазон пересчёта аналового вх - из примера с резистором на 270* градусов) :

    #define POT_MAX_ANGLE 270.0 // макс. угол поворота потенциометра
    int angle = int(val / 1024.0 * POT_MAX_ANGLE);


    А монитор показывает диапазон от 850мксек до 2100мкс
    поэтому "неожиданно" она забивается в крайние углы и там залипает :( .
    Как быть ?