2013年8月19日月曜日

夏休みの工作 ~pythonにおけるセンサ出力値のビット演算~

大した話ではないけど半日詰まったのでメモ。


I2Cなんかから1バイト×2(Hbit、Lbit)のような形でデータを受け取って数値に変換するときの注意点。

例:
Hbyte : 11101110
Lbyte : 00011111

→2つあわせて 1110111000011111 を作ってから数値に変換する。Hの方を左に8bitシフトしたり256を掛けたりしてから足す(あるいはHとLのorをとる)

特にこのあたりでは問題は無いが、2の補数を取って負の値を出したいときpythonでは正常に処理できない場合がある。

例:
H : 10000000
L : 11001100

あわせて 1000000011001100(符号付10進数で-32564) となる。この値をそのままpythonで扱うとpythonの中では32972として扱われる(符号なし扱いのため)。何bitの符号付整数か(どのビットが1だと負扱いなのか)がpythonに認識できないので当然こうなるといえばこうなる。しかしpythonに例えばこのビット列は16ビット符号付整数として扱ってね、とやる方法もちょっとわからなかったので普通にxorを使って2の補数を算出する処理を実装する。これで何ビット整数として扱わせるかもこちらで指定できる。

(プログラムのイメージ)

if H & 0b1000000=0b10000000:   ←Hバイトの頭が1(負数)だったら。ここの数値の桁数でビットを指定している。

   val= (H <<8) | L ←HとLを合体 1000000011001100
   val_inv=val ^ 0b1111111111111111 ←「^」はxor(pythonでは累乗は**なので注意)16bitの全部1の値とxorをとってすべてのビットを反転する。
  val_inv = val_inv+1    ←1足して2の補数にする。この時点で正しい値の絶対値になっている
 out =val_inv*(-1) ←マイナスをつける

以上。これで上の例だと outが-32564になる。
面倒だけどこれをやらないとpythonでは符号付出力のI2Cセンサがまともに使えないので地味に重要。

0 件のコメント:

コメントを投稿