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が定義されていない、となっている。

thonny+micropythonからarduino-pico c++へ

これまで、RP2040関係はthonny+micropythonで動かしてきたが、arduno-picoとc++に移行することにした。

というのも、今回GPSナビを作るにあたり試行錯誤しているのだが、フリーズが多発し実用的なデバイスが作れそうにないため。
私の回路技術およびプログラミング技術の低さによるものなのか、そもそも無謀なことをやろうとしているのか、他に原因があるかは判別できていないが、このままでは埒が明かないので新しいやり方を試そうと思う。
特に、SPI液晶+I2Cセンサ+UARTのGPSという異なる3種類のバスをタイマ割り込みも交えつつ動かすというのがよくないのかもしれない。
リンクを見失ってしまったが、ピン割り込みとタイマ割り込みを高周期の設定で併用するとクラッシュするというようなブログの記載があった気がする。

今までCで書かれたライブラリを頑張ってmicropythonにポートしていたが、技術向上という意味では無駄ではなかったと思いたい。

2024年3月20日水曜日

gc9a01pyで円、楕円、三角を簡単に書けるようにする

gc9a01pyは大変有難いライブラリだが、四角と直線と点しか描けないのが弱点。
さすがに不便なので、円、楕円、三角を足した。
https://github.com/matsuura-h/gc9a01py/tree/main
以下は、ランダムに三角を表示している例。

効率のよい描画ロジックを1から作るのは大変なので、LovyanGFXのコードを参考にした。
CからPythonへの移植だが、すべてを手打ちすると大変なので、https://www.codeconvert.ai/c-to-python-converterで自動変換し、自動ではうまく動かない部分を手直しする。
ほとんどのコードはうまく自動変換できるけど、以下の2パターンだけはNGだった。

  1. do-while
    1. 対処方法:while Trueに書き直して、条件文を末尾にif not <condition>: breakとして追加する
  2. 入れ子になったインクリメントやデクリメント
    1. 対処方法:インクリメントやデクリメントを前出しもしくは後出しにする
一つ困っていることとして、gc9a01pyはMITライセンスだが、LovyanGFXはFreeBSDライセンスになっている。
こういうとき、どうやってライセンスを処理すればよいのだろうか?
また、私が移植した部分と元のコードは一体どのように扱うとよいのだろうか?
下手にpull reqestを送ってrusshughesさんやLovyan03さんの迷惑になったら申し訳ないので、とりあえず自分のリポジトリにforkを作って公開してみた。
よい方法をご存知の方がいたら、是非教えてください。

2024年3月18日月曜日

RP2040-ZERO+gc9a01pyの実描画速度を調べてみる

 gc9a01pyはmicropython派にとって大変有難いライブラリだが、どれくらいの速度で描画できるのかが気になる。

Timerと組み合わせて、簡易的にFPSを調べてみる。

サマリは以下の通り。

関数 1回のdot数 fps
line 240 tft.line(0, 0, 240, i, color565(i,255-i,count&255)) 5fps
line 10 tft.line(115, i, 125, i, color565(i,255-i,count&255)) 106fps
pixcel 1 tft.pixel(30+i, 30+j, color565(i,255-i,j)) 948fps
fill_rect 1 tft.fill_rect(30+i, 30+j, 1, 1, color565(i,255-i,j)) 868fps
fill_rect 100 tft.fill_rect(30+i, 30+j, 10, 10, color565(i,255-i,j)) 755fps
fill_rect 240*240 tft.fill_rect(0, 0, 240, 240, color565(i,255-i,j)) 18fps

line, pixelはdot数律速で、だいたい1秒1000dotが限界。
fill_rectは、SPIの命令送信と液晶内部処理の2つが律速。SPIの命令は最大1000回/s発行できる。
液晶内部での描画は、3パターンという少ない試行数からの試算なので意味があるかは怪しいが、今回の結果からは1dotあたり0.94usかかっていると推測される。
SPIの命令発行にかかる時間が変わらないとして、総塗り替えのときは1dotのときに比べ、54.4ms余分にかかっているので、1dotあたりに直すと0.94usとなる。
この結果を100dotに当てはめると803fpsとなり、実際のfpsに近い値になる。
試してみればいいことではあるが、fill_rectの速度推定にある程度役立つ。

