やや複雑なセンサーネットワーク


9

私は最近プロジェクトに取り組んでおり、センサーネットワークを複雑にするのに十分に関与した最初のプロジェクトでした。結局のところ、コミュニケーションが全体的なパフォーマンスのボトルネックになっていると思います。経験豊富な人々がこの問題をどのように解決していたのだろうと思います。長い読みですが、なかなか面白いと思いますので、こだわってください。問題は、障害物コースをナビゲートし、ピンポンボールを茶色のボックスターゲットにドロップできる自律型飛行船を設計することでした。ここに行く:

センサー

  • 4D Systems uCAM-TTLカメラモジュール-UARTインターフェイス
  • HMC6352デジタルコンパス-I2Cインターフェイス
  • Maxbotix Sonar ez4-1ピンアナログインターフェイス

アクチュエーター

  • 2x L293Dモータードライバー(シンプルなホビーモーターに接続)-これらは、6つのモーターを双方向で駆動するために使用されました。速度を変えるためにPWM入力が必要でした。現在、3つのモーターは常に同じこと(上下の動きを制御するモーター)を使用していたため、3つのモーターすべてを制御するためにコントローラーから2つのPWM出力のみが必要でした。横方向の動きを制御する他の3つのモーターはすべて個別の制御(全方向移動)を必要としていたため、コントローラーからはさらに6つのPWM出力が必要でした。
  • サーボモーター-PWMインターフェース

コントローラー

後で明らかになる理由により、2倍のATmega328Pを使用することになりました。プログラミングにはArduino Unoを使用しましたが(ISPにアクセスできませんでした)、カスタムPCBを製造したので、飛行船に不要な重量が加わるため、Arduinoボードを使用する必要がありませんでした。私たちがATmega328Pを選んだ理由については、私はarduino環境に非常に精通しており、それによってコード開発がはるかに迅速かつ簡単になったと思います。

通信と処理

  • 2x Xbee Basic
  • 2x ATmega328P
  • C ++とopenCVを実行しているデスクトップコンピューター

カメラモジュールからわかるように、私たちのプロジェクトのほとんどはコンピュータービジョンに依存していました。飛行船はそれほどの重量しか運ぶことができず、マイクロコントローラーにコンピュータービジョンを実装するのは快適でした。そのため、XBeeを使用して画像データをデスクトップコンピューターに中継しました。サーバー側では、画像データを受け取り、openCVを使用して画像と図を処理しました。今度はサーバー側も高さ情報(ソナーから)とコンパス情報を知る必要がありました。

最初のしわは、いくつかの理由でマイクロコントローラーでカメラを制御できなかったことでした。主な問題は、uPの内部メモリがフレーム全体の格納を処理できないことでした。巧妙なコーディングによってこれを回避する方法があったかもしれませんが、この質問の目的のために、それが不可能であったとしましょう。この問題を解決するために、サーバー側でXBeeトランシーバーを介してカメラコマンドを送信し、XBeeレシーバー(飛行船に搭載)の出力をカメラの入力に配線しました。

次のしわは、I2CインターフェースがPWMピンの1つを使用しているため(それらをくそ...)、すべてのモーターを制御するのに十分なPWMが1つのATmega328Pにないということでした。そのため、2番目のものを使用することにしました。高さ制御は横方向の移動制御とは完全に独立しているため、コードは実際には並列処理に完全に対応しています(したがって、2マイクロはおそらくPWMコントローラーに接続されたものよりも優れていました)。したがって、U1は2つのPWM出力(アップ/ダウン)とソナーの読み取りを担当していました。U2は、コンパスの読み取り、6つのPWM出力(横方向モーター)の制御、およびソナーの読み取りを担当しました。U2は、XBeeを介してサーバーからコマンドを受信することも担当していました。

それが最初のコミュニケーションの問題につながりました。XBee DOUTラインは、マイクロコントローラーとカメラの両方に接続されていました。もちろん、プロトコルを設計して、マイクロコマンドがカメラコマンドを無視し、カメラコマンドがマイクロコマンドを無視するようにしたので、問題はありませんでした。ただし、カメラがマイクロコマンドを無視すると、出力ラインにNAKデータが返されます。このコマンドはマイクロを対象としているため、XBeeへのカメラ出力をオフにする必要があります。これを解決するために、カメラとXBee(最初のFET)の間、およびU2とXBee(2番目のFET)の間にあるマイクロ制御2 FETを作成しました。したがって、カメラがサーバーに情報を返そうとしたとき、最初のFETは「オン」で、2番目のFETは「オフ」でした。

