Недавно я работал над проектом, и это был первый проект, который был достаточно сложным, чтобы усложнить сенсорную сеть. В конце концов, я думаю, что общение было узким местом с точки зрения общей производительности, и мне интересно, как более опытные люди решили бы эту проблему. Это долгое чтение, но я думаю, что это довольно интересно, поэтому, пожалуйста, придерживайтесь его. Задача состояла в том, чтобы спроектировать автономный дирижабль, способный преодолевать полосу препятствий и сбрасывать шары для пинг-понга в коричневые мишени. Поехали:
датчиков
- Модуль камеры 4D Systems uCAM-TTL - интерфейс UART
- Цифровой компас HMC6352 - интерфейс I2C
- Maxbotix Sonar ez4 - 1-контактный аналоговый интерфейс
исполнительные
- 2 драйвера мотора L293D (подключенные к простым моторам для хобби) - они использовались для двунаправленного управления 6 моторами. Для изменения скорости потребовались входы ШИМ. Теперь 3 наших мотора всегда делали одно и то же (те, которые контролировали движение вверх / вниз), поэтому им требовалось только 2 выхода ШИМ от наших контроллеров для управления всеми 3 моторами. Все остальные 3 мотора, которые контролировали боковое движение, нуждались в индивидуальном управлении (для всенаправленного движения), поэтому для наших контроллеров потребовалось еще 6 выходов ШИМ.
- Серводвигатель - ШИМ интерфейс
Контроллеры
По причинам, которые станут понятны позже, мы использовали 2x ATmega328P. Мы использовали Arduino Uno для их программирования (у нас не было доступа к интернет-провайдеру), но мы создали специальную печатную плату, поэтому нам не пришлось использовать платы Arduino, поскольку это просто добавило бы ненужный вес нашему дирижаблю. Что касается того, почему мы выбрали ATmega328P, я был очень хорошо знаком со средой arduino, и я думаю, что это сделало разработку кода намного быстрее и проще.
Связь и обработка
- 2x Xbee Basic
- 2x ATmega328P
- Настольный компьютер под управлением C ++ с openCV
Как вы можете видеть из модуля камеры, большая часть нашего проекта была основана на компьютерном зрении. Дирижабли могли нести только такой большой вес, и нам было неудобно внедрять компьютерное зрение на микроконтроллере. Итак, в итоге мы использовали XBee для передачи данных изображения обратно на настольный компьютер. Таким образом, на стороне сервера мы получили данные изображения и использовали openCV для обработки изображения и извлечения из него информации. Теперь серверной части также нужно было знать информацию о высоте (от сонара) и информацию о компасе.
Первая проблема была в том, что мы не смогли управлять камерой с помощью микроконтроллера по нескольким причинам. Основная проблема заключалась в том, что внутренняя память в uP не могла справиться с сохранением всего кадра. Возможно, были способы обойти это с помощью умного кодирования, но для целей этого вопроса давайте представим, что это было невозможно. Таким образом, чтобы решить эту проблему, нам пришлось отправлять команды камеры через приемопередатчик XBee, а приемник XBee (на борту дирижабля) имел выход, подключенный к входу камеры.
Следующей проблемой было то, что на одном ATmega328P недостаточно PWM для управления всеми двигателями, ПОТОМУ ЧТО интерфейс I2C использует один из выводов PWM (чёрт возьми ...). Вот почему мы решили использовать второй. Код на самом деле идеально подходил для параллельной обработки, так как контроль высоты был полностью независим от управления боковым движением (поэтому 2 микро были, вероятно, лучше, чем один, подключенный к ШИМ-контроллеру). Поэтому U1 отвечал за 2 выхода ШИМ (вверх / вниз) и за чтение сонара. U2 отвечал за чтение компаса, управление 6 выходами ШИМ (боковые двигатели), а также считывание сонара. U2 также отвечал за получение команд с сервера через XBee.
Это привело к нашей первой проблеме общения. Линия XBee DOUT была подключена как к микроконтроллеру, так и к камере. Теперь, конечно, мы разработали протокол так, чтобы наши микрокоманды игнорировали команды камеры, а команды камеры игнорировали микрокоманды, и это было хорошо. Однако камера, игнорируя наши микрокоманды, отправит обратно данные NAK на своей выходной линии. Так как команда предназначалась для микро, нам нужно было как-то отключить выход камеры на XBee. Чтобы решить эту проблему, мы сделали микропроцессорные 2 полевых транзистора, которые были между камерой и XBee (то есть первым полевым транзистором), а также между U2 и XBee (то есть вторым полевым транзистором). Поэтому, когда камера пыталась отправить информацию обратно на сервер, первый FET был «включен», а второй FET был «выключен».
Итак, чтобы дать вам представление о том, как это работает, вот несколько примеров:
- Сервер запрашивает изображение - PIC_REQUEST проходит через XBee и достигает U2 и камеры. U2 игнорирует это, и камера отправляет обратно данные изображения.
- Сервер только что завершил обработку изображения и отправляет данные двигателя, чтобы дать команду blimp повернуть направо - MOTOR_ANGLE (70) проходит через XBee и достигает U2 и камеры. U2 распознает как микрокоманду и, таким образом, отключает FET камеры (но, возможно, камера уже ответила NAK, кто знает ...). Затем U2 отвечает на команду, изменяя выходы ШИМ двигателя. Затем он снова включает FET камеры (это была настройка по умолчанию, поскольку данные изображения были наиболее важными).
- Сервер понимает, что мы достигли точки в полосе препятствий, где наша высота зависания по умолчанию теперь должна составлять 90 дюймов вместо 50 дюймов. SET_HEIGHT проходит через XBee, и происходит то же самое, что и в примере 2. U2 распознает команду SET_HEIGHT и запускает прерывание на U1. U1 теперь выходит из цикла контроля высоты и ожидает получения последовательных данных от U2. Это верно, больше последовательных данных. В этот момент FET U2 включен (и FET камеры выключен), поэтому сервер получает высоту, которую U2 также посылает в U1. Это было в целях проверки. Теперь U1 сбрасывает свою внутреннюю переменную для height2HoverAt. U2 теперь выключает FET и снова включает FET камеры.
Я определенно пропустил большое количество информации, но я думаю, что этого достаточно, чтобы понять некоторые сложности. В итоге наши проблемы просто синхронизировали все. Иногда в буферах оставались данные, но только 3 байта (все наши команды имели последовательность из 6 байтов). Иногда мы теряем связь с нашей камерой и вынуждены повторно синхронизировать ее.
Итак, мой вопрос: какие методы вы, ребята, предложите, чтобы сделать связь между всеми этими компонентами более надежной / надежной / простой / лучше?
Например, я знаю, что можно было бы добавить схему задержки между встроенным выходом XBee и камерой, чтобы у микроконтроллера была возможность отключить линию разговора камеры, прежде чем она ответит на микрокоманды с помощью NAK. Любые другие идеи, как это?
Спасибо, и я уверен, что это потребует много правок, так что следите за обновлениями.
Edit1:Соединение данных UART камеры через одну из микросхем не казалось нам возможным. Было два варианта для данных камеры, сырой битовой карты или JPEG. Для необработанного растрового изображения камера просто отправляет данные вам так быстро, как может. ATmega328P имеет только 128 байтов для последовательного буфера (технически это настраивается, но я не уверен, как), и мы не думали, что сможем вытащить его из буфера и через XBee достаточно быстро. Это оставило метод JPEG, где он отправляет каждый пакет и ждет, пока контроллер подтвердит его (маленький протокол рукопожатия). Быстрее всего это было 115200 бод. Теперь по какой-то причине самая быстрая надежная передача больших объемов данных через XBee составила 57600 бод (это даже после того, как мы установили соединение между узлом и сетью, чтобы обеспечить возможность автоматической повторной отправки). Добавление дополнительной остановки в нашей сети (от камеры к микро-устройству для XBee, а не только от камеры к XBee) для микро-устройства просто замедляет время, необходимое для передачи слишком большого количества изображения. Нам нужна была определенная частота обновления изображений, чтобы наш алгоритм управления двигателем работал.