Довольно сложная сенсорная сеть

9

Недавно я работал над проектом, и это был первый проект, который был достаточно сложным, чтобы усложнить сенсорную сеть. В конце концов, я думаю, что общение было узким местом с точки зрения общей производительности, и мне интересно, как более опытные люди решили бы эту проблему. Это долгое чтение, но я думаю, что это довольно интересно, поэтому, пожалуйста, придерживайтесь его. Задача состояла в том, чтобы спроектировать автономный дирижабль, способный преодолевать полосу препятствий и сбрасывать шары для пинг-понга в коричневые мишени. Поехали:

датчиков

  • Модуль камеры 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 был «выключен».

Итак, чтобы дать вам представление о том, как это работает, вот несколько примеров:

  1. Сервер запрашивает изображение - PIC_REQUEST проходит через XBee и достигает U2 и камеры. U2 игнорирует это, и камера отправляет обратно данные изображения.
  2. Сервер только что завершил обработку изображения и отправляет данные двигателя, чтобы дать команду blimp повернуть направо - MOTOR_ANGLE (70) проходит через XBee и достигает U2 и камеры. U2 распознает как микрокоманду и, таким образом, отключает FET камеры (но, возможно, камера уже ответила NAK, кто знает ...). Затем U2 отвечает на команду, изменяя выходы ШИМ двигателя. Затем он снова включает FET камеры (это была настройка по умолчанию, поскольку данные изображения были наиболее важными).
  3. Сервер понимает, что мы достигли точки в полосе препятствий, где наша высота зависания по умолчанию теперь должна составлять 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) для микро-устройства просто замедляет время, необходимое для передачи слишком большого количества изображения. Нам нужна была определенная частота обновления изображений, чтобы наш алгоритм управления двигателем работал.

NickHalden
источник
3
Вы прикладываете много усилий, чтобы не расширять свои навыки работы с микроконтроллерами. Я ничего не имею против Arduino, но это не очень подходит для этого. Можете ли вы в конечном итоге заставить его работать? Вероятно. Однако было бы гораздо полезнее изучить более способную платформу. Если вы спросите, как бы это сделали более опытные люди, я бы сказал что-то вроде ARM SBC для openCV и управления, и FPGA, служащую мостом для всех интерфейсов. Тем не менее, это было бы небольшим скачком, поэтому я бы предложил просто попробовать одну новую важную вещь ... может быть, 32-битный микро с достаточным количеством периферийных устройств для взаимодействия со всем?
Даррон
Хаха, я собирался на многое. Увидеть, что этот проект был школьным заданием, и мы хотели сосредоточиться на том, чтобы заставить его работать, а не заставлять одного из двух EE в команде изучать новую платформу микроконтроллера. Я думаю о том, чтобы этим летом заняться ARM и более продвинутыми микрофонами. Другой EE в нашей команде на самом деле брал урок в FPGA ... Я буду кричать на него за то, что он не предположил, что = P
NickHalden

Ответы:

4

Я понимаю, что вы хотели выбрать среду разработки, с которой вы были знакомы, так, чтобы вы могли приступить к работе, но я думаю, что компромисс между аппаратным и программным обеспечением, возможно, поставил вас в тупик, придерживаясь Arduino и не выбирая деталь, которая имела все аппаратные периферийные устройства, которые вам нужны, и вместо этого записывать все в C на основе прерываний.

Я согласен с предложением @Matt Jenkins и хотел бы расширить его.

Я бы выбрал ОК с 2 UART. Один подключен к Xbee, а другой - к камере. ОК принимает команду от сервера, чтобы начать чтение камеры, и может быть написана подпрограмма для передачи данных из канала UART камеры в канал XBee UART на основе байтов на байт - поэтому нет буфера (или, самое большее, только очень маленький). один) нужен. Я бы попытался исключить все другие ОК, выбрав деталь, которая также удовлетворяла бы всем вашим потребностям в ШИМ (8 каналов ШИМ?), И если вы хотите придерживаться 2 разных ОК, заботящихся об их соответствующей оси, то, возможно, другой интерфейс связи был бы лучше, так как все ваши другие UART были бы заняты.

Кто-то еще также предложил перейти на встроенную платформу Linux, чтобы запустить все (включая openCV), и я думаю, что это тоже было бы чем исследовать. Впрочем, я был там раньше, 4-месячный школьный проект, и вам просто нужно сделать это как можно скорее, его невозможно остановить из-за паралича из-за анализа - я надеюсь, что он для вас все же хорошо!


