Eu estava trabalhando em um projeto recentemente e foi o primeiro envolvido o suficiente para tornar a rede de sensores complicada. No final, acho que a comunicação foi o gargalo em termos de desempenho geral e estou me perguntando como as pessoas mais experientes teriam resolvido esse problema. Esta é uma leitura longa, mas acho que é bem interessante, por favor, continue com ela. O problema era projetar um dirigível autônomo capaz de navegar em uma pista de obstáculos e soltar bolas de pingue-pongue nos alvos das caixas marrons. Aqui vai:
Sensores
- Módulo de câmera uCAM-TTL da 4D Systems - interface UART
- Bússola digital HMC6352 - interface I2C
- Maxbotix Sonar ez4 - interface analógica de 1 pin
Atuadores
- 2 drivers de motor L293D (conectados a motores simples) - Estes eram usados para acionar 6 motores bidirecionalmente. Eles exigiram entradas PWM para variar a velocidade. Agora, 3 de nossos motores estavam sempre fazendo a mesma coisa (os que controlavam o movimento para cima / para baixo), portanto, eles exigiam apenas 2 saídas PWM de nossos controladores para controlar todos os 3 motores. Os outros três motores que controlavam o movimento lateral precisavam de controle individual (para movimento omnidirecional), de modo que outras 6 saídas PWM eram necessárias em nossos controladores.
- Servo motor - interface PWM
Controladores
Por razões que ficarão claras mais tarde, acabamos usando 2x ATmega328Ps. Usamos um Arduino Uno para programá-los (não tínhamos acesso a um provedor de serviços de Internet), mas fabricamos uma PCB personalizada, para que não precisássemos usar placas de arduino, pois isso acrescentaria peso desnecessário ao nosso dirigível. Quanto ao motivo pelo qual escolhemos o ATmega328P, eu estava muito familiarizado com o ambiente do arduino e acho que tornou o desenvolvimento do código muito mais rápido e fácil.
Comunicação e Processamento
- 2x Xbee Basic
- 2x ATmega328P
- Computador de mesa executando C ++ com openCV
Como você pode ver no módulo da câmera, a maior parte do nosso projeto se baseou na visão computacional. Os dirigíveis podiam suportar tanto peso e não nos sentíamos confortáveis implementando a visão computacional em um microcontrolador. Então, o que acabamos fazendo foi usar o XBee's para retransmitir os dados da imagem de volta para um computador desktop. Por isso, no lado do servidor, recebemos dados da imagem e usamos o openCV para processar a imagem e descobrir coisas a partir dela. Agora, o lado do servidor também precisava saber informações de altura (do sonar) e informações da bússola.
A primeira ruga foi que não conseguimos controlar a câmera por um microcontrolador por alguns motivos. O principal problema era que a memória interna no uP não suportava o armazenamento de um quadro inteiro. Pode ter havido maneiras de contornar isso através de uma codificação inteligente, mas para os fins desta pergunta, vamos fingir que era impossível. Portanto, para resolver esse problema, o servidor enviou comandos da câmera através do transceptor XBee e o receptor XBee (a bordo do dirigível) teve sua saída conectada à entrada da câmera.
A próxima ruga foi a de que não há PWMs suficientes em um único ATmega328P para controlar todos os motores PORQUE a interface I2C usa um dos pinos PWM (caramba ...). Por isso, decidimos usar o segundo. O código realmente se prestou perfeitamente ao processamento paralelo de qualquer maneira, porque o controle de altura era completamente independente do controle de movimento lateral (portanto, 2 micros eram provavelmente melhores do que um conectado a um controlador PWM). Portanto, o U1 foi responsável por 2 saídas PWM (para cima / para baixo) e pela leitura do Sonar. O U2 foi responsável pela leitura da bússola, pelo controle de 6 saídas PWM (os motores laterais) e também pela leitura do Sonar. O U2 também foi responsável por receber comandos do servidor através do XBee.
Isso levou ao nosso primeiro problema de comunicação. A linha XBee DOUT foi conectada ao microcontrolador e à câmera. Agora, é claro, nós projetamos um protocolo para que nossos micro comandos ignorassem os comandos da câmera e os comandos da câmera ignorassem os micro comandos, o que era bom. No entanto, a câmera, ao ignorar nossos micro comandos, enviava dados de NAK em sua linha de saída. Como o comando foi feito para o micro, precisamos de alguma maneira desligar a saída da câmera para o XBee. Para resolver isso, fizemos os FETs de microcontrole 2 que estavam entre a câmera e o XBee (esse é o primeiro FET) e também entre o U2 e o XBee (esse é o segundo FET). Portanto, quando a câmera estava tentando enviar informações de volta ao servidor, o primeiro FET estava 'ligado' e o segundo FET estava 'desligado'.
Então, para lhe dar uma idéia de como isso funcionou, aqui estão alguns exemplos:
- O servidor solicita uma imagem - PIC_REQUEST passa pelo XBee e chega ao U2 e à câmera. O U2 o ignora e a câmera envia os dados da imagem.
- O servidor acabou de processar uma imagem e está enviando dados do motor para dizer ao dirigível que vire à direita - MOTOR_ANGLE (70) passa pelo XBee e chega ao U2 e à câmera. O U2 reconhece como um micro comando e, portanto, desliga o FET da câmera (mas talvez a câmera já tenha respondido com um NAK ?? quem sabe ...). O U2 responde ao comando alterando as saídas PWM do motor. Em seguida, reativa o FET da câmera (essa era a configuração padrão, pois os dados da imagem eram mais importantes).
- O servidor percebe que chegamos a um ponto na pista de obstáculos em que nossa altura de foco padrão agora precisa ser de 90 polegadas em vez de 50 polegadas. SET_HEIGHT passa pelo XBee e o mesmo acontece no exemplo 2. U2 reconhece o comando SET_HEIGHT e aciona uma interrupção no U1. O U1 agora sai do loop de controle de altura e aguarda para receber dados seriais do U2. É isso mesmo, mais dados seriais. Nesse ponto, o FET do U2 está ativado (e o FET da câmera está desativado), de modo que o servidor recebe a altura que o U2 também está enviando para o U1. Isso foi para fins de verificação. Agora o U1 redefine sua variável interna para height2HoverAt. O U2 agora desliga o FET e liga novamente o FET da câmera.
Eu definitivamente deixei de fora uma boa quantidade de informações, mas acho que isso é suficiente para entender algumas das complicações. No final, nossos problemas estavam apenas sincronizando tudo. Às vezes, restavam dados nos buffers, mas apenas 3 bytes (todos os nossos comandos eram sequências de 6 bytes). Às vezes, perdíamos a conexão com nossa câmera e precisávamos ressincronizá-la.
Então, minha pergunta é: que técnicas vocês sugerem para tornar a comunicação entre todos esses componentes mais confiável / robusta / mais simples / melhor?
Por exemplo, eu sei que alguém teria sido adicionar um circuito de atraso entre a saída do XBee a bordo e a câmera, para que o micro tivesse a chance de desligar a linha de conversa da câmera antes de responder aos micro comandos com NAKs. Alguma outra idéia assim?
Obrigado e tenho certeza de que isso exigirá muitas edições, portanto, fique atento.
Edit1:A emenda dos dados UART da câmera através de um dos micros não nos parecia possível. Havia duas opções para dados da câmera, mapa de bits bruto ou JPEG. Para um bitmap bruto, a câmera envia os dados para você o mais rápido possível. O ATmega328P possui apenas 128 bytes para um buffer serial (tecnicamente isso é configurável, mas não sei como) e não achamos que conseguiríamos tirá-lo do buffer e passar para o XBee com rapidez suficiente. Isso deixou o método JPEG, onde ele envia cada pacote e aguarda que o controlador o aceite (pequeno protocolo de handshaking). O mais rápido possível foi 115200 baud. Agora, por alguma razão, o mais rápido que pudemos transmitir grandes quantidades de dados de maneira confiável pelo XBee foi de 57600 baud (isso ocorreu mesmo após o emparelhamento nó / rede para permitir o recurso de reenvio automático). A adição de uma parada extra em nossa rede (câmera para micro para XBee em vez de apenas câmera para XBee) para o micro simplesmente diminuiu o tempo necessário para transferir muito uma imagem. Precisávamos de uma certa taxa de atualização nas imagens para que nosso algoritmo de controle motor funcionasse.