Официальный сайт компании Arduino по адресу arduino.cc
ArduinoNano/Spektrum DX8/AR8000 - переключение между ручным и автоматическим управлением сервами.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Приветствую!
Имеется ардуина нано, спектрумовский приемник(AR8000) и передатчик(DX8). Также имеется 3-х осевой подвес для аэрофотосъемки. Сейчас в управлении задействованы только две оси pan и tilt, ну и плюс ИК диод для фото.
Хотелось на свободный канал повесить возможность выбора (изменением положения свободного тумблера на пульте) ручного управления сервами либо запуск автоматического цикла ардуины. С приемника выходит только ШИМ - как его обработать чтоб ардуина поняла включен тумблер на пульте или выключен?
Вот код который работает сейчас
#include <Servo.h> #include <multiCameraIrControl.h> /////////////////////////////////////////////////////////////////// // Номера входов и выходов /////////////////////////////////////////////////////////////////// int servo_gor_pin = 7; // пин для сервы горизонтального поворота камеры int servo_vert_pin = 6; // пин для сервы вертикального поворота камеры int manual_pin = 10; // пин включающий ручное управление с пульта int manual_gor_pin = 12; // вход сигнала с приёмника для горизонтальной сервы int manual_vert_pin = 11; // вход сигнала с приёмника для вертикальной сервы /////////////////////////////////////////////////////////////////// // Объекты программы /////////////////////////////////////////////////////////////////// Servo servo_gor; // создаём объект для контроля сервы горизонтального поворота Servo servo_vert; Sony nex(9); /////////////////////////////////////////////////////////////////// // Переменные программы /////////////////////////////////////////////////////////////////// boolean servo_gor_go = LOW; int posv1 = 70; int posv2 = 100; int posv3 = 50; int posr = 92; /////////////////////////////////////////////////////////////////// // Инициализация /////////////////////////////////////////////////////////////////// void setup() { pinMode(servo_vert_pin, OUTPUT); pinMode(servo_gor_pin, OUTPUT); pinMode(manual_vert_pin, INPUT); pinMode(manual_gor_pin, INPUT); pinMode(manual_pin, INPUT); servo_vert.attach(servo_vert_pin); servo_gor.attach(servo_gor_pin); Serial.begin(115200); Serial.println("Starting up!"); digitalWrite(manual_pin, HIGH); } /////////////////////////////////////////////////////////////////// // Автоматическое управление /////////////////////////////////////////////////////////////////// void ServoGor(boolean g) // функция поворота сервы горизонта { int p; if(g==HIGH) { servo_gor_go = HIGH; servo_gor.attach(servo_gor_pin); // подключаем серву горизонтальную for(p=1525; p<=1600; p++) { servo_gor.writeMicroseconds(p); delay(3); } } if(g==LOW) { servo_gor_go = LOW; for(p=1600; p>=1525; p--) { servo_gor.writeMicroseconds(p); delay(3); } servo_gor.detach(); //отключаем серву горизонтальную } } void cycle() { servo_gor.write(posr); servo_vert.write(posv2); delay(800); shutter(); delay(800); servo_vert.write(posv1); delay(800); shutter(); delay(800); ServoGor(HIGH); delay(400); ServoGor(LOW); } void shutter() { nex.shutterNow(); } void auto_loop() { for (int i=0;i<9;i++) cycle(); servo_vert.write(posv3); delay(800); shutter(); delay(800); } /////////////////////////////////////////////////////////////////// // Ручное управление /////////////////////////////////////////////////////////////////// void manual_loop() { digitalWrite(servo_gor_pin, digitalRead(manual_gor_pin)); digitalWrite(servo_vert_pin, digitalRead(manual_vert_pin)); } /////////////////////////////////////////////////////////////////// // Основной цикл /////////////////////////////////////////////////////////////////// int is_manual = 0; void loop() { if (digitalRead(manual_pin) == HIGH) { if (is_manual != 1) { Serial.println("Manual mode is on\r\n"); // Detach servo drivers if (servo_vert.attached() == true) servo_vert.detach(); if (servo_gor.attached() == true) servo_gor.detach(); is_manual = 1; } manual_loop(); } else { if (is_manual != 0) { Serial.println("Automatic mode is on\r\n"); if (servo_vert.attached() == false) servo_vert.attach(servo_vert_pin); if (servo_gor.attached() == false) servo_gor.attach(servo_gor_pin); is_manual = 0; } auto_loop(); } }
Сейчас переключение между ручным и автоматическим управлением осуществляется с помощью минисервы, которая замыкает manual_pin на землю. Серва в свою очередь подключена на свободный канал AUX. Реально ли это осуществить программно?
Буду благодарен любой помощи, ибо сам в этом смыслю поверхностно :)
И еще в догонку - при ручном управлении подергиваются все сервы. Из-за чего это может быть?
Народ, может я как-то не точно выразился? А то никакой реакции нет...
У меня на подвесе сейчас пины на землю вот так замыкаются:
Ну согласитесь - это жесть)
Сложно ардуину научить длинну импульса считать? Ну чтоб она понимала когда тумблер переключается на пульте?
Ладно.... тогда вот так поставлю вопрос:
можно ли прочитать ШИМ сигнал идущий от приемника к серве с помощью Ардуины?
Дайте хоть какуюто зацепку)
можно...
С определенной периодичностью считываете логический (т.е. 0/1) уровень сигнала на вашей ШИМ-линии, на основе полученных данных определяете длительность импульса и длительность паузы. На основании полученных данных получаете частоту ШИМ сигнала (что-то в диапазоне 450-500 Гц, вроде бы), рассчитываете скважность... А больше там и определять-то нечего.
Опроса с частотой 200-300 кГц (частота ШИМ грубо 500 Гц, да по 2 опроса на каждый из 255 шагов изменения скважности - это если ШИМ той-же Ардуинкой генерируется) хватит для вполне приличной точности.
Это если совсем просто. Захочется сложности - можете с помощью прерываний ловить фронты, а с помощью счетчиков рассчитывать длительности пульсов/пауз. На это меньше ресурсов мк потребуется, но больше ваших.
Благодарю за ответ. Мдя, для меня не просто это все... честно говоря не представляю как реализовать это программно.
Может где-нибудь встречали похожие реализации - чтоб посмотреть так сказать на примере?
Сейчас основная задача чтобы ардуина умела передавать ШИМ сигнал на сервы который идет на нее с приемника.
Сейчас основная задача чтобы ардуина умела передавать ШИМ сигнал на сервы который идет на нее с приемника.
Первое, что приходит в голову - выбросить к чертям собачьим ардуину и передавать ШИМ-сигнал с приемника прямо на сервы.
Второе, что приходит в голову, считывать сигнал с приемника любым цифровым входом ардуины и выставлять другой цифровой - но уже выход - раным состоянию на входе. Что-то типа
digitalWrite(pinOUT,digitalRead(pinIN));
Частоты сканирования в пару сотен кГц с лихвой хватит для трансляции ШИМ-сигнала с приемника через Ардуину на серву(-ы). Практически без искажений.
Первое, что приходит в голову - выбросить к чертям собачьим ардуину и передавать ШИМ-сигнал с приемника прямо на сервы.
К сожалению не получится - ардуина должна в случае чего перехватывать управление и фигашить сама сервами.
Второе, что приходит в голову, считывать сигнал с приемника любым цифровым входом ардуины и выставлять другой цифровой - но уже выход - раным состоянию на входе. Что-то типа
digitalWrite(pinOUT,digitalRead(pinIN));
Так именно так у меня и сделано :)
Но дерганья страшные.. получается же передается не ШИМ а значение HI или LOW, я правильно понимаю? А тут нужно через analogRead подходить?
Подрубил управляющий провод с канала элеватора приемника на нулевой пин дуины чтоб посмотреть какие данные он передает
Крутил стиком, крутил - по барабану, никак не реагирует... выдает периодично вот такие данные
Частоты сканирования в пару сотен кГц с лихвой хватит для трансляции ШИМ-сигнала с приемника через Ардуину на серву(-ы). Практически без искажений.
Вот тут куча вопросов - эта частота сканирования где,как и когда задается?)) Где про это почитать?
Наткнулся на интересные статьи, кстати
http://rcarduino.blogspot.co.uk/2012/04/how-to-read-multiple-rc-channels-draft.html
http://rcarduino.blogspot.ru/2012/01/how-to-read-rc-receiver-with.html
http://rcarduino.blogspot.ru/2012/11/how-to-read-rc-channels-rcarduinofastlib.html
Сижу, перевариваю потихоньку
Народ, может я как-то не точно выразился? А то никакой реакции нет...
У меня на подвесе сейчас пины на землю вот так замыкаются:
Ну согласитесь - это жесть)
Сложно ардуину научить длинну импульса считать? Ну чтоб она понимала когда тумблер переключается на пульте?
Роботизированный панорамная головка?
Вместо "этого" можно было оптроны использовать. Ну на крайни случай реле.
А с IRcontrol не заработало?
Это частота, с которой обновляется ваша функция manual_loop(), после того как вы вызываете функцию servo_gor.detach(); вывод скорее всего конфигурируется на вход, попробуйте сделать так в 144 строке:
На выходе получается, то что на входе, а по вашему ШИМ - это не HIGH и LOW? погуглите что такое ШИМ.
Если хотите считывать ШИМ и потом его генерить, то нужна не analogRead() (вообще можно и ее если добавить RC-цепь, но нафиг надо цифровой сигнал превращать в аналоговый, а потом оьратно), а функция например pulseIn() но больше чем уверен, что получится полная ж..а, так как pulseIn() блокирующая функция.
Если все равно дергается и у вас дуина Нана, то можно попробовать увеличить частоту опроса, замените свою функцию manual_loop(), вот на эту:
Вот тут куча вопросов - эта частота сканирования где,
в вашей программе, естественно
Разными способами:
- можно настроить таймер на определенную частоту и в соответствующем прерывании таймера запускать АЦ-преобразование;
- можно следить за "часами" мк (millis(), micros()) и в определенные моменты времени запускать АЦ-преобразование;
- можно вызывать АЦ-преобразование в цикле: сканирование будет производиться с частотой, которую может обеспечить ваш цикл.
Как узнать, с какой частотой выполняется сканирование? В первых двух случаях вопрос не имеет смысла. В третьем случае запомните время перед циклом, выполните 1000 опросов, опять считайте значение времени, поделите разницу значений на 1000 и получите длительность одного цикла сканирования. Обратное этой величине значение будет частотой сканирования.
когда требуется
Интернет, книжки...
Роботизированный панорамная головка?
Вместо "этого" можно было оптроны использовать. Ну на крайни случай реле.
А с IRcontrol не заработало?
Можно сказать и так :) Точнее летающая роботизированная головка :)
О, оптроны, точно ... можно заморочиться)
IRcontrol это что - библиотека, устройство?
вывод скорее всего конфигурируется на вход, попробуйте сделать так в 144 строке:
Сделал, дергается также..
На выходе получается, то что на входе, а по вашему ШИМ - это не HIGH и LOW?
Не ну понятно что HIGH и LOW, но там же скважность еще - дуинка ее не "гробит" при такой передаче?))
но нафиг надо цифровой сигнал превращать в аналоговый, а потом оьратно
Золотые слова! Я тоже так думаю - но вот не знаю как реализовать
Если все равно дергается и у вас дуина Нана, то можно попробовать увеличить частоту опроса, замените свою функцию manual_loop(), вот на эту
Прошу прощения, дуинка ругается на имена портов - что не так?
Спасибо за помощь! ;)
Разными способами:
Спасибо, буду копать)
Версия IDE причиной тому может быть.
Вот не пойму, почему в последующих версия IDE больше косяков, чем в предыдущих...
В общем тогда так:
И кстати, как раз вот таким способом и получится добиться тех самых пары сотен кГц и еще раз повторюсь, так работать будет, только на Нане, Уне, Демеланове (на всех с ATmega328/168), на Меге, Леонарде и т.д. работать не будет.
Вот это да! Все заработало идеально, спасибо maksim
Когда от usb питание идет - вообще нет подергиваний, а вот когда от липошки с беком тогда дергаться опять начинают... пересмотрю цепь питания - может от бека наводки идут %)
IRcontrol это что - библиотека, устройство?
Это ваша библиотека multiCameraIrControl.h (я просто сократил) с ней я так понял не заработало и вы поставили серву на фокусировку и спуск.
Почему, работает - серва замыкает пин и пошла команда ИК диоду)) просто опять же - мне нужно чтоб можно было с пульта спуск осуществлять и чтоб автоматом шло. В панорамном цикле отлично ИК отрабатывает. А так - стик рудера вправо и фоткает) стик влево - панорама пошла) Вот такой колхоз)
Что я не пойму что у вас серва зымыкает?
На землю замыкает пин - на фотограии контактная площадка перед сервой, к ней ноль подведен, а к качельке подведены провода с пинов ардуины (через 1,2 кОм резисторы)
10 пин - включение панорамного цикла
4 пин - включение диода (в этом коде его нет)
Жесть, тогда оптроны не помогут, я думал этой сервой дуина управляет.
А зачем диод подключать?
На пульте ДУ есть настройки каналов? Можно канал настроить как цифровой?
не) пультом требуется - в этом то все и дело :) Вот я и спрашивал как дать понять ардуинке что например тумблер на канале AUX 1 включен в нейтральное полложение, а когда в 1, а когда в 2. Тогда можно было бы с пульта напрямую пинами управлять
Диод нужен для спуска затвора, а изменить канал на просто цифру вроде нельзя, сейчас покопаюсь в настройках
Так а что в описании написано? что идет с приемника на канале AUX 1 ? тоже ШИМ? и вы как раз к нему серву подключили?
Диод нужен для спуска затвора, а изменить канал на просто цифру вроде нельзя, сейчас покопаюсь в настройках
Опять ничего не понял, вы же для спуска затвора используете библиотеку ...IRcontrol зачем диод физически отключать от дуины?
Ну вообще идет ШИМ - так как серву просто включаешь в приемник и все, можно тумблером рулить. Положение 1 - примерно 30 градусный поворот сервы, положение 2 - еще на 30 градусов повернулась
сейчас доку поищу по пульту
Смотрите, диод подключен к дуине на 9 пин (в коде прописан)
Он работает нормально, дуина им управляет когда отщелкивает панорамы
Но когда ручное управление подвесом, мне нужно чтоб я мог с пульта фотографировать. У меня идет видео с борта через видеопередатчик, полностью ручное управление - чтоб сделать кадр, мне нужно отдать команду ардуине. Т.е. я корочу 4 пин для того чтоб ардуина поняла что нужно делать цикл shutter()
С сервой понятно, а попробуйте настроить углы побольше, есть такая возможность?
да углы можно побольше настроить - а что это даст?
Смотрите, диод подключен к дуине на 9 пин (в коде прописан)
Он работает нормально, дуина им управляет когда отщелкивает панорамы
Но когда ручное управление подвесом, мне нужно чтоб я мог с пульта фотографировать. У меня идет видео с борта через видеопередатчик, полностью ручное управление - чтоб сделать кадр, мне нужно отдать команду ардуине. Т.е. я корочу 4 пин для того чтоб ардуина поняла что нужно делать цикл shutter()
Тот вариант, который я вам предложил в ручном режиме будет управлять только двумя сервами, shutter()'а не будет. Если конечно вы не засунули его в тот же цикл, где ручное управление сервами.
Код покажите весь.
да углы можно побольше настроить - а что это даст?
Это даст больший разброс в микросекундах при считывании сигнала с приемника дуиной.
Код с ручным управлением ИК диода на другой машине, и фота с ИК нет чтоб проверить но вроде так работает.
В цикле loop прописываем
Вот полный код, который сейчас, с вашими правками
Подключаете вывод приемника к 2 выводу дуины (учтите, что у приемника и дуины должна быть общая земля) и заливаете это и смотрите в сериал мониторе как меняется значение при разных положениях тумблера.
нули только выдает
прошу прощения!
1900/1500/1100
круто! :)
Ну и остается только добавить это дело в код:
Огромное спасибо за помощь, maksim
С утра доберусь до ардуины, заодно захвачу фот с ИК и все проверю.
Честно, я долго ковырял инет по этому вопросу - в рунете вообще голяк, а на забугорных аналогичного решения я не нашел (хотя может и хреново искал - с моим то знанием инглиша) - очень благодарен вам что уделили время. Думаю многим это очень пригодится!
Еще один нюанс! :)
После некоторых раздумий, все же решил разнести на разные каналы переключение режима съемки и спуск затвора.
Потому что можно случайно перещелкнуть не туда и пойдет цикл автосъемки - а когда снимаешь с коптера то каждая секунда на счету :)
Так вот, maksim, сейчас попробывал по вашей аналогии опросить AUX 1 четвертым пином ардуины, полезли страшные цифры, я испугался и выключил :))
Проблема в том что я не правильно обратился к порту или к этому порту вообще нельзя обращаться таким образом?
Вроде согласно вот этому описанию, 4 пину соответствует PD4..
Опрашивал вторым пином - выдает данные идентичные AUX 2
Дело в том, что внешние прерывания есть только на 2 и 3 выводах.
ага! теперь понятно, спасибо) Сейчас попробую задействовать 3-й пин
То-есть вам нужно копировать функцию Mode назвав например Mode1, поменяв в ней на PIND&1<<3. В сетапе сконфигурировать прерывание 1, указав функцию Mode1 и объявить свои переменные например time1 и time_prev1.
То-есть вам нужно копировать функцию Mode назвав например Mode1, поменяв в ней на PIND&1<<3. В сетапе сконфигурировать прерывание 1, указав функцию Mode1 и объявить свои переменные например time1 и time_prev1.
ага, ясно
Странно, подключил 3-ий пин - нули возвращает
Вроде же негде ошибиться?
А изменить номер прерывания? Еще раз внимательно прочтите первый обзац по выше указанной ссылке.
Прошу прщения - подумал это относится только к общей программе :)
Изменил, все заработало. Сейчас доделаю программу)
Не хочет нормально скетч фунциклировать :(
По логике в основном цикле нужно просто переменную time заменить на time1 перед вызовом shutter() и все... но почему-то начинает отрабатываться автоматическое управление при подаче питания. Оба тумблера на пульте в положении 1900.
Смотрите что получается. У нас в ручном режиме замкнутый цикл, в котором проверяется только переменная time и не проверяется time1, тоесть shutter() будет выполняться только тогда когда мы выйдем из ручного режима, поэтому проверку time1 нужно засунуть в цикл ручного управления.
Еще очень много if'ов в основном цикле что можно запутаться. Можно избавиться от проверки подключена серва или нет, так как ручное управление это цикл, то до этого цикла и после код будет выполняться один раз и поэтому можно не проверять подключение сервы.
Чтобы не начаналось с автоматического цикла при объявлении переменных time и time1 присвойте им сразу значение 1900, иначе дуина еще не успевает их расчетать, а в условии они уже проверяется.
И еще по поводу shutter'а в цикле ручного управления - может происходить так, что shutter выполняется давольно продолжительное время и сервы могут из-за этого дергаться.
Путем добавления задержки в шаттер получилось добиться срабатывания затвора, но с питанием серв все осталось как прежде...
Подтверждаются ваши слова про длительность шаттера, но он полностью перекрывает управление сервами
Задержку delay(2000); перенесите в самый конец функции setup(), а вместо задержки после shutter() можно сделать так