РЕДАКТИРОВАТЬ # 1 В ответ на комментарии @JGord:

Я сделал проект, который реализовал переадресацию UART с ATmega164p. Он имеет 2 UART. Вот изображение из захвата логического анализатора (логический анализатор USB Saleae) этого проекта, показывающего пересылку UART: захват анализатора

Верхняя строка - это исходные данные (в данном случае это будет ваша камера), а нижняя строка - канал UART, на который направляется (XBee в вашем случае). Процедура, написанная для этого, обрабатывает прерывание приема UART. Теперь, поверите ли вы, что во время этой переадресации UART вы могли бы с радостью настроить ваши ШИМ-каналы и обрабатывать свои подпрограммы I2C? Позвольте мне объяснить, как.

Каждое периферийное устройство UART (для моего AVR в любом случае) состоит из пары сдвиговых регистров, регистра данных и регистра управления / состояния. Это оборудование будет работать самостоятельно (при условии, что вы уже инициализировали скорость передачи данных и т. Д.) Без какого-либо вмешательства, если либо:

  1. Байт входит или
  2. Байт помещается в свой регистр данных и помечается для вывода

Здесь важен сдвиговый регистр и регистр данных. Давайте предположим, что на UART0 поступает байт, и мы хотим перенаправить этот трафик на выход UART1. Когда новый байт был сдвинут во входной регистр сдвига UART0, он передается в регистр данных UART0, и прерывание приема UART0 срабатывает. Если вы написали для него ISR, вы можете взять байт в регистре данных UART0 и переместить его в регистр данных UART1, а затем установить регистр управления для UART1, чтобы начать передачу. Что он делает, так это говорит периферийному устройству UART1 взять все, что вы только что положили, в его регистр данных, поместить это в свой выходной сдвиговый регистр и начать его сдвигать. Отсюда вы можете вернуться из своего ISR и вернуться к любой задаче, которую выполнял ваш ОК до того, как она была прервана. Сейчас UART0, после очистки его регистра сдвига и очистки его регистра данных может начаться смещение новых данных, если это еще не было сделано во время ISR, и UART1 смещает байт, который вы только что в него вставили - все это происходит на Сам по себе без вашего вмешательства, пока ваш ОК не выполняет какую-то другую задачу. Весь ISR занимает микросекунды, чтобы выполнить, так как мы перемещаем только 1 байт вокруг некоторой памяти, и это оставляет достаточно времени, чтобы уйти и заняться другими делами, пока не поступит следующий байт на UART0 (который занимает 100 микросекунд). и UART1 сдвигает байт, который вы только что в него вставили, - все это происходит само по себе без вашего вмешательства, пока ваш ОК не выполняет какую-то другую задачу. Весь ISR занимает микросекунды, чтобы выполнить, так как мы перемещаем только 1 байт вокруг некоторой памяти, и это оставляет достаточно времени, чтобы уйти и заняться другими делами, пока не поступит следующий байт на UART0 (который занимает 100 микросекунд). и UART1 сдвигает байт, который вы только что в него вставили, - все это происходит само по себе без вашего вмешательства, пока ваш ОК не выполняет какую-то другую задачу. Весь ISR занимает микросекунды, чтобы выполнить, так как мы перемещаем только 1 байт вокруг некоторой памяти, и это оставляет достаточно времени, чтобы уйти и заняться другими делами, пока не поступит следующий байт на UART0 (который занимает 100 микросекунд).

В этом прелесть наличия аппаратных периферийных устройств - вы просто записываете в некоторые регистры с отображением памяти, и он позаботится об остальном оттуда и будет сигнализировать вашему вниманию через прерывания, подобные тому, который я только что объяснил выше. Этот процесс будет происходить каждый раз, когда в UART0 поступает новый байт.

Обратите внимание, что в логическом захвате есть только задержка в 1 байт, поскольку мы «буферизируем» только 1 байт, если вы хотите думать об этом таким образом. Я не уверен, как вы пришли к вашей O(2N)оценке - я собираюсь предположить, что вы разместили функции последовательной библиотеки Arduino в цикле блокировки, ожидая данных. Если мы фактор в накладных того , чтобы обработать команду «чтение камеры» на УНЦ, метод прерываний больше походит O(N+c)где cвключает единственную задержку байт и «чтение камеры» инструкцию. Это было бы очень мало, учитывая, что вы отправляете большой объем данных (верно, данные изображения?).

