ラベル I2C の投稿を表示しています。 すべての投稿を表示
ラベル I2C の投稿を表示しています。 すべての投稿を表示

2024年4月21日日曜日

QMC5883Lは不安定?

ーーーーーー
2024/05/08追記:やはり原因はQMC5883Lだった。他は全て同じコードで、I2Cで地磁気を読む部分のみセンサおよびコードをLSM9DS1に置き換えると、少なくとも12時間連続動作させても問題ないことを確認。安物、コピーでもよい用途と、ダメな用途があるという学びになった。
ーーーーーー

GPSと方角ベースのナビを作るべくトライし続けているが、地磁気センサとのI2C通信が安定しないので、いつまで経っても先に進まない。
症状としては、起動後すぐは安定した速度で動作しているのだが、10分?60分?以上経過すると、徐々に地磁気センサからのX,Y,Z軸の磁気情報の読取が遅くなるというもの。

最初はプログラムのミスや外付け回路の不良を疑い、プログラムを書き換えたりI2Cのプルアップの値を変えたりして戦ってきたが、どの方法でも解消しない。

そもそもチップが悪いのではと考えて検索したところ、似たような症状の方を発見。
https://shinshu-makers.net/shinshu_makers/2019/10/02/%E3%80%90%E3%83%91%E3%83%AF%E3%83%BC%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC2019%E3%80%91qmc5883l%E4%B8%8D%E8%AA%BF%E3%81%A7lsm9ds1%E3%81%AB%E4%BA%A4%E6%8F%9B%EF%BC%9Cimu%E3%81%A7ok/

やはり格安チップではダメということか?
似たり寄ったりだが、aitendoで買ったHMC5883Lで再トライすることにする。

2024年3月24日日曜日

RP2040にてarudino-picoでWireを使うときの注意点

まず、ArduinoでRP2040を動かすにはMbed OS RP2040という公式系と、arduino picoというphilhowerさんが作ったバージョンがある。少なくともI2Cの使い方がそれぞれ違う。

公式版は、I2Cで任意のピンを使うのが難しいらしい。なので、arduino-picoを選ぶ。

そして、Wire/Wire1は、setup()やloop()のスコープ中でしか使えない。
グローバルスコープで使おうとすると、未定義となりうまくコンパイルできない。
RP2040-ZeroにてArduino IDEでI2Cを使うとき、micropythonの感覚で書くと失敗する。
こんなのにハマるのは私だけかもしれないが、誰かの役に立つかもしれないので一応公開しておく。

■OKのとき

#inclue <Wire.h>
void setup(){
  Wire1.setSDA(14);
  Wire1.setSCL(15);
}

■NGのとき

#inclue <Wire.h>
Wire1.setSDA(14);
Wire1.setSCL(15); void setup(){ }
ちなみに、NGのときは次のようなエラーが出る。
<ファイルパス>:18:3: error: 'Wire1' does not name a type
   18 |   Wire1.setSDA(14);
      |   ^~~~~
<ファイルパス>:19:3: error: 'Wire1' does not name a type
   19 |   Wire1.setSCL(15);
      |   ^~~~~
<ファイルパス>:20:3: error: 'Wire1' does not name a type
   20 |   Wire1.begin();
      |   ^~~~~
exit status 1
Compilation error: 'Wire1' does not name a type
Wire1が定義されていない、となっている。

2024年3月5日火曜日

地磁気センサQMC5883Lにハマりかける