したがって、これがどのように機能するかを理解するために、いくつかの例を示します。

  1. サーバーは画像を要求します-PIC_REQUESTはXBeeを通過し、U2とカメラに到着します。U2はそれを無視し、カメラは画像データを送り返します。
  2. サーバーは画像の処理を終了し、モーターデータを送信して飛行船に右折するように指示しています-MOTOR_ANGLE(70)はXBeeを通り抜け、U2とカメラに到着します。U2はマイクロコマンドとして認識し、カメラのFETをオフにします(ただし、カメラはすでにNAKで応答していますか?次に、U2はモーターのPWM出力を変更することでコマンドに応答します。次に、カメラのFETをオンに戻します(画像データが最も重要だったため、これがデフォルト設定でした)。
  3. サーバーは、デフォルトのホバー高さが50インチではなく90インチである必要がある障害物コースのポイントに到達したことを認識しています。SET_HEIGHTはXBeeを通過し、例2と同じことが起こります。U2はSET_HEIGHTコマンドを認識し、U1で割り込みをトリガーします。U1は高さ制御ループから出て、U2からのシリアルデータの受信を待ちます。そうです、より多くのシリアルデータ。この時点でU2のFETはオン(そしてカメラのFETはオフ)なので、サーバーはU2がU1にも送信している高さを受け取ります。これは確認のためでした。U1は、height2HoverAtの内部変数をリセットします。U2はFETをオフにし、カメラFETをオンに戻します。

私は間違いなくかなりの量の情報を省きましたが、いくつかの複雑さを理解するにはそれで十分だと思います。結局のところ、私たちの問題は単にすべてを同期させることでした。バッファにデータが残っていることがありますが、3バイトしかありません(すべてのコマンドは6バイトシーケンスでした)。時々、カメラとの接続を失い、それを再同期する必要があります。

だから私の質問は:これらのすべてのコンポーネント間の通信をより信頼性の高い/堅牢な/単純な/より良いものにするために、どのようなテクニックを提案するでしょうか?

たとえば、オンボードXBeeアウトとカメラの間に遅延回路を追加して、マイクロがNAKのマイクロコマンドに応答する前にカメラのトークラインをオフにする機会があったことを知っています。そのような他のアイデアはありますか?

おかげで、これには多くの編集が必要になると確信していますので、しばらくお待ちください。


Edit1:マイクロの1つを介してカメラのUARTデータを接続することは、私たちには不可能であるように思われました。カメラデータには、生のビットマップ、またはJPEGの2つのオプションがありました。生のビットマップの場合、カメラはデータをできるだけ早く送信します。ATmega328Pはシリアルバッファ用に128バイトしかありません(技術的にはこれは設定可能ですが、どうすればいいのかわかりません)、私たちはそれをバッファから取り出してXBeeに十分速く到達できるとは思いませんでした。これにより、JPEGメソッドは各パッケージを送信し、コントローラーがACKを受信するまで待機します(小さなハンドシェークプロトコル)。これが最も速いのは115200ボーでした。何らかの理由で、XBeeを介して大量のデータを確実に送信できる最速は57600ボーでした(これは、自動再送機能を許可するためにノードとネットワークのペアリングを行った後でも同じです)。マイクロ用にネットワークに追加のストップ(カメラからXBeeへのカメラではなく、カメラからマイクロへのXBee)を追加すると、画像の転送に時間がかかりすぎます。モーター制御アルゴリズムを機能させるには、画像に特定のリフレッシュレートが必要でした。


3
マイクロコントローラーのスキルを拡張しないように多大な努力を払っています。Arduinoに対して私は何も得ていませんが、それはそれに対してあまり適切ではありません。最終的にそれを機能させることができますか?多分。ただし、より優れたプラットフォームを学習する方がはるかに便利です。より経験豊富な人々がそれをどのように行うかを尋ねている場合、私はopenCVと制御用のARM SBC、およびすべてのインターフェイスへのブリッジとして機能するFPGAのようなものを言います。しかし、それはちょっとしたジャンプになるので、新しい主要なことを1つだけ試してみることをお勧めします。おそらく、すべてにインターフェイスするのに十分な周辺機器を備えた32ビットマイクロですか。
darron

ははははははははははははーい このプロジェクトは学校の課題であり、チームの2人のEEの1人に新しいマイクロコントローラープラットフォームを学習させるのではなく、それを機能させることに集中したかったのです。今年の夏、ARMやより高度なマイクロに参加することを考えています。私たちのチームの他のEEは、実際にはFPGAのクラスを受講していました...私は彼を怒鳴りつけます= P
NickHalden

回答:


4

慣れ親しんだ開発環境を使い始めたいとのことでしたが、ハードウェアとソフトウェアのトレードオフにより、Arduinoにこだわり、すべてが揃っていないパーツを選んだのではないかと思います。代わりに、必要なハードウェア周辺機器とすべてを割り込み駆動型Cで書き込む。

@Matt Jenkinsの提案に同意し、さらに拡張したいと思います。

2つのUARTを備えたuCを選択しました。1つはXbeeに接続され、もう1つはカメラに接続されています。uCはサーバーからのコマンドを受け入れてカメラの読み取りを開始し、ルーチンを書き込んで、バイトごとにカメラのUARTチャネルからXBee UARTチャネルにデータを転送できます。そのため、バッファーはありません(または多くても非常に小さい) 1)必要。私はすべてのPWMニーズにも対応できる部品(8つのPWMチャネル?)を選択して、他のuCをすべて排除しようとしました。2つの異なるuCを使用してそれぞれの軸を処理したい場合は、他のすべてのUARTが使用されるため、別の通信インターフェイスの方が優れていたでしょう。