Все эти подробности о периферийном устройстве UART (и каждом периферийном устройстве в uC) подробно объяснены в таблице данных, и все это доступно в C. Я не знаю, дает ли среда Arduino такой низкий уровень доступа, чтобы вы могли начать доступ регистрирует - и это главное - вы не ограничены их реализацией. Вы контролируете все если вы написали это на C (даже более того, если это сделано в сборке), и вы действительно можете подтолкнуть микроконтроллер к реальному потенциалу.

Джон Л
источник
Я думаю, что я не объяснил это хорошо. Проблема с размещением микро-камеры между камерой и XBee заключалась в том, что тогда микро-устройство не может делать ничего другого, пока оно получает данные изображения, если все остальное на таймерах не прерывается. Кроме того, если вы предполагаете, что получение изображения с N пикселями заняло 5 секунд, то если вы поместите в него микро, теперь это займет ~ 10 секунд. Конечно, это все еще O (N), но действительно 2N, что в этом случае было достаточно, чтобы разрушить нашу цель частоты обновления. В конечном счете, пространство памяти не было ограничивающим фактором, в основном это скорость. Вздох, похоже, единственный реальный ответ ...
NickHalden
было использовать более современное оборудование. Я надеялся, что кто-нибудь предложит что-нибудь действительно умное, что послужит удобным трюком для всех моих лет в качестве EE. О, хорошо, я думаю, это по крайней мере означает, что я не был слишком глуп, чтобы думать об уловке = P О, и это сработало довольно хорошо.
NickHalden
@JGord, по стечению обстоятельств я выполнил проект с использованием пересылки UART, как я описываю между чип-картой и стиральной машиной, используя ATmega164 jonathan-lee.ca/DC18-Smart-Card.html, о котором я говорю используя UART ISR для перемещения одного байта из регистра данных UART в другой регистр данных UART, а затем возврата. Аппаратное обеспечение UART действует независимо и переносит данные оттуда. ISR занимает микросекунды и после возвращения из него, УК может свободно делать все, что захочет, пока не будет сдвинут следующий байт. Лучшее объяснение придет при редактировании, когда я вернусь домой.
Джон Л
Интересно. Итак, вы предлагаете, чтобы сервер говорил только с микро? Тогда, что микро передает команды от сервера к камере и ответы от камеры к серверу? Таким образом, в UART0 ISR (конец разговора с сервером) я мог проверить, есть ли команда камеры. Если да, отразите на UART1 камеру. Если нет, не отражайте и вместо этого изменяйте какое-либо значение (боковой угол, высоту и т. Д. Некоторую переменную, с которой проверяет мой цикл управления.) Тогда ISR UART1 будет просто всегда зеркально отображать данные изображения на UART0. Да, я думаю, это сработает. Так что на самом деле просто получить микро с 2 UARTs ...
NickHalden
и достаточно каналов ШИМ было бы путь. Итак, теперь давайте предположим, что сервер отправил запрос get_data, на который, как предполагается, микро отвечает 6-байтовой последовательностью, в которой он отправляет высоту, заголовок компаса и некоторые ECC. По какой-то причине сервер читает 6 байтов, но у них нет правильного протокола, то есть байты сообщения начала и окончания не выстраиваются в линию. Кто знает почему? Вы просто выбросите сообщение и запросите снова или как? Потому что если бы в буфере был какой-то фиктивный байт, 6-байтовое сообщение никогда не выровнялось бы снова? Вы бы порекомендовали промывать после неудачного сообщения?
NickHalden
1

Почему вы не можете передать данные камеры через микроконтроллер? Я не имею в виду буферизацию изображений, а передачу данных UART через микроконтроллер, чтобы он мог решить, что следует отправлять обратно, а что - нет?

Проще всего, если у вас есть микроконтроллер с двумя UART, но его можно эмулировать программно.

Majenko
источник
Ха, да, это была одна из вещей, которую я пропустил ... редактирование вопроса сейчас. Хорошая идея, тем не менее, мы очень обрадовались, когда подумали об этом тоже.
Ник Халден,
1

Мне пришел в голову другой вариант, но он может быть несколько громоздким и слишком тяжелым для вашего проекта:

  • Почему бы не использовать беспроводной USB-сервер, подключенный к небольшому USB-концентратору, с адаптерами USB-> RS232 для предоставления нескольких каналов управления различным частям системы?

Да, громоздко, но если вы урезаете их и, возможно, будете использовать USB вместо RS232, вам это может сойти с рук ...

Majenko
источник