以下は、実際に測定に使ったコードと結果の詳細。

■line:240dot
コードはこのような感じ。

  # Timer、計測部分
  from machine import Timer
  def showFPS(t):
      global count, count_prev, tft
      fps = count - count_prev
      tft.text(font,"FPS: {0}".format(fps),40,120,WHITE,BLACK)
      count_prev = count
  
  tim = Timer(period=1000, mode=Timer.PERIODIC, callback=showFPS)
  # 描画部分
  count = 0
  count_prev = 0
  while True:
      for i in range(240):
          count += 1
          tft.line(0, 0, 240, i, color565(i,255-i,count&255))
この例は、直線描画の速度を調べている。
結果、ほぼ5fps。ごくまれに6になるときもあるが、無視してよいレベル。


■line:10dot
今度は、線分の式を「tft.line(115, i, 125, i, color565(i,255-i,count&255))

」に変えてみる。
結果、106fpsくらいまで性能向上する。

lineの中身を見てみるとわかるが、これって結局pixelで1dotずつ描画指令を送信しているので、pixel数の多さで速度が決まるということだ。
このライブラリに限らず、なるべく1点ずつ打つのを避けないと、どんどん描画速度が下がってしまう。

■pixel
じゃあ、今度は1秒に何点打てるのか?を測ってみる。
while True:
    for i in range(180):
        for j in range(180):
            count += 1
            tft.pixel(30+i, 30+j, color565(i,255-i,j))
見てみると、948点/s行けるようだ。
lineで10点ずつ打つと100fps→1000点/sで、240点ずつだと5fps→1200点/sなので、lineの結果ともマッチする。



■fill_rect:1dot
次は、fill_rectを試す。vline, hline, rectも内部でこの式を呼び出している。
fill_rectは、液晶に対し開始終了地点と色を送るだけなので、実はpixelに比べてSPIで送る指示は2byteしか変わらず、送信回数は同じ。
もしSPIの送信がボトルネックとすれば、pixelと遜色ない速度が出せるはず。
while True:
    for i in range(180):
        for j in range(180):
            count += 1
            tft.fill_rect(30+i, 30+j, 1, 1, color565(i,255-i,j))
結果、868fps前後となった。pixelに比べ、8.4%の性能低下で済んでいる。
これは1点ずつの描画だが、次は1回の描画面積が広くなっても変わらないか、試してみる。

■fill_rect:100dot
縦横を10ずつにして、1度に10dotずつ描画させてみる。
while True:
    for i in range(180):
        for j in range(180):
            count += 1
            tft.fill_rect(30+i, 30+j, 10, 10, color565(i,255-i,j))
この場合は755 or 761fpsとなった。RP2040⇔GC9A01の間のSPIは変わらないが、液晶内部の描画が増えた分でこれだけ遅くなったということ。とはいえ13%の性能低下で、1回で更新できるdot数ベースならlineに比べて圧倒的に速い。

最後に、240x240全て塗り替えにすると画像は無いが18fpsくらいだった。さすがに全消去は遅い。

以上。

2024年3月17日日曜日

NMEAの経度・緯度を、Google Mapの形式に変換する

 緯度経度を目にするのはGoogle Map経由という人が大多数だと思う。

Google Mapでは、「https://www.google.com/maps/@<緯度>,<経度>,15z?entry=ttu」として緯度・経度を入力すると、その場所を中心とした地図を表示してくれる。

Google Mapで使う緯度経度は、DEGというフォーマットのよう。
他に、DMMなりDMSなりPOTなりがあって非常にわかりづらい。
GPSの吐き出す生データ(NMEA)は、DMM形式。
よくわからなくなることが多いので、変換方法をメモしておく。

■経度、緯度のフォーマットと相互変換方法メモ

DMM:度分.分
例)北緯3542.60402度=スカイツリー

DEG:度.度
例)北緯35.710067度=スカイツリー

DMM→DEG:int(mod(input, 100)) + mod(input, 100) / 60

DEG→DMM:int(input)*100 + mod(input, 1) * 60


