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

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月4日月曜日

aitendoの丸形液晶(M128GC9A01A, GC9A01)をm5で試す<失敗>

追記:この後UI FLOWでこの液晶を動かそうとしたが、ライブラリを読み込むとメモリ溢れで落ちることが判明。UI FLOWは諦めて、raspberry pi picoで動かすよう方針転換。

後日、RP2040-ZERO+Thonnyでうまく動いたので、動作例が知りたい方はこちらをご覧ください。
https://matsu-log.blogspot.com/2024/03/aitendom128gc9a01a-gc9a01rp2040-zero.html

-------

aitendoの丸形液晶 M128GC9A01Aも買ったので、m5atom matrixで表示できるよう試験する。
商品リンク:https://www.aitendo.com/product/20938


この液晶、中身はGC9A01というコントローラを使ったもので、価格もサイズも手ごろで見た目も綺麗なためか、aitendoだけでなくadafruitやsparkfunなどいろいろな会社からdip化基板セットやタッチパネル、rp2040と組み合わせたセットが出ていて面白い。

■SPIとI2Cのどちらで繋ぐか?

このボードはSPIとI2Cの両方で繋げるようだが、グラフィック関係は帯域の問題からSPIを使うのがよさそう。このサイト(https://emb.macnica.co.jp/articles/8191/)で分かりやすくまとめられているが、bpsの桁が違う。SPIは50Mbpsを狙えるが、I2Cは1Mbpsとのこと。

atom liteは240MHzで、SPIは最大80MHz対応とのこと。
例えば128x128dot、フルカラー8+8+8=24bitを20Hzで更新したいとき、1フレームは128*128*3Byte=49,152Byte=48kBとなり、これを1秒に5枚転送するので、240kB/s=1,920kbps=1.875Mbpsとなる。
I2Cだと1MHzでも1Mbps未満なので、完全に帯域不足。

I2Cは帯域で劣るものの、2線で済むのが一番のメリットで、バイト単位のR/Wで十分なセンサ類と繋ぐのがよい。

■m5atomとの接続

先人のコードを参考に、どこに何を繋げばいいのか読み解いていく。
m5側はUIFLOWだとこんな名前になっているので、それぞれどれと繋げばよいかが問題。


他の液晶の例だが、https://lang-ship.com/blog/work/m5stickc-spi/を参考に何を繋げばよいか検討する。
  1. BLK … 不要 ※バックライトの制御用
  2. CS … GND ※他に繋ぐものが無ければ、L固定でOK
  3. DC … MISO ※RのみでOK
  4. RES … 任意のW ※画面リセット用
  5. SDA … MOSI ※WのみでOK
  6. SCL … SCK
  7. VCC … 3.3V
  8. GND … GND
今回は順番に以下のように接続した。
  1. BLK … n/a
  2. CS … GND
  3. DC … G22
  4. RES … G19
  5. SDA … G23
  6. SCL … G33
  7. VCC … 3.3V
  8. GND … GND
atomはRead Onlyなどで迷うことが無いので楽。
結果、ブロックの設定は次のようになる

そうこうするうちに遅くなってしまったので、続きはまた次回。

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が動いたのでよしとする。

GPSモジュールAT6558を試す

 m5のGPSユニットは安くなく、サイズも大きいので、aitendoの安いモジュール(AT6558)を使えないか試してみる。
https://www.aitendo.com/product/17122
今は税抜き\900と、m5の半額で買える。
ただし、アンテナは別で必要。

chinaの主張を感じる

aitendoから拝借
この画像がめちゃくちゃ役に立つ

汚い配線だが気にしない
とりあえずV,G,RX,TXだけ繋ぐ

早速仮配線し、atom matrixで繋いでみる。

小さくて便利
このチップは3.3Vでないとダメなので、5Vのボードとは繋げない

極々シンプルなプログラム

まずはアンテナ無しで試してみる。
結果、以下のようなメッセージが出る。
電波が拾えずうまく繋げていないことがわかる。

$GNGGA,,,,,,0,00,25.5,,,,,,*64
$GNGLL,,,,,,V,M*79
$GPGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5*02
$BDGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5*13
$GPGSV,1,1,00*79
$BDGSV,1,1,00*68
$GNRMC,,V,,,,,,,,,,M*4E$GNVTG,,,,,,,,,M*2D
$GNZDA,,,,,,*56
$GPTXT,01,01,01,ANTENNA OPEN*25

続いて、アンテナを繋いでリトライ。


ちなみに、このアンテナは特価品で\199のもの。
もうすぐ無くなりそう。
https://www.aitendo.com/product/17558

アンテナを繋ぐと、起動して少し待てば衛星と繋がり、時間や座標を正しく知らせてくれるようになる。

$GNGGA,142138.000,3xxx.1177,N,1xxxx.6385,E,1,10,1.1,4.0,M,0.0,M,,*79
$GNGLL,3xxx.1177,N,1xxxx.6385,E,142138.000,A,A*49
$GPGSA,A,3,13,11,06,29,30,07,36,20,35,,,,2.1,1.1,1.8*32
$BDGSA,A,3,19,,,,,,,,,,,,2.1,1.1,1.8*21
$GPGSV,3,1,11,06,38,135,15,07,30,071,18,09,,,25,11,76,126,17*42
$GPGSV,3,2,11,13,46,214,37,15,14,233,,20,66,000,24,29,22,308,22*7C
$GPGSV,3' 
※xで緯度経度の一部を塗りつぶしています

思ったより簡単に動く。
これで小型化・安価化を達成できそう。

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の描画が遅いのでブレがあるが、ロジック自体は問題無し
あとはフィールド試験




2024年2月24日土曜日

m5シリーズのUI FLOW, micropythonでLSM9DS1を使う

m5のUI FLOWやmicropythonでLSM9DS1を使えるlibrayを作成。
手っ取り早く使いたい方は、githubに説明とコードをupしたので以下を見てください。

秋月のLSM9DS1使用9軸センサモジュール AE-LSM9DS1-I2Cを買ってきて、m5stickCやm5atom matrix, liteで使おうとしたらひとしきりハマりました。

LSM9DS1は、1つのチップにそれぞれ3次元の加速度センサ、ジャイロセンサ、地磁気センサが詰まっていて、9軸自由度=9DoFセンサと呼ばれるもの。
今回はこのうち地磁気センサ、つまり電子コンパスを使う予定。
そもそも6軸imuなら多くのm5デバイスやスマートウォッチにも入っていて、作例も豊富だけど、意外と地磁気センサを使う作例は少ない気がする。

(画像は秋月電子より借用)



LSM9DS1は秋月やスイッチサイエンスでも手に入り、値段もたぶん一番安い。
しかしながら真面目に使おうとすると、分解能を設定し、各センサ値を2byte リトルエンディアンで読み取らないといけず、ちゃんとドキュメントを読まないと手も足も出ない。
自ずから既存のライブラリに頼りたくなるのだが、そのライブラリがArduino C++やcircuitpython向けしかない。

micropython、m5用は全く無い
タコ猫が出てしまう

また、既存のライブラリを移植しようにも、UI FLOWで簡単に使えるI2Cと微妙に読み書き関数の仕様が異なるので、そこの読み解きが難しい。
そして、UI FLOWで使われているi2c_bus.easyI2Cもまたリファレンスや作例がないので模索しながら構築した。

3日以上格闘した結果何とか動くものができたので公開しました。