エアガン測定

エアガンに関する色々を測定したりしなかったりしています http://www.eonet.ne.jp/~daisaku-tech/index.html

Blue Pill/STM32duinoで電子コンパスHMC5883Lを動かす

Blue Pill+Arduino_STM32(Roger Clark氏作成版stm32duino環境)

Arduino_STM32(Roger Clark氏作成版)環境のBlue Pillでは、電子コンパスHMC5883Lが動作しません。

2019/03/17時点のmaster

https://github.com/rogerclarkmelbourne/Arduino_STM32

 

注:Arduino_STM32のWebサイトは http://www.stm32duino.com/ となっていますが、 https://github.com/stm32duino とは別物です。

 

このArduino_STM32環境で電子コンパスHMC5883L用ライブラリを使用し、スケッチ例のQMC5883_compassをビルドして実行すると、電子コンパスを動かしても値が変化しません。

2017/12/04コミット版

https://github.com/DFRobot/DFRobot_QMC5883

 

注:ライブラリ名はQMC5883ですが、HMC5883L/QMC5883両対応となっています。

 

このライブラリの、次の2行を削除すると動作します(HMC5883Lのみ)。

DFRobot_QMC5883/DFRobot_QMC5883.cpp:482 行目 DFRobot_QMC5883::readRegister16()

 Wire.beginTransmission(HMC5883L_ADDRESS); ←削除
 Wire.requestFrom(HMC5883L_ADDRESS, 2);
 while(!Wire.available()) {};
 #if ARDUINO >= 100
  uint8_t vha = Wire.read();
  uint8_t vla = Wire.read();
 #else
  uint8_t vha = Wire.receive();
  uint8_t vla = Wire.receive();
 #endif
 Wire.endTransmission(); ←削除

QMC5883では未確認です。

原因:Data Outputレジスタread後に不要なwriteがあるため

直接の原因は、HMC5883Lレジスタのoffset+03~+08のData OutputレジスタX/Y/Zの2バイトずつに対して、それぞれをI2Cでreadしたあと、そのreadした同じ値を2バイトwriteしてしまうことです。

 

理由は不明ですが、上記readRegister16()内でWire.write(reg)でreadするアドレスを指定した後、Wire.read()する際にWire.beginTransmission/endTransmisstionで囲んであるとreadした値をそのままwriteします。

f:id:daisaku_tech:20190318214727p:plain

BluePillの場合

Wire.requestFrom()/Wire.read()するだけならWire.beginTransmission/endTransmissionで囲む必要はないように思えます。

 

ただし、ArduinoUNOでは、上記の2行を削除しなくても正常に動作します。ArduinoUNOの場合は、Data Outputレジスタread後、I2Cのwriteでデータなし(I2CスレーブアドレスとR/Wビットのみ)の状態となり、おかしな値をwriteしないためです。正常に動作するといっても、このように不要なwrite(データなし)が行われます。

f:id:daisaku_tech:20190318214813p:plain

ArduinoUNOの場合

推測ですが、Blue Pillで動作しない原因は次の2つの組み合わせで発生しているように思えます。

  • DFRobot_QMC5883::readRegister16()内の不要なWirte.beginTransmission/endTransmission実行。
  • Arduino_STM32のWire(I2C)ライブラリの不具合。