※スカイツリー公式サイトから借用


RP2040のUARTで全文を途切れさせずに読み切る

GPSのNMEAを読み出すとき、文章が長かったりタイミングが悪いと、途中で途切れてしまうことがある。

以下のようにany()を使うと解決する。

■BEFORE

msg = uart.read()

■AFTER

msg = ""
while uart.any():
    msg = msg + str(uart.read())[2:-1]

スライサーで2文字目以降を取ることで、バイト列を文字列に変換したときの先頭の「'b」をスキップしている。-2にして文末もスキップすべき?

RP2040-ZERO+micropythonにてGPS AT6558の日時緯度経度を丸形液晶GC9A01に表示してみる

以前の記事。
RP2040-ZEROとGC9A01の試験→https://matsu-log.blogspot.com/2024/03/aitendom128gc9a01a-gc9a01rp2040-zero.html
GPS AT6558→https://matsu-log.blogspot.com/2024/03/gpsat6558.html

今度は、RP2040-ZEROに液晶とGPSを繋いで、緯度経度を液晶に表示してみる。


USART0を使いたいので、GP0,1を空ける。DCとRSTは、代わりにGP3,4に繋いでおく。

■液晶

  1. GND → GND
  2. VCC → 3V3
  3. SCL → GP6/SPI0 SCK
  4. SDA → GP5/SPI0 TX
  5. RES → GP3
  6. DC → GP4
  7. CS → GP5/SPI0 CSn
  8. BLK → 未使用
■GPS
  1. GND → GND
  2. VCC → 3V3
  3. TX → GP1
    ※RXは繋がなくてもいいので無視

Fritzingで作った回路図。探してみると、RP2040-ZEROなどたくさんのAdd-onパーツが公開されていて非常に有難い。さすがにGPSは無かったので、似たような部品と汎用ヘッダで代用。

以下のようなコードで、$GNGGAと$GNRMCから日時と緯度経度を吸い上げて、液晶に表示した。液晶、GPSをうまく繋げられていたので、これはすんなり作れた。

以下、micropythonコード。

from machine import Pin, SPI
import gc9a01py as gc9a01
import time

import vga2_8x16 as font

from machine import UART
uart = UART(0, baudrate=9600, tx=0, rx=1)

# GPSの結果から日時と緯度経度を抜き出す
def GPS(input):
    if input is None:
        return ("","","","")
    msgs = str(input)[2:-1].split("\\r\\n")
    lat = ""
    lgt = ""
    date = ""
    time = ""
    for msg in msgs:
        if msg[0:6] is "$GNGGA":
            item = msg.split(",")
            if len(item) <= 4:
                continue
            #print(item[1], item[2], item[4])
            time = item[1]
            lat = item[2]
            lgt = item[4]
        elif msg[0:6] is "$GNRMC":
            item = msg.split(",")
            if len(item) <= 10:
                continue
            time = item[1]
            lat = item[3]
            lgt = item[5]
            date = item[9]
    return (date, time, lat, lgt)

# GC9A01初期化
SPI_PORT = 0
SPI_BAUDRATE = 60000000
RESET_PIN = Pin(3, Pin.OUT)
DC_PIN = Pin(4, Pin.OUT)
CS_PIN = Pin(5, Pin.OUT)

spi = SPI(SPI_PORT, baudrate=SPI_BAUDRATE, sck=Pin(6), mosi=Pin(7))
tft = gc9a01.GC9A01(spi=spi, dc=DC_PIN, cs=CS_PIN, reset=RESET_PIN, backlight=None, rotation=0)

bgcolor = gc9a01.color565(0x00, 0x44, 0x22)
tft.fill(bgcolor)

tft.text(font,"GPS Tracker",80,20,gc9a01.BLACK,bgcolor)
while True:
    msg = uart.read()
    ret = GPS(msg)
    pos = 40
    for item in ret:
        if not item is "":
            tft.text(font,item,80,pos,gc9a01.BLACK,bgcolor)
        pos += 20
    tft.fill_rect(88,80,24,40, gc9a01.GREEN)
    time.sleep(0.5)

2024年3月16日土曜日

