開発記録->独自シリアル通信->3回読み取って平均を取る
- 外乱の影響を少しでも軽減するため、三回読み取って平均を取ることとする。
実際の処理は以下の二通り。
three_read_bit = (D1 + D2 + D3) >> 1;
three_read_byte = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
になることを説明する。
three_read_bit = (D1 + D2 + D3) >> 1;
three_read_byte = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
になることを説明する。
一回目(D1):1110
二回目(D2):0110
三回目(D3):1101
二回目(D2):0110
三回目(D3):1101
結果(Ans):1110とする。
手法としては、
D1の0bit目 + D2の0bit目 + D3の0bit目の結果が0〜1ならば0、2〜3ならば1となる。
D1の0bit目 + D2の0bit目 + D3の0bit目の結果が0〜1ならば0、2〜3ならば1となる。
つまり、
0 + 0 + 0 = 0 → 0
0 + 0 + 1 = 1 → 0
0 + 1 + 0 = 0 → 0
0 + 1 + 1 = 2 → 1
1 + 0 + 0 = 1 → 0
1 + 0 + 1 = 2 → 1
1 + 1 + 0 = 2 → 1
1 + 1 + 1 = 3 → 1
0 + 0 + 1 = 1 → 0
0 + 1 + 0 = 0 → 0
0 + 1 + 1 = 2 → 1
1 + 0 + 0 = 1 → 0
1 + 0 + 1 = 2 → 1
1 + 1 + 0 = 2 → 1
1 + 1 + 1 = 3 → 1
となることより明らかである。
(入力に1が二回あれば1、0が二回あれば0だから)
(入力に1が二回あれば1、0が二回あれば0だから)
これをC言語で表現してみる。
unsigned char ans;
switch ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) {
case 0:
case 1:
ans &= 0xE; // B'1110'
break;
case 2:
case 3:
ans |= 0x1; // B'0001'
break;
default:
}
case 0:
case 1:
ans &= 0xE; // B'1110'
break;
case 2:
case 3:
ans |= 0x1; // B'0001'
break;
default:
}
switch ( ((D1>>1)&1) + ((D2>>1)&1) + ((D3>>1)&1) ) {
case 0:
case 1:
ans &= 0xD; // B'1101'
break;
case 2:
case 3:
ans |= 0x2; // B'0010'
break;
default:
}
case 0:
case 1:
ans &= 0xD; // B'1101'
break;
case 2:
case 3:
ans |= 0x2; // B'0010'
break;
default:
}
switch ( ((D1>>2)&1) + ((D2>>2)&1) + ((D3>>2)&1) ) {
case 0:
case 1:
ans &= 0xB; // B'1011'
break;
case 2:
case 3:
ans |= 0x4; // B'0100'
break;
default:
}
case 0:
case 1:
ans &= 0xB; // B'1011'
break;
case 2:
case 3:
ans |= 0x4; // B'0100'
break;
default:
}
switch ( ((D1>>3)&1) + ((D2>>3)&1) + ((D3>>3)&1) ) {
case 0:
case 1:
ans &= 0x7; // B'0111'
break;
case 2:
case 3:
ans |= 0x8; // B'1000'
break;
default:
}
case 0:
case 1:
ans &= 0x7; // B'0111'
break;
case 2:
case 3:
ans |= 0x8; // B'1000'
break;
default:
}
これをちょっとだけ最適化してみる。
(D1の0bit目 + D2の0bit目 + D3の0bit目) / 2 = Ansの0bit目
となる。
これは、
0 / 2 = 0
1 / 2 = 0.5
2 / 2 = 1
3 / 2 = 1.5
となるが、整数型であるので、小数点は切り捨てられるため、
0 / 2 = 0
1 / 2 = 0
2 / 2 = 1
3 / 2 = 1
となることより明らかである。
0 / 2 = 0
1 / 2 = 0.5
2 / 2 = 1
3 / 2 = 1.5
となるが、整数型であるので、小数点は切り捨てられるため、
0 / 2 = 0
1 / 2 = 0
2 / 2 = 1
3 / 2 = 1
となることより明らかである。
unsigned char ans;
if ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) / 2 == 1){
ans |= 0x1;
}
ans |= 0x1;
}
ここで、÷2の動作を「1bit右シフト」に置き換える。
unsigned char ans;
if ( ((D1>>0)&1) + ((D2>>0)&1) + ((D3>>0)&1) ) >> 1 == 1){
ans |= 0x1;
}
ans |= 0x1;
}
ただし、この手法は1bitずつしか出来ないので8bit分実行すると遅くなってしまう。
一気に8bit分を実現する方法は。
まず、三回分の入力信号を次の様に仮定する
D1:1110
D2:0110
D3:1101
D2:0110
D3:1101
これで、一回目と二回目を比較してみると。
2bit目〜0bit目は一致している。
つまり、2/3を獲得しているので、これは確定。
2bit目〜0bit目は一致している。
つまり、2/3を獲得しているので、これは確定。
3bit目だけが不定となる。
つまりD1とD2を比較した結果、
ANS:x110
であることが確定する。
ANS:x110
であることが確定する。
ここで、xは不確定、つまり1と0がそれぞれ一回ずつ存在しているので。
三回目が1ならば1であるし、0ならば0になる。
三回目が1ならば1であるし、0ならば0になる。
と、言う事は。
三回目の結果の3bit目で上書きすれば良い。
ANDとORとXORを使って説明すると。
D1:1110
D2:0110
D3:1101
D2:0110
D3:1101
ANS:1110
D1とD2の差異を抽出→XORする
1110 XOR 0110 = 1000
論理を反転→NOTする→XORする
1000 XOR 1111 = 0111
D1とD2で一致していなかった部分を0にする→さきほどの結果とANDする
1110 AND 0111 = 0110
これで、x110が得られた(x=0にする)ことになる。
D3からD1とD2で未確定だった部分を抽出する→最初の結果とANDする
1101 AND 1000 = 1000
最後に、抽出した結果で3bit目を上書きする→ORする
0110 OR 1000 = 1110
というわけで、ANS:1110と一致しました。
この演算を式に纏めると。
この演算を式に纏めると。
X = D1 XOR D2
X = X XOR 0xFF (Xをビット反転する)
Y = D1 AND X
Z = X AND D3
ANS = Y IOR Z
X = X XOR 0xFF (Xをビット反転する)
Y = D1 AND X
Z = X AND D3
ANS = Y IOR Z
となります。
ここで、D1,D2,D3,ANSの真理値表を作成すると。
真理値表
真理値表
| D1 | D2 | D3 | ANS |
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
となるので。
次に、
f = (Aバー)・B・C + A・(Bバー)・C + A・B・(Cバー) + A・B・C
※D1=A、D2=B、D3=C、ANS=fとした。
を元に、カルノー図を書いて最適化すると。
f = (Aバー)・B・C + A・(Bバー)・C + A・B・(Cバー) + A・B・C
※D1=A、D2=B、D3=C、ANS=fとした。
を元に、カルノー図を書いて最適化すると。
カルノー図
| A/BC | 00 | 01 | 11 | 10 |
| 0 | 1 | |||
| 1 | 1 | 1 | 1 |
よって、
f = A・B・C + A・B + A・C
f = A・B・C + A・B + A・C
となることより、
ANS = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
が導かれる。
ANS = (D1 & D2 & D3) | (D1 & D2) | (D1 & D3);
が導かれる。
また、
ANS = (D2 & D3) | (D1 & D2) | (D1 & D3);
でも実現可能である。
ANS = (D2 & D3) | (D1 & D2) | (D1 & D3);
でも実現可能である。
このwikiの更新情報RSS