簡易通信用パケット
by K.I
Index
簡易通信チップの改良版の作成を依頼されたので、改良版のパケット仕様を検討した。
- 前回はエラー対策を殆ど行っていなかったが、今回は回線品質が悪い場合を想定して、パケット構成とプログラム構成の全面的な見直しを行った。
- それによりある程度の効果が得られたため、パケット構成とプログラムの概要をまとめた。
[top]
まず前回の仕様と問題点を基に、改良版の仕様を検討する。
以前作成した 簡易データ通信チップの特徴として、
- NRZIなので、データ極性を考慮する必要がない。
- ボーレート自動追従機能があったので、通信ボーレートの変更が可能。
- 4B5B或は、4B7B1変換を行なって、マンチェスタと同等のDCオフセットに抑えた。
問題点としては、
- データフレームの開始の検出の問題
- 単にヘッダとしてアイドル信号を置いていただけなので、開始位置の検出が難しい。
- ヘッダ部分が、一部でも壊れると受信を開始出来ない。
- エラー検出やエラー訂正を全く行なっていなかったので、データの信頼性が低い。
- 割り込みを使わずにプログラムしたので、ボーレートの調整が難しかった。
- 内蔵CR発振による通信と、ボーレート自動追従のため、エラー率が多かった可能性がある。→少なくともエラー原因の特定が難しかった。
前回の問題点についての改良を考えてみる。
- 15bit2PN符号によるフレーム検出
- エラーを許容することで、3フレーム検出率を上げる。
- 8bitデータを4bit+4bitに分割し、それぞれ3bitの訂正ビットを付加して14bitとする。
- それぞれ、1bitのエラー訂正と、2bitまでのエラー検出が可能になる。
- DCオフセットを少しでも少なくするため、マンチェスタに変更する。
- ボーレート自動追従は止めて、セラロックで固定ボーレートとする。
考慮すべき点について、、、
- マンチェスタへの変更
- ビットレートは低下するが、前回もDCオフセットを抑えるため4B7Bとか無理矢理に使っていたので、あまり大きな変化はない。
- データ極性を考える必要があるが、今回は固定で構わないので大丈夫だろう。
- NRZIは全てのエッジがクロックであり、意味を持っているが、マンチェスタは無意味なエッジが多く含まれている冗長な符号になっている。復号化については全面的に書直す必要があるが、無効エッジの取扱いが難しいと思われる。
- ボーレート自動追従は出来なくなったが、その代わりエラー原因は特定し易くなるだろう。
フレーム検出を確実に行なうためには、以下のような条件が必要になる。
- 繰返し部分の無い、ある程度の長さを持つ
- データと取り違えが起こらないようなコード
- エラーが発生しても、上記の性質が出来るだけ守られる事が望ましい
これらの性質を持つ符号列は何かというと、結果的に乱数が適当ということになる。
- フレーム検出には上記の理由から、M系列のPN符号を使うことにする。
- フレーム検出率を上げるために、ビットエラーがあっても許容とする。
- 何ビットまで許容するかは、ヘッダ長や、データ部分のビット長により検討が必要だろう。
エラー訂正としては、ブロック符号と、畳み込み符号に大別される。
- ブロック符号 →1区切りのデータ(現在のデータ)のみでエラー訂正を行なうので、アルゴリズムが簡単で高速処理が可能。
- 畳み込み符号 →過去のデータの情報も含めて検討しエラー訂正を行なうので、時間が掛かるが、エラー訂正能力が高い。
今回はリアルタイムで処理するため、ブロック符号であるハミング符号を選択した。
送信情報ビット数を8bitとしたので、データ部分の長さは、14bit。チェックサムも付けて16bitとした。
ハミング符号は、エラー訂正の基本として良く挙げられるが、アルゴリズムが簡単で、高速処理が可能。またエラー検出率も悪くないので、実用的な符号でもある。
- 7bitデータがx1x2x3x4x5x6x7である時、以下が全て0になるように x5,x6,x7を選ぶ。
- さらに、送信データは8ビットの方が切りが良いので、チェックサムも付加する。
c4 = x1+x2+x3+x4+x5+x6+x7
- つまり送信データは以下の16通りのデータになる。これは変換テーブルを使って簡単に変換可能である。
元DATA | TXDATA | |
0 | 00000000 | 00 |
1 | 00011110 | 1E |
2 | 00101101 | 2D |
3 | 00110011 | 33 |
4 | 01001011 | 4B |
5 | 01010101 | 55 |
6 | 01100110 | 66 |
7 | 01111000 | 78 |
8 | 10000111 | 87 |
9 | 10011001 | 99 |
A | 10101010 | AA |
B | 10110100 | B4 |
C | 11001100 | CC |
D | 11010010 | D2 |
E | 11100001 | E1 |
F | 11111111 | FF |
- 受信データについても、c2 c1 c0を求める。全て0であればエラー無しになるはず。
- 0以外の場合は、c2c1c0番目のビットを反転すれば、訂正が可能になる。
以下は、この規則に従ってExcelで計算してみたもの。
RXDATA | 訂正前 | C0 | C1 | C2 | 訂正後 | |
00 | 0000000 | 0 | 0 | 0 | 0000000 | 00 |
01 | 0000001 | 1 | 1 | 1 | 0000000 | 00 |
02 | 0000010 | 0 | 1 | 1 | 0000000 | 00 |
03 | 0000011 | 1 | 0 | 0 | 1000011 | 43 |
04 | 0000100 | 1 | 0 | 1 | 0000000 | 00 |
05 | 0000101 | 0 | 1 | 0 | 0100101 | 25 |
06 | 0000110 | 1 | 1 | 0 | 0010110 | 16 |
07 | 0000111 | 0 | 0 | 1 | 0001111 | 0F |
08 | 0001000 | 0 | 0 | 1 | 0000000 | 00 |
09 | 0001001 | 1 | 1 | 0 | 0011001 | 19 |
0A | 0001010 | 0 | 1 | 0 | 0101010 | 2A |
0B | 0001011 | 1 | 0 | 1 | 0001111 | 0F |
0C | 0001100 | 1 | 0 | 0 | 1001100 | 4C |
0D | 0001101 | 0 | 1 | 1 | 0001111 | 0F |
0E | 0001110 | 1 | 1 | 1 | 0001111 | 0F |
0F | 0001111 | 0 | 0 | 0 | 0001111 | 0F |
10 | 0010000 | 1 | 1 | 0 | 0000000 | 00 |
11 | 0010001 | 0 | 0 | 1 | 0011001 | 19 |
12 | 0010010 | 1 | 0 | 1 | 0010110 | 16 |
13 | 0010011 | 0 | 1 | 0 | 0110011 | 33 |
14 | 0010100 | 0 | 1 | 1 | 0010110 | 16 |
15 | 0010101 | 1 | 0 | 0 | 1010101 | 55 |
16 | 0010110 | 0 | 0 | 0 | 0010110 | 16 |
17 | 0010111 | 1 | 1 | 1 | 0010110 | 16 |
18 | 0011000 | 1 | 1 | 1 | 0011001 | 19 |
19 | 0011001 | 0 | 0 | 0 | 0011001 | 19 |
1A | 0011010 | 1 | 0 | 0 | 1011010 | 5A |
1B | 0011011 | 0 | 1 | 1 | 0011001 | 19 |
1C | 0011100 | 0 | 1 | 0 | 0111100 | 3C |
1D | 0011101 | 1 | 0 | 1 | 0011001 | 19 |
1E | 0011110 | 0 | 0 | 1 | 0010110 | 16 |
1F | 0011111 | 1 | 1 | 0 | 0001111 | 0F |
: | : | : | : | : | : | |
: | : | : | : | : | : | |
78 | 1111000 | 0 | 0 | 1 | 1110000 | 70 |
79 | 1111001 | 1 | 1 | 0 | 1101001 | 69 |
7A | 1111010 | 0 | 1 | 0 | 1011010 | 5A |
7B | 1111011 | 1 | 0 | 1 | 1111111 | 7F |
7C | 1111100 | 1 | 0 | 0 | 0111100 | 3C |
7D | 1111101 | 0 | 1 | 1 | 1111111 | 7F |
7E | 1111110 | 1 | 1 | 1 | 1111111 | 7F |
7F | 1111111 | 0 | 0 | 0 | 1111111 | 7F |
- これも変換テーブルを使って復号化する。
- チェックサムを計算すれば2bitのエラーを検出可能だが、今回はエラー時の処理を特に考えていないので、無視する。
14B7Bは標準的な符号ではなく独自に定義したものである。DCオフセットを少なくするため3回以上連続した0,1を排除した符号になっているので、マンチェスタと同じ特性を持つ。
215bitはエラーを考えると、ちょっと短いがデータが14bitなのでこれぐらいで抑えておく。
3今回、フレーム検出は特に問題にならなかったので、実際にはエラーの許容はしていない。
[top]
マンチェスタ符号を2400bpsで送受信することを考える。
- マンチェスタ符号は1bitで1周期になるから、最大2400Hz。
- 1周期は416μs、0或は1の時間は半分の208μsになる。
- サンプリングの時間は、最低その半分だが、通常は1/4の52μs、或は1/8の26μsで行なった方が良いだろう。
- PICの場合、SystemClockが4MHzだと52cycleなので、あまり処理時間を取れない。
- つまり最低限その倍の10MHz、出来れば20MHzで動作させる必要がある。
以上のことから、基本的に52μs(26μs)の割り込みにより全体のシーケンスをコントロールするように設計することにした。
[top]
送信回路は、52μsのタイマ割り込み×4のタイミング4で、データにハミング符号を付加して、ヘッダを付けたパケットを送信する。
- 送信間隔は約50msとした。
- 技適の対応として、送信動作は以下の制限を設けている。
- 連続送信は、50ms×100=約5秒で制限される。
- また、データ送信後は、約2秒の停止期間を設ける。
- Randomを押しながらResetすることで、テストモードとなる。テストモードでは以下のような動作となる。
- 連続送信が可能になる。
- Tx/Rx=1とすることで、キャリアの停止を行わない。
実際のデータフレームは、さらにIDLEを付加した5byteとした。
IDLE: データフレームとは無関係。通信時のDCオフセットを低減させるため
HEADER,FOOTER: フレームヘッダ。フレーム認識を行なう
DATAH,DATAL: 8bitデータを4bitづつに分けて、ハミング符号を付加したもの(x:ハミング符号、p:パリティ)
- フレーム検出部を2つに分離してHEADER,FOOTERにした理由は、同期検出でクロックを取り損ねてシフトしたデータを取得してしまう確率を減らすことを考慮したため。
技適の評価用に511PN符号ジェネレータを実装した。
- 511PNは9bitのM系列であり、以下のようなシフトレジスタによる構成で、適当なタップを指定することで生成することが出来る。
- しかし、今回のプログラムではPN符号が割込み時間内に生成することが出来なかったので、テーブルによる簡易生成方法をとった。
4或いは、26μs×8のタイミングで、タイマ割込みを発生させる。
[top]
入力データはクロックに同期していないため、受信動作はクリティカルなものになる。
- そのためタイマ割込み処理中に最優先でおこなう。
- データ受信は、ノイズ除去回路→同期検出→フレーム検出→ハミング復号の順に行われる。
- これを、割込み期間(52μs或いは26μs)以内に全て完了する必要がある。
通信によるノイズ、特にバーストノイズの除去のために、シフトレジスタを使ったノイズ除去回路を実装した。
- 1〜2bit程度のバーストエラー5はこれで除去できる。
マンチェスタの場合、データに必ずクロックが含まれている反面、全てのエッジに意味があるわけではないので、意味の無いエッジを無視する必要がある。
- 最初はIDLE信号で同期エッジだけが入るようにして、無用なエッジをスキップするようにコーディングしたが、エラーが多くて使いものにならなかった。
- そのため全てのエッジを検出、さらに変化のない場合も検出して、交互にデータを取得するようにした。
- 有効なデータと、無効なデータ6を、それぞれ32bitのシフトレジスタで構成されたバッファに読み込む。
同期検出で読み込まれた2つのバッファの内容から、HEADERとFOOTERの一致を検出することで、有効データの判定とフレーム検出を同時に行う。
- フレーム検出さえ出来れば、データ部をハミング・デコードしてデータ復号すれば良い。
SystemClockを10MHz(約52μs毎に割込み)として、データ送受信が行えることを確認した。
- 通信クロックの4倍でサンプリングしているので、必要条件は満たしていると思われるが、サンプリング後のデータを観察すると、かなり揺れがみられる。
- この揺れは、データの読取りには直接影響しないはずであるが、波形がナマッた場合にクロックの検出に影響を与える可能性はある。
- サンプリングを8倍(約26μs毎に割込み)とすると、かなり揺れが少なくなることから、実用的にはSystemClockを20MHzとして、26μsサンプリングでの動作が望ましいと思われる。
5これは一般的なバーストエラーのことではなく、単にサンプリングでの話。データのバーストエラーをはじくためには、インターリーブとかしないといけない。
6この時点では、データが有効か無効かを判断出来ない。例えば1が永遠に続くデータの場合、どちらが有効なエッジかを区別するのは不可能であり、データが0なのか1なのかを区別することも出来ない。
[top]
プログラム上の問題点があって少し直した。忘れないようにメモ。→いずれも頻度が少ないので分かりにくいBUGだった
- デューティが極端に7狂った場合にも対処出来るように、ノイズ除去回路の最後の2ビットもチェックするようにした。→ノイズ除去で同じになるので2ビット目だけチェック。
- 50msカウント用のカウンタをリセットするIF文は割込み禁止にする、或は50ms以上とすることで、ここで割込みが起きないようにする。→メインルーチンと割込みルーチンで共通の変数に同時にアクセスしてはいけないという原則を忘れてた。
7ちゃんと考えたんだけど、忘れた。。。
[top]
[電子工作関連に戻る]