aitendoの丸形液晶(M128GC9A01A, GC9A01)をRP2040-ZEROで試す

aitendoの丸形液晶 M128GC9A01Aについて、前回、M5+UI FLOWで挑戦するも、失敗。
商品リンク:https://www.aitendo.com/product/20938

今度は、raspberry pi pico互換のRP2040-ZEROで挑戦する。
まずはSPI接続。

以下、スイッチサイエンスさんより画像を借用。
RP2040-ZEROのSPIは2系統あり、片方は裏面のパッドや左右のピンに点在してしまっているので、今回はSPI0を使い右側で固めて配線することにする。電源は左側固定で、さらにジャンパ使うのであまり意味はないが。

配線表とmicropython用のライブラリや使用例を見比べて、以下のつなぎ方に決定。

  1. GND → GND
  2. VCC → 3V3
  3. SCL → GP6/SPI0 SCK
  4. SDA → GP5/SPI0 TX
  5. RES → GP0
  6. DC → GP1
  7. CS → GP5/SPI0 CSn
  8. BLK → 未使用
試しては無いが、たぶん3, 4以外は任意のピンでよいとは思う。
ライブラリはこちら:https://github.com/russhughes/gc9a01py/tree/mainを使わせていただく。
libのgc9a01py.pyをダウンロードし、ThonnyでRP2040-ZEROのルートにこのライブラリのpyファイルを格納すればOK。
下図のように、デバイスのルート直下にファイルが表示されていれば大丈夫。これで、「import gc9a01py as GC9A01」というようにして呼び出せるようになる。

本当に大したコードではないけど、私自身がこのディスプレイをRP2040-ZERO+micropythonで利用するのに結構苦労したので残しておきます。

from machine import Pin, SPI
import gc9a01py as GC9A01

# GC9A01初期化
SPI_PORT = 0
SPI_BAUDRATE = 60000000
RESET_PIN = Pin(0, Pin.OUT)
CS_PIN = Pin(5, Pin.OUT)
DC_PIN = Pin(1, Pin.OUT)

spi = SPI(SPI_PORT, baudrate=SPI_BAUDRATE, sck=Pin(6), mosi=Pin(7))
tft = GC9A01.GC9A01(spi=spi, dc=DC_PIN, cs=CS_PIN, reset=RESET_PIN, backlight=None, rotation=0) 
 
tft.fill(GC9A01.RED)
for i in range(240):
    tft.pixel(i, i, GC9A01.GREEN)
    tft.pixel(120, i, GC9A01.BLUE)
    tft.pixel(i, 120, GC9A01.WHITE)

これがうまく動くと、冒頭の画像のようになる。赤背景に、緑青白の線を引いただけ。
速度を気にするなら矩形や線描写のメソッドを使ったほうがいいはず。

以上。

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日金曜日

身近な材料で銅をエッチングする

自分用のメモ。
「CalendarMemo 作者の独り言」様にて、薬局や百均で買える材料を用いた銅のエッチングのレポートを発見。
http://zatubun.nis-lab.moo.jp/?eid=672

我が家でも試しにやってみたら、うまく銅を溶かすことができた。
材料は以下の通り。

  1. 過炭酸ナトリウム
  2. クエン酸
  3. 食塩
過炭酸ナトリウムとは、実際には過酸化水素水+炭酸ナトリウムのこと。水に溶かすと、アルカリ溶液とH2O2に分離する。

2Na2CO3・3H2O2

画像はWikipediaから拝借

過酸化水素が酸化剤として銅を溶かし出し、クエン酸で銅イオンを溶かしたままにするよう。
また、この反応はハロゲンイオンがあると加速するので、食塩でCl-を供給するみたい。
クエン酸は、余分な炭酸ナトリウムを中和する役割もある。

このやり方に限らず、銅イオンの廃液はそのまま流すのは厳禁とのこと。
アルミホイルを入れて液が青くなくなるまで放置し、固体は濾過したうえで大量の水で薄めて流す必要がある。
もしくは、セメントや吸水ポリマーで固めるか、自然蒸発させてから燃えるゴミに出すのが正しいやり方みたい。

地磁気センサ(電子コンパス)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で緯度経度の一部を塗りつぶしています

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