他の誰かも、すべてを実行するために組み込みのLinuxプラットフォームに移動することを提案しました(openCVを含む)。これも同様に検討する必要があるでしょう。私は以前にも行ったことがありますが、4か月の学校プロジェクトで、すぐにそれを実行する必要があるだけで、分析によって麻痺から立ち往生することはできません。


編集#1 コメントへの返信@JGord:

ATmega164pでUART転送を実装するプロジェクトをしました。2つのUARTがあります。以下は、UART転送を示す、そのプロジェクトのロジックアナライザーキャプチャ(Saleae USBロジックアナライザー)の画像です。 アナライザーキャプチャ

一番上の行はソースデータ(この場合はカメラ)で、一番下の行は転送されているUARTチャネル(この場合はXBee)です。これを行うために作成されたルーチンは、UART受信割り込みを処理しました。さて、このUART転送が行われている間に、PWMチャネルを楽しく構成し、I2Cルーチンも処理できると思いますか?その方法を説明させてください。

(とにかく私のAVRの)各UARTペリフェラルは、カップルシフトレジスタ、データレジスタ、および制御/ステータスレジスタで構成されています。このハードウェアは、次のいずれかの場合、ユーザーの介入なしに(ボーレートなどを既に初期化していると仮定して)独自に処理します。

  1. バイトが入ってくるか
  2. バイトがそのデータレジスタに配置され、出力のフラグが立てられます

ここで重要なのは、シフトレジスタとデータレジスタです。1バイトがUART0で受信され、そのトラフィックをUART1の出力に転送するとします。新しいバイトがUART0の入力シフトレジスタにシフトインされると、UART0データレジスタに転送され、UART0受信割り込みが発生します。ISRを書き込んだ場合は、UART0データレジスタのバイトを取得してUART1データレジスタに移動し、UART1の制御レジスタを設定して転送を開始できます。これは、UART1ペリフェラルに、データレジスタに入れたすべてのものを取り出して、それを出力シフトレジスタに入れ、シフトアウトを開始するように指示することです。ここから、ISRから戻って、中断される前にuCが実行していたタスクに戻ることができます。今UART0、シフトレジスタをクリアした後、データレジスタをクリアすると、ISR中にまだ行っていない場合、新しいデータのシフトインを開始できます。UART1は、挿入したバイトをシフトアウトします-すべてが発生しますuCが他のタスクを実行していない間は、介入なしで独自のものになります。一部のメモリ内を1バイトだけ移動しているため、ISR全体の実行にマイクロ秒かかります。これにより、UART0の次のバイトが到着するまで(100マイクロ秒かかる)、オフにしたり、他のことを行ったりするのに十分な時間が残されます。そしてUART1はあなたがそれに入れたバイトをシフトアウトしています-あなたのuCが他のタスクを行っている間、あなたの介入なしにそれはすべてそれ自体で起こります。一部のメモリ内を1バイトだけ移動しているため、ISR全体の実行にマイクロ秒かかります。これにより、UART0の次のバイトが到着するまで(100マイクロ秒かかる)、オフにしたり、他のことを行ったりするのに十分な時間が残されます。そしてUART1はあなたがそれに入れたバイトをシフトアウトしています-あなたのuCが他のタスクを行っている間、あなたの介入なしにそれはすべてそれ自体で起こります。一部のメモリ内を1バイトだけ移動しているため、ISR全体の実行にマイクロ秒かかります。これにより、UART0の次のバイトが到着するまで(100マイクロ秒かかる)、オフにしたり、他のことを行ったりするのに十分な時間が残されます。

これがハードウェア周辺機器の利点です。メモリマップレジスタに書き込むだけで、そこから残りの処理が行われ、上記で説明したような割り込みを通じて注意を促すことができます。このプロセスは、UART0に新しいバイトが入るたびに発生します。

