RC передатчик и Arduino UNO

Тема в разделе "Глядите, что я сделал", создана пользователем pyro, 14 фев 2013.

  1. pyro

    pyro Гик

    Доброго дня Вам, уважаемые форумчане.
    Имея у себя, 5 - канальную RC аппаратуру решил подружить ее с контролером. Чтобы в будущем, иметь возможность ручного управления вот этим чудом. А так как я только учусь, поставил перед собой еще две задачи. Разделить программу на функции и помигать светодиодами без "delay", и не одним, а пятью сразу. 1-5 каналы RC приемника подключены соотвественно ко 2-6 ринам, сконфигурированным как входы, светодиоды 8-12. Для тех кто не знает, выходной сигнал у приемника такой же как входной у сервомашинки, подробнее здесь. Порядок работы такой: ручка управления в центре - светодиод горит, в низу - мигает 1 раз в секунду, в верху - мигает 2 раза в секунду, и так для каждого канала.

    Код (Text):
    int time[5] = {0,0,0,0,0}; //массив значений задержек
    unsigned long previousMillis [5]= {0,0,0,0,0}; //массив значений начала задержки
    int led[5] = {0,0,0,0,0}; //массив значений состояния LED
    int p; //переменная вызова функции pulseLength()
    int l; //переменная вызова функции Led()
    void setup() // инициализация портов
    {
      for (int x = 2; x < 7; x++)
      {
        pinMode(x, INPUT);
      }
      for (int x = 8; x < 13; x++)
      {
        pinMode(x, OUTPUT);
      }
     
    }
    //********** процедура считывания длительности импульса*********
    int pulseLength()
    {
      for (int x=0; x<5; x++)  //задаем номер канала
      {
        int pulseWidth = pulseIn (x+2, HIGH, 20000);  //измеряем длительность импульса, записываем в массив
        if (pulseWidth > 1200 || pulseWidth < 1700) time[x] = 0; //присваиваем значение задержки
        if (pulseWidth < 1200) time[x] = 1000;
        if (pulseWidth > 1700) time[x] = 500;
      }
      return p;
    }
     
    //****************Процедура обработки LED***********
    int Led()
    {
      for (int x=0; x<5; x++) // номер канала
      {
        if (time[x] == 0) //если стик в цетральном положении Led включен
        {
          led[x] = 1;
          digitalWrite(x + 8, led[x]);
        }
        else
        {
          int Millis = millis() - previousMillis[x]; //если нет - находим значение задержки
     
          if ((Millis) > time[x]) //если больше заданного
          {
            led[x] = !led [x]; //инвертируем значение состояния Led
            digitalWrite(x+8,led[x]);
            previousMillis[x] = millis(); //обновляем значение начала задержки
          }
        }
      }
    }
    //**************** Программа**************
    void loop() // программа, применяющая поученные значения
    {
      p = pulseLength(); //вызываем функцию измерения длительности импульса
      l = Led(); //вызываем функцию обработки Led
    }
     
     
     
     
     
     
     
  2. nailxx

    nailxx Официальный Нерд Администратор

    Спасибо, что поделились. Может оказаться крайне полезным сниппетом.
     
  3. triada13

    triada13 Нуб

    Pyro а можно схему подключения приемника и дуины глянуть?
     
  4. pyro

    pyro Гик

    20130214_211405.jpg
    Это фото комплекта. Приемник 8-ми канальный. Имеет восемь трехпиновых разьема, сверху вниз 1-8 канал. Слева на право сигнал, 5В, земля, как у серво, которые туда и подключаются.
    IMG_20130214_211652.jpg
    Cигнальные пины подключены к цифровым входам со 2 по 6, +5В и земля к соответствующим пинам у Дуни.
     
    Megakoteyka и nailxx нравится это.
  5. Modelist32

    Modelist32 Нуб

    Привет! Ребята, кто нибудь этот код на сервы перекладывал?
    pyro как поживает шестиногий на р\у
    Почему онтересуюсь, потому что сам хочу нечтоподобное сделать. С радиоуправлением я на ты, а вот с ардуино проблемы, поэтому и спрашиваю у вас.
    буду рад если кто чем поможет :)
     
  6. pyro

    pyro Гик

    Паук ждет деталей, механика нуждается в переделке.
    Объясните , что конкретно вам нужно, управлять одной серврой на кнал или группой серв?
    У меня такая же проблемма, с дуней познакомился пол года назад, пытаюсь писать разный код, в надежде, как нибудь в будущем, применить его в более серьезной программе.
     
  7. Modelist32

    Modelist32 Нуб

    Меня заинтересовали роботы на пульте управления, я стал изучать эту тему...
    Для понятия принципа написания программы сначала пример управления одной сервой.
    Так вот все роботы выполняют действия уже заранее заложенные у них в программе, а сигнал на начало той или иной программы поступает с пульта. Например как я понял, на примере Phantom X (шестиногий) в самом скетче к этому роботу записаны только поверхностная шапка, тоесть при нажатии этой кнопки, запускается движение вперед, это например. А уже в библиотеке к этому скетчу записаны все движения серв, которые подразумеваются под словом "вперед". Это мое предположение, прав я или нет я не знаю...
    Я нашел программу этого Phantoma X библиотеки к нему, но при компиляции программы выскакивают ошибки...вот из-за этого не могу продвинутся дальше.
    Теперь вернемся к ответу на вопрос. Я хотел понять как написать скетч, чтобы при команде с RC пульта ардуино включало последовательность движений нескольких серв. Если понять как это сделать, то уверяю Вас. Дальше внешний вид и функционал роботов ограничится только фантазией. Все что искал в нете, я нашел как управлять светодиодами с RC пульта, но чё-то это мне не помогло....
    Буду рад помощи) Нужен пример программы.
     
  8. Modelist32

    Modelist32 Нуб

    или ссылки, где по этой теме пишут... Судя по всему в России, до этого очень далеко...мало интересующихся людей.
     
  9. Megakoteyka

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

    Поскольку аппаратура радиоуправления для моделей заточена под управление сервами, на них идет ШИМ-сигнал. Для того, чтобы передать модели некую программу действий, нужно сделать полноценный канал - чтобы передавались данные в виде байтов, а не скважности ШИМа.
    Например, вот. А контроллер модели уже должен перевести "программу движения" в конкретные команды сервам. Кроме того, Вы получите радиоканал, по которому можно передавать любые данные, а не только команды сервам. А если сделать еще и обратный канал, то можно до кучи телеметрию с модели снимать.
    Можно и поизвращаться с имеющейся аппаратурой - представить 8 каналов пульта как 8 бит байта и передавать байты, меняя скважность на соответствующих каналах (будет заморочка с синхронизацией, но она вполне решаема). Только скорость передачи данных при этом будет невысока и обязательно понадобится пакетный протокол (он в любом случае понадобится, помехи в радиоканале еще никто не отменял).
     
  10. roggedhorse

    roggedhorse Гик

    Вы хотели сказать "выходной сигнал приемника как и входной у сервы" ?
    И если я верно понял затею, то необходимо написать декодер ШИМ-сигналов, поступающих на ноги Ардуины. Верно ?

    На мой взгляд проблему преобразования ШИМ-сигнала многоканального приемника в цифровой сигнал (байты или последовательности байтов) простым циклом в loop() и pulseIn() не решить. Усложнение проекта потребует дополнительного кода. Дополнительный код вызовет закономерные задержки в цикле pulseLength(), что в свою очередь вызовет ошибки трансляции ШИМ в команды.
    Мне кажется, нужно отказаться от pulseIn, подключить приемник к ногам, понимающим прерывания PCINT (pin change) и декодер ШИМ построить исключительно на прерываниях.
    В таком случае какой бы сложный не был остальной код, декодер ШИМ будет выполнять свою работу на пять с плюсом
     
  11. cybertesla

    cybertesla Нуб

    эх я только собрался купить недорогое 4х канальное RC управления для своей будущей платформы на шаговиках. а тут такое=(
    придётся чёто выдумывать с 433mhz
     
  12. pyro

    pyro Гик

    Все зависит от основного кода, для управления светодиодами быстродействия вполне хватает.
    И для паука, думаю хватит, тем более, что для него это только дополнение. На прерываниях, оно конечно, гораздо лучше, но где их взять то. У UNO их всего два, но каналов то - пять.
    Я намеренно разделил программу на отдельные функции, поэтому достаточно написать такую, которая будет отвечать за последовательность действий нужных вам.
     
  13. roggedhorse

    roggedhorse Гик

    Согласно первоисточника http://arduino.cc/en/Hacking/PinMapping168 практически на каждую ногу ATmega 328 можно повесить прерывание

    [​IMG]

    В скобочках указаны Alternate Pin Functions. Там где PCINT, там можно заюзать прерывание
     
  14. pyro

    pyro Гик

    Попробуйте присмотреться к этому.
     
  15. pyro

    pyro Гик

    Кто подсказать может, как сделать прерывание на аналоговых входах?
     
  16. roggedhorse

    roggedhorse Гик

    Если на ноге можно назначить прерывание типа Pin Change Interrupt,
    ищите в даташите на МК регистры типа PCMSK.
    В данном случае их три. Каждый отвечает за обслуживание того или иного прерывания PCINT. Прерывания PCINT сгруппированы. Всего три группы. Каждая группа разрешается отдельно установкой бита в регистре PCICR.

    Найдите интересующее вас прерывания в одном из регистров PCMSK.
    Например, прерывание PCINT12 (аналоговый вход 4) мы найдем в регистре PCMSK1.
    В этом регистре маскируются прерывания с 8 по 14.

    Далее нужно разрешить группу прерываний, к которой относится PCINT12, в регистре PCICR.

    Код (Text):
    void _PCINT12Enable() {
        PCMSK1 |= _BV(PCINT12);
        PCICR  |= _BV(PCIE1);
    }
     
    void _PCINT12Disable() {
        PCMSK1 &= ~(_BV(PCINT12));
        PCICR  &= ~(_BV(PCIE1));
    }
     
    Готово

    Обратите внимание на следующий факт:
    поскольку прерывания сгруппированы в три группы, на каждую группу прерываний свой обработчик: PCIE0, PCIE1, PCIE2

    То есть, если вы назначили прерывания PCINT12, PCINT13 и PCINT5, то прерывания 12 и 13, вызванные внешними факторами, будут обрабатываться обработчиком ISR(PCIE1), а прерывание PCINT5 обработчиком ISR(PCIE0).
    Соответственно, когда будет вызван обработчик ISR(PCIE1), в его теле вам нужно проанализровать, что явилось источником этого вызова: PCINT12 или PCINT13. (в теории два события могли произойти одновременно или достаточно быстро - быстрее, чем такт процессора. Учитывайте это)

    И кроме того, обработчик PCINT вызывается 2 раза: когда пин изменил значение с LOW на HIGH и когда произошел обратный процесс.


    На самом деле все очень просто! Когда вы почувствуете это, больше не останется преград :)
     
  17. roggedhorse

    roggedhorse Гик

    У меня есть сервы, регуляторы БК-двигатели и сами БК-двигатели, есть приемник, но нет передатчика.
    Все думал, как же без него.
    Вспомнил, что мне не нужен RC-передатчик :)
    У меня же есть Ардуино.

    Взял пример Джереми Блюма из фильма "5-я серия - Моторы и транзисторы".
    Подключил серву к своей UNO. Серва ожила.
    Потом отключил и убрал серву, а ногу Digital pin 9 соединил с Analog in 4.

    Залил вот этот скетч:

    Код (Text):
    #include <Servo.h>
    int servoPin = 9;
    Servo servo;
     
    void _PCINT12Enable() {
        PCMSK1 |= _BV(PCINT12);
        PCICR  |= _BV(PCIE1);
    }
     
    void setup() {
      servo.attach(servoPin);
      DDRB |= _BV(5); // Эквивалент pinMode(13, OUTPUT);
      _PCINT12Enable();
    }
     
    void loop() {
      for (int i = 0; i <=180; i++) {
        servo.write(i);
        delay(10);
      }
    }
     
    // Обработчик PCINT12
    ISR(PCINT1_vect) {
      // Если на ноге Analog in 4 уровень HIGH - зажечь диод L
      // Если на ней же уровень LOW - потушить диод
      if (PINC & 0x10) PORTB |= _BV(5); else PORTB  &= ~(_BV(5));
      // операцией PINC & 0x10 мы проверяем состояние бита 4 регистра C, который в соответствии с Pin Mapping Arduino Uno и есть Analog input 4
    }
     
    Servo.write(i); каждые 10 миллисек пишет новое значение в серву на ноге 9 (которой там уже нет).
    Сигнал с ноги 9 убегает на ногу Analog in 4.
    Соответственно при любом изменений состояния на ноге 9 LOW->HIGH или HIGH->LOW
    вызывается обработчик ISR(PCINT1_vect).
    Соответственно яркость светодиода L будет изменяться пропорционально скважности ШИМ на ноге 9.
    Проверьте, это действительно так :)

    Остается в обработчике написать мерялку скважности и мы получим надежный декодер ШИМ в числовое значение (которое потом можно будет записать в другую серву командой Servo.write)

    Соответственно, станет возможным подключить модельный пульт к Ардуине и читать состояние рычагов
     
  18. pyro

    pyro Гик

    Кто-нибудь знает про вот эту штуку что-нибудь?
     
  19. pyro

    pyro Гик

    К сожалению, я пока не дружу с "С" для AVR. Только, только познакомился с "Wiring" для дуньки.
    Может есть способ вызвать прерывание на аналоговой ноге, пользуясь только стандартными командами Arduino.
     
  20. roggedhorse

    roggedhorse Гик

    Стандартные средства позволяют вызывать стандартные прерывания. На UNO их всего два, кажется.

    Я вот подумываю над тем, а не озадачиться ли и не написать ли многоканальный ШИМ-декодер на Ардуино чтобы можно было подключать R/C-пульт к ней и считывать положения джойстиков ?