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します。
Wire.requestFrom()/Wire.read()するだけならWire.beginTransmission/endTransmissionで囲む必要はないように思えます。
ただし、ArduinoUNOでは、上記の2行を削除しなくても正常に動作します。ArduinoUNOの場合は、Data Outputレジスタread後、I2Cのwriteでデータなし(I2CスレーブアドレスとR/Wビットのみ)の状態となり、おかしな値をwriteしないためです。正常に動作するといっても、このように不要なwrite(データなし)が行われます。
推測ですが、Blue Pillで動作しない原因は次の2つの組み合わせで発生しているように思えます。
- DFRobot_QMC5883::readRegister16()内の不要なWirte.beginTransmission/endTransmission実行。
- Arduino_STM32のWire(I2C)ライブラリの不具合。