前回、ATD5883Lを1つ焼いてしまったので、Amazonで格安の類似品を注文。3つで\769と格安。(https://www.amazon.co.jp/dp/B0CFQSW2TG)

aitendoで買ったATD5883Lでうまくいったコードを動かしてみると、そもそもI2Cのアドレスが0x0D (13)と表示され、アドレスを変えて動かすも、なぜかセンサの値が3軸とも0になる。

よくよく調べてみると、このチップは「QMC5883L」というレジスタアドレスが互換ではない似て非なるチップとのこと。
https://leico.github.io/TechnicalNote/Arduino/esp32-qmc5883l-basicにて先人がレジスタをまとめてくださっているので、有難く参照する。

要所は以下の通り。

  • 出力レジスタが異なる
    • MAG_X:0x00-01
    • MAG_Y:0x02-03
    • MAG_Z:0x04-05
  • 出力レジスタ16bitがリトルエンディアンの並び順
  • 連続モードの設定方法が異なる
    • 0x0Bに0x01を書き込み
    • 0x09に0x1Dを書き込み


UI FLOWだと上記の通り。
以下はmicropython。

pin0 = machine.Pin(22, mode=machine.Pin.OUT, pull=0x00)
pin0.off()
i2c0 = i2c_bus.easyI2C((23, 19), 0x00, freq=10000)
wait_ms(100)
print('----start')
print(i2c0.scan())
print(i2c0.available())
wait_ms(100)
i2c0.addr=(0x0d)
wait_ms(100)
i2c0.write_u8(0x0b, 0x01)
i2c0.write_u8(0x09, 0x1d)
print(i2c0.read_reg(0x0D, 1))
while True:
  print(str([i2c0.read_u16(0x00, byteorder="little"), i2c0.read_u16(0x02, byteorder="little"), i2c0.read_u16(0x04, byteorder="little")]))
  wait_ms(100)
  wait_ms(2)

この例では、m5atom liteの3.3V側の端子5pinにセンサを直結している。G22を0V出力にして、G23, 19をI2Cに割り当てればOK。

これでうまく地磁気を読み取れて、めでたしめでたし。

2024年3月2日土曜日

地磁気センサ(電子コンパス)ATD5883Lを試す2

前の投稿の続き(https://matsu-log.blogspot.com/2024/03/atd5883l.html)

aitendoのATD5883Lを試したが、うまくいかなかったのでリトライ。
結論、i2cアドレスと周波数設定と電圧ミスが原因だった。
センサ1個目は、うかつにportAにつないだせいで5Vで焼けてしまったよう…無念。安くない勉強料だ。
2個買っておいたので何とか助かった。
これ、シルクをよく見るとGY-271という基板名っぽい。この名前だとAmazonで安いコピー品が大量にヒットする。

私の買ったデバイスは、100kHz 3.3Vでアクセスすると30, 104という二つのIDがヒットする。
104ではうまく動かず、30でA/B/CのWHO AM Iを読むと、以下の値が読みだされる。
 b'H', b'4', b'3'

ハネウェルの正規品とは異なるので、要注意。

出力結果だが、以下のように、x,y,zを読み取っていい感じにプロットできた。

※ちなみに、この3次元プロットにはhttps://qiita.com/yo16/items/b5af6d2e9d1bf5e8ab51を活用させていただいた


焼けていないほうのチップをm5atomの3.3V, G, 21, 25につなぎ直して、上記のプログラムを走らせれば無事動いた。

x,y,zの生値を見ると、以下の範囲になっている。
 x: -435~649
 y: -556~540
 z: -585~409

乱暴だが、それぞれ中点を取ると107, -8, -88となるので、これをオフセットとして使う。
それなりの精度になっていそうなので、オモチャレベルではこれでよしとしておく。

2024年3月1日金曜日

地磁気センサ(電子コンパス)ATD5883Lを試す

(成功事例はこちら)

今度は、ATD5883L。
秋月の9軸センサを使っていたが、実際IMUは無くても必要十分な精度が出せることがわかったので、コンパスだけで安いこちらを使ってみる。
未だとaitendoで税抜\695。
https://www.aitendo.com/product/9545

小さくて安い

まずはGROVE端子経由のPORTAにつないでアドレスダンプしてみる。



結果、このICは13 = 0x0Dのよう。
このICは「HMC5883L」の互換品らしいので、このワードで使用例を探してみる。

raspiで繋いでいる例が以下のリンクにある。
0x0A,0B,0Cを見れば、識別コードが書いてあるっぽい。
さくっと読み出してみる。


これは正しい値なのか・・・?


strawberryリナックスのサイトを見るに、明らかに間違っていそう。
https://strawberry-linux.com/catalog/items?code=12105
原因もわからないし、今日はここまで。GPSが動いたのでよしとする。

2024年2月25日日曜日

GPSと地磁気センサで、目的地までの距離と方角だけを出す簡易ナビを作る

タイトルの通り。
LSM9DS1をいじっていたのは、これを作るため。

いいアイデアだと思っていたが、既に先駆者がいて製品化までされている。(https://www.plotonline.com/motor/beeline/)
先を越されたのは悔しいから、こっちはネット環境無しでも使えるものを目指したい。
今悩んでいるのは、目的地の緯度・経度をどうやって入力するか?
今のバージョンは、プログラム中に直打ちしてしまっている。

プロトタイプ
左上のマスキングテープの下にLSM9DS1がある
GPSはm5純正品、U032というやつ
完成したら円形液晶とか使って格好よく仕上げたい

コード実行だらけのUI FLOW
素直にmicropythonやArduino C++を使ったほうがいいのかもしれない

初代m5stickc用の.m5fをgithubに上げたので、詳細な中身が知りたいときはそちらをご覧ください。
https://github.com/matsuura-h/lsm9ds1_micropython/tree/main
■方角検出
地味に苦労したのは、磁気センサの値を方角に変換する部分。
atan2に行きつくまでに相当時間がかかった。
地磁気のx, yをプロットしてみると、中心が相当ずれていることがわかる。
現物合わせだが、コード内に直書きでx+0.03, y-0.25の補正を加えている。
本来はoffsetをセンサに書き込むべき。
補正後のx,yを、参考URLのように位相を横軸にプロットしてみる。
それなりのsin, cos波になった。

ちなみに、LSM9DS1をGPSやm5stickcの傍で動かすと、磁界の影響でめちゃくちゃな値になるので注意。

atan2で処理した後も、まずラジアン角から度に直し、±180度から0-360度レンジに変換し、さらに東西南北=90度-270度-180度-0度になるように補正する必要がある。

コード例は以下の通り。
mx0,my0,mz0 = lsm.read_magnet()
deg = math.atan2(my0-0.25, mx0+0.03)*180/math.pi
deg = deg if deg >= 0 else 360 + deg
deg = (deg + 180) % 360

1行目は、自作ライブラリで磁気センサを読み取る部分。
2行目でオフセット補正+角度算出+ラジアン→度への変換をやっている。
続いて、3行目で±180から0-360度に変換。
最後に、このままだと南が0度なので、180度回転させている。
もしセンサを裏表逆に使う場合、最初に正負逆転させるか、atan2の引数の符号を変えることで対応可能。

実際に動かしてみたときの動画
薄い赤の△が北、黒の▲が目的地の方角を示している
m5stickcの描画が遅いのでブレがあるが、ロジック自体は問題無し
あとはフィールド試験




2017年11月27日月曜日

Arduinoのクロック精度を試す

秋月のI2C接続8x2LCDを使ってみた。

変換基板付きで\600、なしだともっと安い。


写真はLCDのみだが、後でRTCも繋いでみた。
LCDとRTCの制御自体はI2Cの作例がいくつもあるので割愛。
コマンド通りに叩くだけ。

検証したいのは、水晶とセラロックや、基板ごとの周波数精度の違い。
1ヵ月くらいのロギングをやるのに、ATmega+セラロックでOKか、水晶が必要かを見極めたい。
使用予定はLeonardoとUno 3(ATmega単体動作も)とArduino Nanoクローン。
温度ログなのでそこまでずれても痛くないけど、せめて1ヵ月で数分くらいの誤差に収めたいところ。

時間はFlexiTimer2でカウント。
LCD表示器に時計を表示して、電波時計を基準にずれを測定。
目視なので、1秒未満の誤差は防げない。
キッチリやるならRTCを正として差分を蓄積していくべき?

↓↓至ってシンプルなコード。
void setup() {
  Wire.begin();
  init_LCD();
 
  FlexiTimer2::set(1000, timer);
  FlexiTimer2::start();
  pinMode(13, OUTPUT);
}


■結果














何と、正規品のArduino Uno 3が一番ずれずれ。
次いで、Ceralock動作のATmega。
Leonardoが最良なのは不思議ではないけど、Maid in Chinaのコピー品のNanoが大健闘。
たった400円なのに凄い。

MsTimer2にすると、Uno 3もいい結果なのかもしれない。
また、Nano以外はばらつきが小さいのでuSleepを適当に入れれば十分な精度になりそう。

■温度ロガー(Arduino Nano + microSD + RTC)
小さいし安いので、本番はArduino Nanoでロガー作成した。
結局、安いRTCが手に入ったのでArduinoのクロック評価は実は意味なし。
タッパーに入れて、サーバの温度データを外部で保存してみた。
会社だとN/W経由で情報を取れないので、ArduinoでMicroSDに貯めると非常に便利。



## 実験は'17/4~5月にやったが、まとめが延び延びになっていた。
  ブログって、気を抜くとすぐに間が空いてしまいますね。