ロジックキャプチャでは1バイトの遅延しかないことに注意してください。そのように考えたいのであれば、1バイトしか「バッファリング」していないからです。どのようにO(2N)見積もりを出したかわかりません。Arduinoのシリアルライブラリ関数を、データを待機しているブロッキングループに格納したと想定します。uCで「カメラの読み取り」コマンドを処理する必要があるというオーバーヘッドを考慮に入れると、割り込みドリブン方式は、1バイトの遅延と「カメラの読み取り」命令を含むに似てO(N+c)cます。大量のデータを送信している場合、これは非常に小さくなります(画像データですよね?)。

UARTペリフェラル(およびuCのすべてのペリフェラル)に関するこのすべての詳細はデータシートで完全に説明されており、すべてCでアクセスできます。レジスター-そしてそれは-それがそうでなければ-あなたはそれらの実装によって制限されます。Cで記述した場合はすべてを制御でき(アセンブリーで作成した場合はさらに制御できます)、マイクロコントローラーを実際の潜在能力に押し上げることができます。


私はこれをうまく説明しなかったと思います。カメラとXBeeの間にマイクロを配置することに関する問題は、タイマーが中断していない限り、画像データを取得している間、マイクロは他に何もできないことでした。さらに、Nピクセルの画像を取得するのに5秒かかると想定した場合、microを挿入すると、約10秒かかります。確かに、まだO(N)ですが、実際には2Nランタイムです。この場合、リフレッシュレートの目標を達成するのに十分でした。結局のところ、メモリ空間は実際には制限要因ではなく、ほとんどが速度でした。ため息、それが唯一の本当の答えのようです...
NickHalden

より高度なハードウェアを使用することでした。私は、EEとしての私のすべての年の間、便利なトリックとして役立つだろう本当に賢い何かを誰かが提案することを望んでいました。まあ、私は少なくとも私がトリックを考えるのに馬鹿ではなかったことを意味していると思います= Pおお、それはかなりうまくいきました。
NickHalden、2011年

@JGord、偶然にも、ATmega164 jonathan-lee.ca/DC18-Smart-Card.htmlを使用して、ICカードと洗濯機の間でUART転送を使用してプロジェクトを作成しました。 UART ISRを使用して1バイトをUARTデータレジスタから他のUARTのデータレジスタに移動してから戻る。UARTハードウェアは独立して動作し、そこからデータをシフトアウトします。ISRはマイクロ秒かかり、uCが返されると、次のバイトがシフトインされるまで、uCは何でも自由に実行できます。
Jon L

面白い。それで、あなたの提案はサーバーにマイクロのみと話させることでしょうか?次に、そのマイクロはサーバーからカメラへのコマンドとカメラからサーバーへの応答を中継しますか?したがって、UART0 ISR(サーバーとの通信終了)で、カメラコマンドかどうかを確認できました。はいの場合、UART1からカメラにミラーリングします。そうでない場合は、ミラーリングせずに、値(横方向の角度、高さなど、制御ループがチェックする変数)を変更します。UART1のISRは、常に画像データを常にUART0にミラーリングします。ええ、私はそれがうまくいくと思います。だから本当に2つのUARTを備えたマイクロを取得しています...
NickHalden

そして、十分なPWMチャネルを使用する方法でした。それでは、サーバーがget_dataリクエストを送信したとしましょう。マイクロは、高さ、コンパスの見出し、およびいくつかのECCを送信する6バイトのシーケンスで応答するはずです。何らかの理由でサーバーは6バイトを読み取りますが、正しいプロトコルがありません。つまり、開始メッセージと終了メッセージのバイトが揃っていません。誰がその理由を知っていますか?メッセージを破棄して、再度要求するか、または何をしますか?バッファにダミーバイトがあった場合、6バイトのメッセージは二度と整列しません。メッセージが失敗した後にフラッシュすることをお勧めしますか?
NickHalden 2011年

1

µCを介してカメラデータをパイプできないのはなぜですか?画像をバッファリングするのではなく、µCを介してUARTデータを中継して、何を送り返すべきか、何を送るべきでないかを判断できるようにしますか?

2つのUARTが組み込まれたµCがある場合に最も簡単ですが、ソフトウェアでエミュレートできます。


ええ、ええ、それは私が取り除いたものの一つでした...今、質問を編集しています。でもいい考えだと思ったときも興奮しました。
NickHalden、2011年

1

別のオプションが私に起こりました、しかしこれはあなたのプロジェクトにとってややかさばって重すぎるかもしれません:-

  • 小さなUSBハブにリンクされたワイヤレスUSBサーバーを、USB-> RS232アダプターと一緒に使用して、システムのさまざまな部分に複数の制御チャネルを提供しませんか?

はい、かさばりますが、それらを取り除き、可能であればRS232の代わりにUSBを使用すると、おそらくそれを回避できます...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.