あなたの夢を実現するのに役立ついくつかの概念があります。私は、この答えの中で、あなたが望むものをどのように実装するのかを正確に伝えることはできませんが、実装するのに役立つ概念を示すことができます。
まず、バスマスタというコンセプトがあります。これは必ずしも通信をインスタンス化するデバイスではありません。代わりに、これはバスを所有し制御するデバイスです。
バスマスタではないデバイスがバス上で通信したい場合、まずバスマスタからの許可を求めます。古いZ80(まあ、私は「古い」と言っていますが、今日でもいろいろな形でまだ使用されています)は、他のチップがデータバスとアドレスバスを使用できるようにするためにこのコンセプトを使用しました。 BUSRQとBUSACKの2つの信号で構成されています。デバイスはまず、BUSRQまたはBUSACKのいずれかがアクティブであるかどうかを調べ、どちらもアクティブでない場合は、BUSRQをアクティブにします。バスマスタが他のデバイスにバスを放棄しようとしている場合(その時点でそれを使用していない場合)、バスマスタはBUSACKを起動し、他のデバイスはバスを使用できることを認識します。 BUSRQとBUSACKの両方がリリースされるまで、それ以外のものは使用できません。ニースとシンプルでエレガント。
しかし完璧ではない。 2つのデバイスが非常に同じ瞬間にバスを要求すると決定した場合、衝突が発生します。これは、このような共有バスシステムの共通の問題であり、正しく処理する方法がわからない限り、未解決の問題を引き起こします。
listen-while-you-talk のコンセプトを入力します。これは、別の受信機を介してバス上に送信されているものを聴いているバスを送信しているデバイスを含む。その後、バスで送られたものが実際にバスで終わったかどうかを知ることができます。たとえば、2つのデバイスが同時に発言し、1つが 10011001
を送信し、もう1つが 11001100
を送信した場合、バスに表示される結果は実際にはバス信号の作成方法に応じて 11011101
、または 10001000
だからあなたが送ったものが壊れているのを知ったら、あなたは今それについて何かできます。
次のコンセプト:後退。これは、両方の送信者が短期間待ってから再試行して送信する場所です。彼らが両方の時間の異なる時間のために遅延する限り、しようとする最初のものは、バスを取得し、通信することができます。しかし、あなたはどうやって彼らが異なる時間に両方を遅らせることを保証しますか?答えは簡単だと思うかもしれません: rand()
や random()
のような乱数を使用してください。しかし、それも問題である。
Another concept: The pseudo random number generator
Arduinoは乱数を生成しません。複雑な数式を使って、私たちに無作為に見える数列を作成するだけです。彼らはそうではありません。シリアルを通して10の乱数を印刷し、それを複数回実行するための小さなプログラムを書く(リセットボタンを押す)。毎回同じ順序で同じ「ランダム」番号が見つかるでしょう。別のArduinoで試してみて、同じ数字をもう一度得る。いつも同じ。
じゃあ何をすればいいの?答えは乱数ジェネレータをシードすると呼ばれます。 rand()
などが生成する次の数字は、最後に生成された番号に依存します。 最初のの数字を変更すると、残りの数字はすべて変更されます。しかし、キャッチ22の状況があります。乱数ジェネレータをシードする乱数が必要です。乱数を生成して乱数ジェネレータ...無限にシードするには、乱数ジェネレータを乱数にする必要があります。あなたはそれがどこにあるのかを見ますか? rand()
はランダムなソースからシードされるまでランダムではないので、 rand()
からシードすることはできません。だからあなたはランダムな情報源を見つける必要があります。
それは簡単なことではありません。知られているエントロピーの最良のソースはホワイトノイズです。これは、ダイオード接合部の破壊から、抵抗器の熱変動の非常に高い利得増幅まで、さまざまな回路を使用してさまざまな方法で生成することができます。
すべてはあなたが本当に望むものにはかなり複雑ですが、何かに接続されていないアナログ入力を読み込む方が、ほんの僅かでランダムな方法では簡単です。適切なエントロピージェネレータほどの範囲はありませんが、各デバイスが異なるシードを取得する妥当な確率を与えるのに十分なランダム性を提供する必要があります。
もう一つの便利な概念は割り込みです。
これは、すべての衝突などを伴うマルチマスターバスの複雑さを望まない状況では有効です。バス上のすべての作業を行う単一のマスターがあり、スレーブデバイスが何か重要なことを言うときは割り込みでマスタをナッジします。マスターは次に「はい、あなたは何をしたいですか?スレーブが「誰かが私のボタンを押した」と返答します。
そうすれば、マスターはスレーブを常にポーリングして、ボタンが押されたかどうかを確認することはありません。これはSPIのようなバス構成でよく使用され、入力ピンの1つが変化したときに割り込みをアサートできるIO拡張チップなどのチップが多数あります。
しかし、20個のデバイスを持っていると、20個の割り込みピンがあることになりますか?必ずしも。新しいコンセプト:有線OR
複数の異なるスレーブがすべて同じ割り込みピンを使用することは完全に可能です。このピンは通常、抵抗(内部プルアップ抵抗でも可)でHIGHに保持され、各スレーブにはそのピンに接続されたオープンドレイン出力があります。オープンドレイン出力は、「オフ」のときは何も接続されていません。ピンが入力モードにあるようなものです(実際には入力モードと出力モードを切り替えることでオープンドレインのないチップでエミュレートできます)。出力が「オン」のときは、ピンと同じようにピンをグランドに接続し、IOピンをプルダウンします。
それから、誰が注意を必要としているかを見るために、その中断に付随していることを知っている奴隷の周りを回るのは、主人までです。もちろん、それぞれのスレーブの異なるグループを持つ複数の異なる割り込みピンを実装することができます。たとえば、デバイスが1つの場合は優先度が高く、それぞれのデバイスが複数ある場合は優先度が低くなります。
wired OR と open drain という同じ概念を使用して、複数のデバイスがすべて同じ物理配線を共有できるようにすることができます。つまり、2つのバスラインは抵抗によってプルアップされ、その上のデバイスはオープンドレイン出力を使用してラインをローにプルダウンし、ハイレベルに戻して異なるロジックレベルを作り出します。 2つのデバイスが共に低くなると、それはちょうど低くなります。オープンドレイン方式がなければ、1つのデバイスが1を出力し、もう1つが0を出力すると、基本的に2つの間の短絡が発生し、破損したチップになります。
もちろん、同期と非同期のコミュニケーションのコンセプトはありますが、それはまったく異なる魚です。簡単に言えば、そのクロックを生成するマスタを持つSPIやI2Cのようなクロックを持つプロトコルは同期しています。 UARTやRS-232、RS-485などのプロトコルは非同期です。信号の到着時に信号をどのように解釈するかを知るために、データの転送速度(ボーレート)を両者が頼りにしています。