chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

お越しいただきありがとうございます。

このブログでは主に以下の内容を記載しています(自分の記録用)。

  • 何か作った話(自分は何かを作るために生きている..できたらクスっと笑えるものや、アートと絡みたい)(長続きせず、飽きるのが問題)
  • 音楽(AerophoneやDTM(FL-Studio))を勉強しようと思ったが、音楽はレッスンが続けられないので、、絵に転向しようとしたが、DTMに戻った(が、悶々とするだけで何も作っていない)。テクノ音楽を作れるよう、オンライン教材やソフト(AbletonLive等)に投資中。でもLLMに追い越されて、プロンプト入力したら勝手に音楽作ってくれる時代らしい。
  • 趣味のロードバイク(坂道をひーこら走ると結構大変な人生(笑)と重なる。。その後、定年・再雇用でメインタスクからはずれて仕事のストレスがほぼゼロで最近は全く走っていない。。いかん)

記事が渾然一体となってカオス状態ですが、マイコンのプログラムも、ちゃりで走るのも、料理するのも、自分の中ではそれぞれが繋がっているので、カオスな日常をそのまま反映させています。リンクや引用はご自由にどうぞ。質問等ありましたらコメントに書いてください。微力ながら自分の分かる範囲で回答します。
とにかく、、人に「あほやなぁ」と言われる事に精進するのが我が人生。へこんでも創造の力で進みたい

■2025年目標
今年は音楽(EDM)とAI(ミニマムなLLM、エッジAI(tiny ML))に全振りする(時間、お金、そして情熱?)。

■スターを付けてくださる方へのお礼
古い記事を見つけて時々スターを付けてくださる方がおられます。わざわざお越しくださりありがとうございます。不明な点があればコメント欄に書いておいていただけると、回答できるかもしれません。

Ubuntu環境でFlashライタを使ってUAIPduino上のCH32V003にテストプログラム書き込み

背景:Ubuntuで、RISC-V用ビルド環境と、FlashライタからCH32V003に書き込める環境を作る
結果:昨日作ったFlashライタを使ってサンプルBlink.bin を書き込み、動作確認までOK
詳細:

Flashライタ用ファームを焼いたUIAPduino(画面左)と、素のUIAPduino(画面右)を接続、

Ubuntu環境からminichlinkで接続、以下の様にターゲットマイコン(素のUIAPduino)が見えている状態

$ sudo ./minichlink -i
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
Found rv003-funprog
Programmer firmware version 5.00-201f
There is newer version of programmer firmware available - v.5.20
Interface Setup
Detected CH32V003
Flash Storage: 16 kB
Part UUID: cf-a5-ab-cd-39-bb-be-49
Part Type: 00-31-05-10
Read protection: disabled
USER/RDPR  : 08f7/5aa5
DATA1/DATA0: 00ff/00ff
WRPR1/WRPR0: 00ff/00ff
WRPR3/WRPR2: 00ff/00ff
R32_ESIG_UNIID1: cfa5abcd
R32_ESIG_UNIID2: 39bbbe49
R32_ESIG_UNIID3: ffffffff

Ubuntu環境でお試しでビルドしたblink.cを焼いてみる

$ sudo ../../minichlink/minichlink -w blink.bin  flash
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
Found rv003-funprog
Programmer firmware version 5.00-201f
There is newer version of programmer firmware available - v.5.20
Interface Setup
Detected CH32V003
Flash Storage: 16 kB
Part UUID: cf-a5-ab-cd-39-xx-xx-xx
Part Type: 00-31-05-10
Read protection: disabled
Writing image

Image written.

blinkのソースは以下*1

#include "ch32fun.h"
#include <stdio.h>

#define PIN_1 PD0
#define PIN_K PD4
#define PIN_BOB PD6
#define PIN_KEVIN PC0

int main()
{
        SystemInit();
        funGpioInitAll(); // Enable GPIOs
        funPinMode( PIN_1,     GPIO_Speed_10MHz | GPIO_CNF_OUT_PP ); // Set PIN_1 to output
        funPinMode( PIN_K,     GPIO_Speed_10MHz | GPIO_CNF_OUT_PP ); // Set PIN_K to output
        funPinMode( PIN_BOB,   GPIO_Speed_10MHz | GPIO_CNF_OUT_PP ); // Set PIN_BOB to output
        funPinMode( PIN_KEVIN, GPIO_Speed_10MHz | GPIO_CNF_OUT_PP ); // Set PIN_KEVIN to output

        while(1)
        {
                funDigitalWrite( PIN_1,     FUN_HIGH ); // Turn on PIN_1
                funDigitalWrite( PIN_K,     FUN_HIGH ); // Turn on PIN_K
                funDigitalWrite( PIN_BOB,   FUN_HIGH ); // Turn on PIN_BOB
                funDigitalWrite( PIN_KEVIN, FUN_HIGH ); // Turn on PIN_KEVIN
                Delay_Ms( 250 );
                funDigitalWrite( PIN_1,     FUN_LOW );  // Turn off PIN_1
                funDigitalWrite( PIN_K,     FUN_LOW );  // Turn off PIN_K
                funDigitalWrite( PIN_BOB,   FUN_LOW );  // Turn off PIN_BOB
                funDigitalWrite( PIN_KEVIN, FUN_LOW );  // Turn off PIN_KEVIN
                Delay_Ms( 250 );
        }
}

エラーなく焼けた。minichlinkからターゲットをresetできるようなのでやってみる

$ sudo ../../minichlink/minichlink -b
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
Found rv003-funprog
Programmer firmware version 5.00-201f
There is newer version of programmer firmware available - v.5.20
Interface Setup
Detected CH32V003
Flash Storage: 16 kB
Part UUID: cf-a5-ab-cd-39-xx-xx-xx
Part Type: 00-31-05-10
Read protection: disabled

ターゲットのUIAPduinoの基板に乗っている2つのLEDがチカチカと交互に点滅している。これは最初に入っているデモプログラムとは違う動きなので、新しく焼いたファームが稼働しているのだろうと判断*2。

Ubuntu環境でRISC-V用バイナリのコンパイルと、UIAPduinoをFlashライタに仕立てて、minichlinkからFlashに焼けることが確認できた。あとは、、仕様書を見ながらレジスタを掘ってテストプログラムを書けば、I2CやらSPIやらがC言語から使えるはず。。。
一旦環境構築が終わったので、CH32V003ネタは中断して、逃避している研修用テキストの改定に戻る。。

*1:ソースを見ると、ch32funのライブラリが提供されていて、ライブラリを活用することでGPIOのレジスタを直接書くことなくソースが書けそうな。。Delayも用意されているようだし。。

*2:ch32funのLEDブリンクサンプルソース上で、UIAPduinoのLEDのピン接続がなぜ分かっているのか?は不明->回路図を参照すると、LEDが接続されているPin名はD2/PD0とA7/PD4、ソース上でもこれらのPinに対してL/H操作している。よって2つのLED点滅する。ソース上では同時にL/H操作しているのに、ボード上は交互に点滅している。この理由は、片方のLEDは3.3V-LED-GPIOと接続されており、もう片方のLEDは、GPIO-LED-GNDに接続されているため、L/HでLEDの点灯が逆転する

CH32V003用のビルド環境を構築-> Ubuntu + Dockerでビルド環境はできた

背景:感触を得るためUIAPduinoでLチカする*1
取り組み:軽量のビルド環境(ch32fun)を構築、サンプルコードをビルドして焼く
結論:RISC-V用ビルド環境はできた。まだ焼いていないが、Ubuntu環境からCH32V003に焼くためのFlashライタもできた(エラー出ないので多分OK)
詳細:

ネット上で情報を集めるには自分で知識を再構築する能力が必要となり時間がかかるので、、一冊で全体を見通せることを期待して「CH32V003開発ガイドブック」を発注(boothでPDF版購入)
booth.pm
ざっと読んだ印象として、この本は、Arduino環境、MounRiver Studio、ch32funの3環境での開発方法が整理されており非常に分かりやすい。優れた章立てのお陰で自分が欲しい情報がどこにあるか分かって読むべき章が分かる。迷った時に読み返すと道筋が見えて、細かい所はClaude等に質問したら問題も解決できると思う。

Ubuntu環境でビルド環境を揃えるとして、ビルドツールは、一番コンパクトにバイナリが作れる、ch32funを使う。Ubuntu環境を汚したくないので、Dockerコンテナ内にRISC-Vコンパイルツール一式をインストールしてコンテナ内でコンパイルをする方針。ライター(WCH-LinkE)は安いから追加で買うつもりだが、当面はUIAPduinoに専用ファーム(rvswlink?)を焼いて、minichlinkから呼び出してマイコンのFlashにコードを焼く*2

wiki を見て、おおよそ以下のパッケージ入りのコンテナを作ればよいのかと。。 そのままではコンテナからUSBは使えないようで、追加の作法が必要なのだった。
Debian and WSL

apt-get install build-essential libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev libudev-dev gdb-multiarch

ただ、、上記はRISC-V用のビルド環境と思われ、書き込みツールのminichlinkは作られるのだろうか?*3
コンテナ環境であることを無視すると、ビルドツールを入れた後の作業は以下らしい

# 1.リポジトリをClone
git clone https://github.com/cnlohr/ch32fun.git
# 2. minichlink のビルド
cd ch32fun/minichlink
make
# 3. サンプルに移動して動作確認
cd ../examples/blink
make
#4. minichlinkを駆使してFlashに焼く(ここはトラブルだろう)

BestPracticeではないが、、以下のDockerfileでイメージ構築

# select base image;  debian:bookworm-slim
FROM debian:bookworm-slim

# create work directory
WORKDIR /workspace

# install packages
RUN apt-get update && apt-get install -y \
    build-essential \
    libnewlib-dev \
    gcc-riscv64-unknown-elf \
    libusb-1.0-0-dev \
    libudev-dev \
    gdb-multiarch \
    git \
    && rm -rf /var/lib/apt/lists/*

CMD ["/bin/sh"]
IMAGE_NAME=ch32v_buildenv
docker build -t $IMAGE_NAME .
$ docker images
                                                                    i Info →   U  In Use
IMAGE                            ID             DISK USAGE   CONTENT SIZE   EXTRA
ch32v_buildenv:latest            93caf30835cd        806MB             0B
sudo apt install gh
gh auth login
gh repo clone cnlohr/ch32fun
 ls -F
ch32fun/
$ ls -F
build_scripts/   examples_h41x/  examples_v20x/  extralibs/   package.json
ch32fun/         examples_l103/  examples_v30x/  LICENSE      platformio.ini
examples/        examples_usb/   examples_x00x/  minichlink/  projects/
examples_ch5xx/  examples_v10x/  examples_x035/  misc/        README.md

リポジトリがローカルに配置できたので、ここを作業場所としてマウントしつつコンテナを起動する

$ ls -F
ch32fun/
$ pwd
/home/<ID>/tech/uc/ch32v

教科書通り、起動した後は消すという事なら以下で起動

docker run -it --rm -v /home/<id>/tech/uc/ch32v:/workspace ch32v_buildenv:latest 

以下でminichlinkをビルド

cd minichlink/
make

とりあえず走らせてみる->怒られる

# ./minichlink
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
VID:0x1209, PID:0xb003
Error: Could not initialize any supported programmers

コンテナから出て素のUbuntuでツールを実行する。それでも同じように怒られる。ただ、、コンテナ内だと、グループに対して怒られているが、このお叱りはなくなって、素のUbuntuでは書き込みツールが無いと怒らている。だとすると、、UIAPduinoをリセット起動してHIDにしておけばそのまま書けるのか?

$ ./minichlink
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
VID:0x1209, PID:0xb003
Error: Could not initialize any supported programmers

DeskTopのUbuntuに接続したがどうも認識されないような。。dmesgの内容は以下。usbとして接続エラーのような

[ 8548.418136] usb 2-1.4: New USB device found, idVendor=1209, idProduct=b803, bcdDevice= 1.41
[ 8548.418147] usb 2-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 8548.418151] usb 2-1.4: Product: 32V003
[ 8548.431555] hid: raw HID events driver (C) Jiri Kosina
[ 8548.434974] usbcore: registered new interface driver usbhid
[ 8548.434977] usbhid: USB HID core driver
[ 8548.438616] hid-generic 0003:1209:B803.0001: hiddev0,hidraw0: USB HID v1.10 Device [32V003] on usb-0000:00:1a.0-1.4/input0
[ 8572.462574] usb 2-1.4: USB disconnect, device number 7
[ 8580.135763] usb 2-1.4: new low-speed USB device number 8 using ehci-pci
[ 8580.201762] usb 2-1.4: device descriptor read/64, error -32
[ 8580.369761] usb 2-1.4: device descriptor read/64, error -32
[ 8580.535759] usb 2-1.4: new low-speed USB device number 9 using ehci-pci
[ 8580.601759] usb 2-1.4: device descriptor read/64, error -32
[ 8580.769760] usb 2-1.4: device descriptor read/64, error -32
[ 8580.871886] usb 2-1-port4: attempt power cycle
[ 8581.451750] usb 2-1.4: new low-speed USB device number 10 using ehci-pci
[ 8581.863746] usb 2-1.4: device not accepting address 10, error -32
[ 8581.927747] usb 2-1.4: new low-speed USB device number 11 using ehci-pci
[ 8582.343740] usb 2-1.4: device not accepting address 11, error -32
[ 8582.343873] usb 2-1-port4: unable to enumerate USB device
[ 8931.231866] usb 2-1.4: new low-speed USB device number 12 using ehci-pci
[ 8931.296868] usb 2-1.4: device descriptor read/64, error -32
[ 8931.465870] usb 2-1.4: device descriptor read/64, error -32
[ 8931.631873] usb 2-1.4: new low-speed USB device number 13 using ehci-pci
[ 8931.697876] usb 2-1.4: device descriptor read/64, error -32
[ 8931.865877] usb 2-1.4: device descriptor read/64, error -32
[ 8931.968043] usb 2-1-port4: attempt power cycle
[ 8932.547889] usb 2-1.4: new low-speed USB device number 14 using ehci-pci
[ 8932.959895] usb 2-1.4: device not accepting address 14, error -32
[ 8933.023898] usb 2-1.4: new low-speed USB device number 15 using ehci-pci
[ 8933.439900] usb 2-1.4: device not accepting address 15, error -32
[ 8933.440030] usb 2-1-port4: unable to enumerate USB device
[ 9351.512103] usb 5-1: new low-speed USB device number 2 using xhci_hcd
[ 9351.691143] usb 5-1: device descriptor read/64, error -71
[ 9351.975171] usb 5-1: device descriptor read/64, error -71
[ 9352.261089] usb 5-1: new low-speed USB device number 3 using xhci_hcd
[ 9352.440171] usb 5-1: device descriptor read/64, error -71
[ 9352.726171] usb 5-1: device descriptor read/64, error -71
[ 9352.829444] usb usb5-port1: attempt power cycle
[ 9353.272094] usb 5-1: new low-speed USB device number 4 using xhci_hcd
[ 9353.274815] usb 5-1: Device not responding to setup address.
[ 9353.486803] usb 5-1: Device not responding to setup address.
[ 9353.692094] usb 5-1: device not accepting address 4, error -71
[ 9353.869095] usb 5-1: new low-speed USB device number 5 using xhci_hcd
[ 9353.871816] usb 5-1: Device not responding to setup address.
[ 9354.078802] usb 5-1: Device not responding to setup address.
[ 9354.284094] usb 5-1: device not accepting address 5, error -71
[ 9354.285420] usb usb5-port1: unable to enumerate USB device

普通につないだ時、0x1209:0xb803として認識される。

root@upkubu01:/var/log# lsusb
Bus 005 Device 006: ID 1209:b803 Generic 32V003

dmesgの結果

[ 9912.347981] usb 5-1: new low-speed USB device number 6 using xhci_hcd
[ 9912.542480] usb 5-1: New USB device found, idVendor=1209, idProduct=b803, bcdDevice= 1.41
[ 9912.542490] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 9912.542494] usb 5-1: Product: 32V003
[ 9912.546969] hid-generic 0003:1209:B803.0002: hiddev0,hidraw0: USB HID v1.10 Device [32V003] on usb-0000:03:00.0-1/input0
root@upkubu01:/var/log# lsusb -v -d 1209:b803

Bus 005 Device 006: ID 1209:b803 Generic 32V003
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 [unknown]
  bDeviceSubClass         0 [unknown]
            *略*

手を放すタイミングだが、、すぐに手を放せと書いている。これを守ってみる。

[10412.417749] usb 5-1: new low-speed USB device number 7 using xhci_hcd
[10412.596832] usb 5-1: device descriptor read/64, error -71
[10412.902179] usb 5-1: New USB device found, idVendor=1209, idProduct=b803, bcdDevice= 1.41
[10412.902189] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10412.902193] usb 5-1: Product: 32V003
[10412.905725] hid-generic 0003:1209:B803.0003: hiddev0,hidraw0: USB HID v1.10 Device [32V003] on usb-0000:03:00.0-1/input0

0x1209:0xb003(rv003usbのブートローダ専用PID)となってほしいところが、0x1209:0xB803になっている。これは普通のHIDらしい。LEDがもやもやと点滅している状態が書き込みモードと思うのだがデバイスをこの状態にするとHIDとして認識されない。(追記:HIDとして認識されないのは、もやもや点滅はLEDブリンクのデモプログラムでありこの状態ではUSBドライバが走っていない。RESET短押しの状態だとUSBドライバを含むモニタプログラムが走り、OSからはUSBデバイス(1209:B803)として認識される)

いろいろやってみて自分の理解
1. UIAPduinoに焼ける状態となるには、RESETボタンを押しながら電源投入時する。この時、1209:B003となるはず(追記:ボード側は0x1209:0xB803になる)
2. minichlinkから焼く時は、相手が 1209:B003であることを期待する(追記:1209:B003を期待するかもしれないが、Windows版では、0x1209:0xB803でも焼ける。UIAPduino側は問題ない、Ubuntu側での特有の問題が発生している)
3. Ubuntuマシンの場合、RESETボタンを押しながら電源投入しても、USBデバイスは認識エラーとなる。よって、1209:B003としては接続できない(追記:RESETを長押しするからデモプログラムに移行してNGとなる、すぐに離すと、1209:B803になる)
4. UIAPduinoをFlashライターとして仕上げるための回避策としては、実績の多いWindows環境でFlash用ファームを焼いてライタに仕上げるのが良いのでは 。仕上がってからUbuntuマシンに接続して使う(追記:この回避策は効果があった)

Ubuntu環境のminichlinkから出力されるエラー。1209:B003が見つからないと怒っていると思われる

$ ./minichlink
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
VID:0x1209, PID:0xb003
Error: Could not initialize any supported programmers

(追記):なぜ、1209:B803だと焼いてくれないのかが不明、Windows版だと1209:B803でも書き込みできる。一般権限でminichlinkを走らせている点はテスト誤り(追加試験でroot権限で走らせても同じ結果)

いきなりUbuntuで焼くのはあきらめて、まずはArduino IDEを使って、flashライタ用ファームを焼くことにする。uiapボードのセットアップをすると、必要なツールがインストールされる。メッセージを見ているとどんなツールが入るのかが分かって興味深い。

RESETボタン押しながらUSB接続すると、不明なデバイスとは怒られないが、、デバイスIDは、1209:B803になっている。これでOKなのか? (Resetボタンの細工をしないと、不明なデバイスと怒られる)

Arduino IDEからLチカやってみる

書き込みは成功した

わかりやすくチカっと光らせたいのでタイミングを変更

#define LED_BUILTIN 2
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // change state of the LED by setting the pin to the HIGH voltage level
  delay(100);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // change state of the LED by setting the pin to the LOW voltage level
  delay(1000);                      // wait for a second
}

元のBlinkを少し修正、手順に従って操作したら一発で書き込みまで完了した。さすがArduino + 作者様のセットアップ。。。
安定してファームが焼けるということで、このままFlashライターに仕立てたいのだが。。Arduino版のFlashライタソースがどこにあるのか。。Claudeに聞いたけど、無さそうだという回答*4
Claudeと話をすると、、Windows版のminichlinkが動いているはずで、minichlinkは書き込みモードのUIAPduinoと通信できるはずだと。だから、Ubuntu 等でビルドしたCH32V003用のFlashライタbin(hex?)をWindows環境に持ってきて直接焼いたらいいのでは?と言ってきた。

UbuntuのRISC-Vビルド環境で以下をビルドすると
github.com
できたHEXかBINをWindows環境のminichlinkでUIAPduinoに焼くと。。

以下でCLONE

gh repo clone cnlohr/rv003usb

以下でコンテナ起動(ch32vでマウントしているので、、このまま使う)

docker run -it --rm -v /home/<id>/tech/uc/ch32v:/workspace ch32v_buildenv:latest 

コンテナに入ってrv003usb/rvswdio_programmerでMakeしたらバイナリはできた

-rw-r--r-- 1 root root  32310 Sep 26 11:40 rvswdio_programmer.map
-rwxr-xr-x 1 root root 142808 Sep 26 11:40 rvswdio_programmer.elf
-rw-r--r-- 1 root root 362083 Sep 26 11:40 rvswdio_programmer.lst
-rwxr-xr-x 1 root root  15756 Sep 26 11:40 rvswdio_programmer.bin
-rwxr-xr-x 1 root root      0 Sep 26 11:40 rvswdio_programmer_ext.bin
-rw-r--r-- 1 root root  44330 Sep 26 11:40 rvswdio_programmer.hex
root@accxxxxxa:/workspace/rv003usb/rvswdio_programmer# pwd
/workspace/rv003usb/rvswdio_programmer

binなのか、elf なのか、hexか、どれが焼けるのか分からないが、、とりあえずこれらをwindows環境に転送する

ArduinoからUIAPduinoへの書き込みはminichlinkを使っていて、その時のコマンド配下

"C:\Users\<user_id>\AppData\Local\Arduino15\packages\UIAP\tools\minichlink-2982dfd\1.0.0\minichlink.exe" -w "C:\Users\<user_id>\AppData\Local\arduino\sketches\4A097E6CB27DD9D682B0BD2B63CF3004\Blink.ino.bin" flash
Found UIAPduino Pro Micro CH32V003 V1.4 Bootloader

上記実行パスを流用しつつ、書き込みファイルを、rvswdio_programmer.bin にしたら焼けるはず。
以下で焼くには焼いた。

$ /cygdrive/c/Users/<user_id>/AppData/Local/Arduino15/packages/UIAP/tools/minichlink-2982dfd/1.0.0/minichlink.exe -w rvswdio_programmer.bin   flash
Found UIAPduino Pro Micro CH32V003 V1.4 Bootloader
Halting Boot Countdown
Interface Setup
Image written.

ちなみに、、この状態で普通にWindowsPCに接続すると、不明なデバイスとは怒られない。デバイスマネージャではそれらしいデバイスが見つけられず。
Ubuntuでは以下と認識される(dmesg)

[21751.680785] usb 2-1.4: new low-speed USB device number 22 using ehci-pci
[21751.763896] usb 2-1.4: New USB device found, idVendor=1206, idProduct=5d10, bcdDevice= 0.02
[21751.763907] usb 2-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[21751.763910] usb 2-1.4: Product: RV003 RVSWDIO Programmer
[21751.763913] usb 2-1.4: Manufacturer: CNLohr
[21751.763916] usb 2-1.4: SerialNumber: RVSWDIO003-01
[21751.767483] hid-generic 0003:1206:5D10.0009: hidraw0: USB HID v1.10 Device [CNLohr RV003 RVSWDIO Programmer] on usb-0000:00:1a.0-1.4/input0
root@upkubu01:~# lsusb
Bus 002 Device 022: ID 1206:5d10 CNLohr RV003 RVSWDIO Programmer

素性は以下と認識されている。HIDが当初想定と違っているのだが、このファームは、WCH-LinkE を目指していると書かれていた気が。。

root@upkubu01:~# lsusb -v -d 1206:5d10

Bus 002 Device 022: ID 1206:5d10 CNLohr RV003 RVSWDIO Programmer
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 [unknown]
  bDeviceSubClass         0 [unknown]
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x1206 CNLohr
  idProduct          0x5d10 RV003 RVSWDIO Programmer
  bcdDevice            0.02
  iManufacturer           1 CNLohr
  iProduct                2 RV003 RVSWDIO Programmer
  iSerial                 3 RVSWDIO003-01
~/tech/uc/ch32v/ch32fun/minichlink$ sudo ./minichlink -i
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
Found rv003-funprog
Programmer firmware version 5.00-201f
There is newer version of programmer firmware available - v.5.20
Error: Setup chip failed. Got code 00000000
Error: Setup chip failed. Got code 00000000
Error: Setup chip failed. Got code 00000000
Error: Setup chip failed. Got code 00000000
Could not setup interface.

すくなくとも、ライタが居ないと怒られることはなくなった。(そもそもUSBを使うにはroot権限が必要なようであった)
ChipSetupのエラーになっているのは、書き込み対象のCH32V003が接続されていないためと思われる。
Claudeからの回答


■試行錯誤振り返り
1. UIAPduinoを書き込みモードでUbuntuに接続してもHIDとして認識されない。Ubuntu環境からUIAPduinoの書き込みモードを使うのはあきらめる
2. 回避策として、Windows版Arduino環境を整えてuiap用ボード環境をセットアップ、UIAPduinoに書き込めることを確認
3. UbuntuでFlashライタ用ファームをビルド(RISC-V用ファーム)
4. Windows環境で、minichlinkを走らせて上記ファームをUIAPduinoに焼く
5. Flash用ファームを焼いたUIAPduinoをUbuntuマシンに接続、Ubuntu上のminichlinkから接続確認->接続正常

どうやってターゲットと接続するのかちょっとわからないのだが、、GitHubの図を引用すると以下

(cnlohr氏のGitHubより)
https://github.com/cnlohr/rv003usb/tree/master/rvswdio_programmer

今回はClaudeと相談しながら構築を進めました。一日でビルド環境構築と、CH32V003用Flashライタ作成までできましたが、一人でやっていたら数日かかっていたと思われる。そもそもゴールまでたどり着けたかどうかも怪しい。。

■再調査
UIAPduinoが書き込み状態の時に、本当にUbuntuから認識できなかったのかを再確認。Youtubeで書き込み動画があり、動画ではRESETボタンをすぐに離されていた。同じことをUbuntuマシンでもやってみた時に、以下のID(1209:b803)で認識されている。このGeneric 32V003のデバイスの状態でminichlinkからライタとして使ってもらえるのかが不明(Claudeは、1209:B003でないと使えないと言っていて、確かに、minchlinkは1209:B003ではないと怒っていた)

$ lsusb
Bus 002 Device 004: ID 1209:b803 Generic 32V003

ただ、、PCの時も1209:B803の状態でArduino IDEから書き込みができたのと、Flashライタとして仕上がったUIAPduinoの接続テスト時、root権限付けずにminchlinkからつなごうとしたら、1209:B003でないと怒られ、root権限付きでminchlinkを動かすと、エラーなく繋がった。なお、この時のIDは、1209:B003ではなく、1206:5d10 であった。だから、、Flashライタとして、何種類かに接続できるように作らていると思われる(ソース読めという感じですが)
一般ユーザ権限で接続テストすると、いつものエラーで怒られる

$ ~/tech/uc/ch32v/ch32fun/minichlink/minichlink
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
VID:0x1209, PID:0xb003
Error: Could not initialize any supported programmers

root権限でも同じエラーであった。だからFlashライターとしては認められないと。。ボードは電源LEDだけが点灯している状態

$ sudo ~/tech/uc/ch32v/ch32fun/minichlink/minichlink -i
WARNING: You are not in the plugdev/dialout group, the canned udev rules will not work on your system.
minichlink version - bfff1cf2158794a1676d65d1ec2fc1d7d54f555b
VID:0x1209, PID:0xb003
Error: Could not initialize any supported programmers

Ubuntu から見えているデバイス情報は以下

$ sudo lsusb -v -d 1209:b803

Bus 002 Device 004: ID 1209:b803 Generic 32V003
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 [unknown]
  bDeviceSubClass         0 [unknown]
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x1209 Generic
  idProduct          0xb803 32V003
  bcdDevice            1.41
  iManufacturer           1
  iProduct                2 32V003
  iSerial                 3
  bNumConfigurations      1

だったら、あのLEDがもらっと点滅している状態だとUSBデバイスとしてはどう認識されるのか??
UbuntuとしてはUSBデバイスとしては認識していない。多分ボード内でUSBドライバが走っていないと思われる。WindowsPCでも不明なデバイスと怒られるので。テストプログラムだけが走っている状態なのだろう。
結局、1209:b803 の状態で焼けないのは、minichlink起動時のオプションが足りないのか、1209:B803から別のモードに切り替えないといけないのか?? Windows版minchlinkでどう書き込めているのか、手打ちで起動したらもう少し分かるのではと調査...  UIAPduinoを書き込みモードにして、Windows版minchlinkで接続すると以下と表示される。この時、ボードのIDが何なのか分からない。

$ ./minichlink.exe  -i
Found UIAPduino Pro Micro CH32V003 V1.4 Bootloader
Halting Boot Countdown
Interface Setup
USER/RDPR  : 08f7/5aa5
DATA1/DATA0: 00ff/00ff
WRPR1/WRPR0: 00ff/00ff
WRPR3/WRPR2: 00ff/00ff
Flash Size: 16 kB
R32_ESIG_UNIID1: cfa5abcd
R32_ESIG_UNIID2: 39bbbe49
R32_ESIG_UNIID3: ffffffff

この状態で、USBデバイス一覧を表示、以下の通り、1209:B803として見えている。この状態でminichlinkは書き込み対象と認識している。だから、UIAPduinoとしては、1209:B803で待っている状態が正しい。Ubuntu でも、1209:B803で待っていた。だがminichlinkから書き込み対象なしと怒っていた。UbuntuではUIAPduino側の問題ではなく、USB経由での接続か、minichlink内の問題か、オプション不足によるものか、、いずれかと思われる。エラーメッセージである、VID:0x1209, PID:0xb003というものがなぜ出ているのかは分からないが、VID:0x1209, PID:0xb003のみを探しているわけではないと思われる。

PS C:\WINDOWS\system32>   Get-PnpDevice | Where-Object {$_.FriendlyName -like "*UIAPduino*" -or $_.FriendlyName -like "*HID*"} | Select-Object FriendlyName, InstanceId

FriendlyName                                  InstanceId
------------                                  ----------
                         *略*
HID 準拠デバイス                              HID\VID_1209&PID_B803\6&2C9D86C2&0&0000
                         *略*

■参考URL
github.com
github.com

|

*1:Arduinoのエコシステムが苦手なので、なるべく素でmakeしたい

*2:UIAPduinoにはライタ不要になるよう、USB-HIDとして起動されるファームが入っているのでライタなしでいいのだが、ファーム無しの素のCH32V003にも対応できるようにと思って、自力で焼ける環境を作る

*3:Geminiに質問すると、 build-essentialに86系のビルドツール一式が含まれるとのこと

*4:CH32V003を使い倒している人ならすぐにわかるのだろうけど、、自分は詳しいことは分からない

UIAPduino Pro Micro CH32V003を発注した

背景:普段はRaspberry Pi Pico 2 (RP2350)を使っていてMicroPythonで気楽にプログラミングやってるのだけど、知り合いの人から、UIAPduino について質問を受けた
取り組み:UIAPduinoに搭載されているマイコンはCH32V003というかなり省資源なRISC-Vマイコンの様で、プログラミングはC/C++か、Arduino*1を使うらしい。RAMは2KBしかないのでインタプリタは動かずコンパイル型言語のみ。使ってみないとどれぐらい使えるものか分からないので、UIAPduino Pro Micro CH32V003を発注した。在庫が結構なくなってるようで、共立電子に発注した。

UIAPduinoは開発者の思いがこもった熱いマイコンボードとは思いますが、、省資源なマイコンなので使いこなすのも実はテクが必要ではないかと。。。何も考えずにプログラミングしたらRAM枯渇するのではないか。。 2KBもあったら十分??
個人的には、、この省資源マイコンに、豊四季TinyBasicを載せてみたいけど。。。また泥沼に陥るのだろうか。
■追記
TinyBasicを動かしている先人がおられました。
note.com
やっぱり、CH32V003を動かすなら、↑のように、素っ裸(失礼)で動かしたいですよね。。シリアルだけが出ているような。。

いっそのこと、俺Basicを作ってしまう?


■追記
TinyBasicの文法をClaudeに質問した結果

Tiny BASICには複数の実装(Palo Alto Tiny BASIC、Tom PittmanのTiny BASICなど)がありますが、
Dennis Allisonが1975年にPeople's Computer Companyで発表した「オリジナル仕様」のBNF文法が
最もよく参照されます。以下がその骨子です。

基本文法(BNF)
line        ::= number statement CR | statement CR

statement   ::= PRINT expr-list
              | PR expr-list
              | INPUT var-list
              | LET var = expression
              | GOTO expression
              | GOSUB expression
              | RETURN
              | IF expression relop expression THEN statement
              | REM 任意の文字列
              | CLEAR
              | LIST
              | RUN
              | END

expr-list   ::= (string | expression) (, (string | expression))*

var-list    ::= var (, var)*

expression  ::= (+|-|ε) term ((+|-) term)*

term        ::= factor ((*|/) factor)*

factor      ::= var | number | (expression)

var         ::= A | B | C | ... | Z

number      ::= digit digit*

digit       ::= 0 | 1 | ... | 9

relop       ::= '<' ('>' | '=' | ε)
              | '>' ('<' | '=' | ε)
              | '='

string      ::= " ( 任意の文字 )* "

■追記
CH32V003の2KB RAMでも動作できるTinyBasicを作ってみようかと思って試作を始めたけど、ミニマムにすると仕様の細かい所が収まり悪く(代入文)、ミニマムな言語として有名なForthをベースにCH32V003用のTinyForthを作ってみることにする。

■追記
CH32V003(UIAPduino)が届いたのでビルド方法とかを調べ始めた。特にファームの書き込みが、1線式(1-wire SWD)の独自仕様のため、標準のOpenOCDでは焼けなかったりとなかなか大変なマイコンであることが分かった。RISC-VであるのはOKなのだが、、振り返ってみると、知り合いの人から、「UIAPduinoってどうなの?」と聞かれなかったら、CH32V003には手を出していなかっただろうと思う。CH32V003を使い倒している人が大勢いて、その情熱に頭が下がる思いです*2。

■参考URL
www.uiap.jp
eleshop.jp
akizukidenshi.com
www.wch-ic.com

*1:Arduinoも本質的にはC/C++らいしい(普段使わないので詳細分からず)

*2:秋月なら50円で買えるのですね。これは確かに価格破壊だ。50円なら常識を覆してあっぱれと思う。かつて坂村教授が家じゅうにマイコンまいてユビキタス!と叫んでいたけど、50円なら家じゅうの家電や建具に埋め込みできそうだ。何のため?どうやって通信するか?はおいといて

OP-Zのパーツが破損->3Dプリンタで修理パーツ作成

背景:OP-Zをごくたまに使うのだが、OP-Zの左上に付いてる黄色の電源兼ボリュームのつまみが割れてしまった。fixitでパーツが販売されているけど、今は在庫なし
取り組み:3Dプリンタ用のCADデータが配布されているので、これを入手して、知り合いに頼んで3Dプリンタを使わせてもらう
結論:3Dプリンタで出力した代替パーツは、ほとんど調整なしでぴったり収まった
詳細:
OP-Zを持っているが、とうてい使いこなせていない。ごくたまにリズムを打ち込んでみる程度。OP-Z本体の左上に、黄色の電源兼ボリュームが付いてるのだが破損しているのに気づいた。

電源スイッチを兼ねており、修理しないとスイッチが入らない。fixitというサイトがあって、ここで修理パーツ(OP-Z Volume Knob)が販売されているけど今は在庫なし。
3Dプリンタ用データが配布されており、それを使って、知り合い(FabBase)の3Dプリンタを使わせてもらうことにした。データはPrintablesで入手できる。使わせもらったのはBambu LabのBambu Lab A1というタイプ(一番売れているタイプと思いますが*1)。以下は印刷風景

以下が出力された修理パーツ(左が出力したパーツ、右がオリジナルパーツ)

特に調整せずともすんなり軸に取り付けられた。はめ合いというのか、軸への収まり具合もきつすぎず、緩すぎず最適

パーツの端がエッジ立っていて手に痛いので、2000番のやすりでちょっと面取りしました。

■参考URL
www.ifixit.com
www.printables.com

*1:印刷を横で見てましたが利用開始時、キャリブレーションなのか結構音がします

NiceGUIで温度センサビューアを試作

背景: マイコンで計測した値をどうやって表示するかが課題。キャラクタディスプレイに出す、MQTTブローカ経由でIoT プラットフォームに送り付ける、マイコンがWebServerとなって、自分で絵作りする。。etc
取り組み: USB SerialでPCと繋がっている状態で、手軽にグラフ表示できる方法を考える。Thonnyのグラフ機能を使う手もあるけど、自由度を考えてThonny以外の方法を考える。Pythonで手軽に作れるWebサービス(?)、NiceGUIを使って温度センサビューアを作ってみる*1。

詳細:
WSLにNiceGUIと関係ライブラリをインストール。今時は環境を汚さないために、ローカルにvenvを作ってそこに個人のライブラリを入れるらしい。

mkdir projects
mkdir projects/rp2350_temp_sensor
cd projects/rp2350_temp_sensor
python3 -m venv .venv
source .venv/bin/activate
pip install nicegui
pip install pyserial
pip install matploib
ln -s  ~/lang/py/nicegui/rp2350_temp_sensor/  ./src

nicegui.io

お手軽なセンシングとして、RP2350には温度センサが内蔵されているのでこれを使う。RP2350の温度センサの値をPCのブラウザでリアルタイム表示する想定で、試作アプリを組んでみた。PC側のビューアの外観は以下

NiceGUIのコードは以下(大半のClaudeに書いてもらったので、細かいオプション等は不明です。Claudeと相談しながらコードを作ると1時間もかからずに書けてしまう。。自分はあまり理解できていない。良いのか悪いのか。。)
GUIのボタンを押した時は登録されたcallbackが呼び出される。一定周期で更新したい場合は、timerを使い、これも一定周期でcallbackで呼び出される。呼び出された関数内で、RP2350から温度を取ってきて、グラフオブジェクトに値を追加する。今は軽い動作なので問題ないけど、、callbackで時間がかかったらGUI更新されないとか、無応答とかになりそうなのだが。。

from nicegui import ui
from datetime import datetime
import random

# regist start time for drawing graph
start_time = datetime.now()

ui.label('Temperature Sensing DEMO').classes('text-2xl font-bold')
ui.label('Temperature graph')
temp_plot = ui.line_plot(n=1, limit=100, figsize=(6, 3), update_every=1) \
    .with_legend(['temp'], loc='upper right')

label_status = ui.label('status: none')

def on_click_start():
   label_status.set_text('Sensing started')
   timer.activate()

def on_click_stop():
   label_status.set_text('Sensing stopped')
   timer.deactivate()

def read_temperature():
   return 23.5 + random.uniform(-5.0, 5.0)

def on_timer():
    temp = read_temperature()
    timestamp = datetime.now()
    timestamp_iso = timestamp.isoformat(timespec='seconds')
    log_area.push(f'{timestamp} {temp:.2f} C')

    elapsed = (timestamp - start_time).total_seconds()
    temp_plot.push([elapsed], [[temp]])

with ui.row():
   ui.button('START', on_click=on_click_start)
   ui.button('STOP', on_click=on_click_stop)

ui.label('Temperature log')
log_area = ui.log(max_lines=200).classes('w-96 h-40 border')
timer = ui.timer(1.0, on_timer)
timer.deactivate()

ui.run()

NiceGUIはWidgetが揃っているので、パーツを選んできて貼り付けるだけで画面ができる。。楽だ*2。
今は測定データがダミーなので、次は、RP2350とUSB-Serialで接続して、RP2350から温度計測値を取得するようにする。
RP2350には温度センサが内蔵されているということで(Claude情報)、以下で温度測定(Geminiによるコード)

import time
import machine

sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)

def read_temperature():
    raw = sensor_temp.read_u16()
    voltage = raw * 3.3 / 65535
    temperature = 27.0 - (voltage - 0.715) / 0.00192
    return temperature

while True:
    print(f'{read_temperature():.2f}')
    time.sleep(1)

RP2350のハードウエア仕様書を確認していませんが、上記プログラムは動くには動く。それらしい値が表示される。今回はプロトなので、これで良し。起動時に測定値を連続的にシリアルに送ってほしいので、main.pyとして、上記コードを保存する。これで電源投入後は、温度を測定して、USB Serialに出力しつづける。
RP2350はCOM18に接続されている(USB シリアルデバイス(COM18))。これをWSLのシリアルとして見えるようにする必要がある。
PowerShellで以下を実行

PS C:\WINDOWS\system32> usbipd list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
2-1    2e8a:0005  USB シリアル デバイス (COM18)                                 Not shared
2-2    046d:c058  USB 入力デバイス                                              Not shared
2-5    1199:90b1  Sierra Wireless EM7431 Qualcomm® Snapdragon™ X16 LTE-A, S...  Not shared
2-7    5986:118f  USB FHD Camera, IR Camera, Camera DFU Device                  Not shared
2-8    06cb:00c6  Synaptics UWP WBDI                                            Not shared
2-10   8087:0033  インテル(R) ワイヤレス Bluetooth(R)                           Not shared

Persisted:
GUID                                                                           DEVICE
2a4f2781-19c5-4922-a1dd-e961068xxxxx  USB シリアル デバイス (COM14), USB JTAG debug unit
394be5e3-bae4-45a4-9a57-a160d4xxxxx  USB シリアル デバイス (COM20)
6b9e6ec4-1707-401f-8d5d-8ac0b2xxxxx  USB シリアル デバイス (COM18), USB JTAG/serial debug unit
820033e8-df76-408a-b5b9-8807c6xxxxx  USB-Enhanced-SERIAL CH9102 (COM19)
99da461d-cfbb-4945-89e7-6741fxxxxx  USB 大容量記憶装置, RP2350 Boot
b24984ee-275b-44bd-905e-387f22xxxxx  USB シリアル デバイス (COM17), USB JTAG/serial debug unit
c8df5152-439b-47bc-b8b6-de2c8axxxxx  USB シリアル デバイス (COM13), USB JTAG/serial debug unit

WSLのドライバ?更新が必要なのだった。WSLを更新してもまだ怒られ続けるのは、Linux側のドライバを更新する必要があるらしい。

PS C:\WINDOWS\system32> wsl --update
更新プログラムを確認しています。
Linux 用 Windows サブシステムをバージョン 2.7.13 に更新しています。
PS C:\WINDOWS\system32> wsl --shutdown
PS C:\WINDOWS\system32> usbipd attach --wsl --busid=2-1
usbipd: error: There is no WSL 2 distribution running; keep a command prompt to a WSL 2 distribution open to leave it running.
PS C:\WINDOWS\system32> usbipd attach --wsl --busid=2-1
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: error: WSL kernel is not USBIP capable; update with 'wsl --update'.
PS C:\WINDOWS\system32> wsl --update
更新プログラムを確認しています。
Linux 用 Windows サブシステムの最新バージョンは既にインストールされています。

WSL上のUbuntu内でモジュールが更新されている必要があり更新作業した。ただし、、WSL用にカスタマイズされている必要があったりで試行錯誤した。どれが有効に働いたのか分からず。とりあえず記録だけ

  241  apt-get --yes upgrade
  242  apt-get --update ; apt-get --yes upgrade
  243  apt upgrade
  244  sudo apt update
  245  sudo apt install linux-tools-generic hwdata
  246  sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20
  247  apt update
  248  apt install --yes ffmpeg
  249  apt update
  250  apt install linux-tools-virtual hwdata
  251  which usbip
  252  usbip version
  253  sudo apt install linux-tools-generic hwdata
  254  sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20
  255  usbip version
  256  apt get install linux-tools-standard-WSL2
  257  apt install linux-tools-standard-WSL2
  258  apt install linux-cloud-tools-standard-WSL2
  259  sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/*-generic/usbip 20
  260  apt list --installed | grep linux-tools
  261  ls /usr/lib/linux-tools/*-generic/usbip
  262  update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/6.8.0-139-generic/usbip 20
  263  usbip version
  264  mkdir -p /usr/lib/linux-tools/$(uname -r)
  265  cp -r /usr/lib/linux-tools/6.8.0-139-generic/* /usr/lib/linux-tools/$(uname -r)/
  266  usbip version
  267  history

WSL側は以下のようにバージョンが正しく表示されている状態である必要あり

root@ubuFV4:~# usbip version
usbip (usbip-utils 2.0)

まだ同じエラーが出たのでClaudeに聞くとWIndows側のドライバを更新しろと言ってきた

PS C:\WINDOWS\system32> usbipd --version
4.2.0+54.Branch.master.Sha.5b36605535dd52bc3d8a8e4bbaee7f4d480c86ad
PS C:\WINDOWS\system32> winget upgrade usbipd
見つかりました usbipd-win [dorssel.usbipd-win] バージョン 5.3.0
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
ダウンロード中 https://github.com/dorssel/usbipd-win/releases/download/v5.3.0/usbipd-win_5.3.0_x64.msi
xxxx                               4.29 MB / 4.29 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストールが完了しました
PS C:\WINDOWS\system32> usbipd attach --wsl --busid=2-1
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'mirrored'.
usbipd: info: Using IP address 127.0.0.1 to reach the host.
PS C:\WINDOWS\system32>

これでエラーなくWSL上のUbuntuにUSB Serialが接続されたと想像する。WSL上のUbuntuで確認

root@ubuFV4:~# ls /dev/ttyACM0
/dev/ttyACM0
root@ubuFV4:~# ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Sep  6 11:33 /dev/ttyACM0

多分大丈夫だろう。Permissionが気になるが。。以下のテストプログラムで温度が読めているのでOK

$ python3
Python 3.12.3 (main, Mar 23 2026, 19:04:32) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)
>>> line = ser.readline()
>>> print(line)
b'39.22\r\n'

Ubuntu上のビューアプログラムを改修して、シリアルから取得した計測値を表示するようにした。結果は以下。RP2350チップを冷やしてから室温に戻した結果

修正版プログラムは以下

from nicegui import ui
from datetime import datetime
import serial

# regist start time for drawing graph
start_time = datetime.now()

#
#  connection to RP2350(RPi Pico) via usb serial
#
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)

ui.label('Temperature Sensing DEMO').classes('text-2xl font-bold')
ui.label('Temperature graph')
temp_plot = ui.line_plot(n=1, limit=100, figsize=(6, 3), update_every=1) \
    .with_legend(['temp'], loc='upper right')

label_status = ui.label('status: none')

def on_click_start():
   label_status.set_text('Sensing started')
   timer.activate()

def on_click_stop():
   label_status.set_text('Sensing stopped')
   timer.deactivate()

def read_temperature():
    line = ser.readline()
    temp_str = line.decode().strip()
    return float(temp_str)

def on_timer():
    temp = read_temperature()
    timestamp = datetime.now()
    timestamp_iso = timestamp.isoformat(timespec='seconds')
    log_area.push(f'{timestamp} {temp:.2f} C')

    elapsed = (timestamp - start_time).total_seconds()
    temp_plot.push([elapsed], [[temp]])

with ui.row():
   ui.button('START', on_click=on_click_start)
   ui.button('STOP', on_click=on_click_stop)

ui.label('Temperature log')
log_area = ui.log(max_lines=200).classes('w-96 h-40 border')
timer = ui.timer(5.0, on_timer)
timer.deactivate()

ui.run()

まとめ
NiceGUIによるデータ表示は作りこめば高機能はUIが提供できる。その一方で、USB SerialをWSLに接続するところが手間かかる。(Windows環境でPython使うのに抵抗がなかったら、WSLは不要、USB Serialの苦労もなし)
MicroPythonによるセンシングの表示手段としてNiceGUIを推すのはちょっと問題と思った。自分の場合に当てはめると、WSL上でWebServer走らせるのは抵抗ないけど、ここまで手間かけてUSB Serialを接続して使うか?といわれると、面倒なので、何回もしたくない。

*1:熱中して作っていたHDMIディスプレイにグラフ表示する手もあるが、グラフ描画のプログラムを書くのが結構手間。静的に表示するだけなら何とかなるかもですが、リアルタイムに表示する場合、横方向のリサイズとか、描画データ範囲の決定とか、再描画とかいろいろ作る必要あり

*2:JavaScriptのGUIフレームワークでももちろんできると思うが、JSが苦手なので

mpremoteのモジュールを使ってRP2350上のMicroPythonを制御、画像描画

背景:QVGA + RGB565の解像度でどれぐらいきれいに描画できるのかを確認したい
取り組み:絵画データをQVGA + RGB565に変換してからの、、バイナリ変換が面倒なので、mpremote + RP2350 + HSTX/TMDS + framebufモジュールの組み合わせで描画する
結果:ゴッホとか原色が使われている絵画はかなりきれいに表示される。ただし、、PC上で走っているmpremoteからRP2350上のMicroPythonに対して一画素ずつ制御しているのでめちゃくちゃ遅い
詳細:

RP2350+HSTXによるイメージ描画のために、QVGA/RGB565にイメージ変換したバイナリデータをMicroPythonのFlashメモリに転送して、MicroPython側でイメージを読み込むべきだが、バイナリ変換が面倒。PCからREPLを自動的に制御する方法を考える。

MicroPythonをPCから制御するためのメンテナンスツール、mpremoteがあるが、実はモジュールとしてPythonから呼び出せるのであった。だから、USB-Serialで接続した後は、PC上のPythonからREPLにコマンドを送ることができる。mpremoteをモジュールとして呼び出してREPLに接続して、一画素ずつPCからコマンドを呼び出してみた。1画面表示するのにめちゃ時間がかかるが、一応表示された。使ったのは、ゴッホの夜のカフェ・テラス。下記は小型HDMI ディプレイに描画された状態を撮影。

HDMIモニタで「夜のカフェテラス(ゴッホ作)」を表示中
PCからRP2350上のREPLに接続して、framebufの描画関数、pixel()を呼び出すプログラム。PCから一画素ずつ描画コードを送って実行する。Claudeからも遅すぎて実用にならないとは言われたが*1。。

#
# control RP2350 via mpremote
#
from mpremote.transport_serial import SerialTransport
from mpremote.transport import TransportError, TransportExecError

TTY='/dev/ttyS12'

#  python3 -m mpremote connect /dev/ttyS12 fs ls

#
# send demo src and execute
#

transport = SerialTransport(TTY, baudrate=115200)
transport.enter_raw_repl()

PY_FILE='./src/dvi_color_320_240_16bit.py'
transport.execfile(PY_FILE)
transport.exec('fb.fill(0x0)')
#transport.exec('fb.pixel(160,120,0xffff)')


#
# send pixel data to RP2350
#

from PIL import Image

IMAGE_FILE='./img/CafeTerraceAtNight.jpg'


QVGA_WIDTH = 320
QVGA_HEIGHT = 240

SIZE_QVGA = (QVGA_WIDTH, QVGA_HEIGHT)
BG_COLOR_WHITE=(0, 0, 0)

def png_to_qvga_letterbox(file_path):
    img = Image.open(file_path).convert("RGB")
    img.thumbnail(SIZE_QVGA, Image.LANCZOS)  

    canvas = Image.new("RGB", SIZE_QVGA, BG_COLOR_WHITE)
    offset_x = (SIZE_QVGA[0] - img.width) // 2
    offset_y = (SIZE_QVGA[1] - img.height) // 2
    canvas.paste(img, (offset_x, offset_y))
    return canvas

img = png_to_qvga_letterbox(IMAGE_FILE)
pixels = img.getdata()

for y in range(QVGA_HEIGHT):
   for x in range(QVGA_WIDTH):
       r, g, b = pixels[QVGA_WIDTH * y + x]
       rgb565 = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
       transport.exec(f'fb.pixel({x}, {y}, {rgb565})')

#transport.exit_raw_repl()
#transport.close()

■追記
ここにきて落ち着いて考えると、、自分がやってることは、1000円以下で買えるSPI接続のLCDディプレイ(240x320)に表示することと変わらないのでは。。(何が見えるか?という最終結果だけを比べると)。。 DVI信号で出力するというのは技術的に違っているが、出てきたものは、QVGA RGB565であると。。。見える物は同じ。
何が違うのか?を改めて考える。。SPI接続のLCDディスプレイは安くて手軽ですぐ使える。だけど、、サイズが小さい、配線が手間*2、結構壊れる、、HDMIケーブルで接続できるDVI出力はTVとの接続が楽、マイコンだけ現地に持っていけばTVを借りて大きく表示できる。。これぐらいの違いか。本当に安定してプログラムが動くのか??はもう少し確認必要
外観はこんな感じ。

単に面白いというだけで作っていて、目的、用途、意義はあと付けなのであった(勉強会でデモに使うと喜んでもらえるだろうか。。「(こんな手間なことしなくても)Raspberry Pi Zeroを使えばHDMI出力できますよね?」とか言われそうだが。。)。

メモ

mkdir ~/projects/rp2350-sensor-gui
cd ~/projects/rp2350-sensor-gui
git init
python3 -m venv venv
source venv/bin/activate
pip install nicegui pyserial

*1:画像一ライン分をバイナリとして転送して描画しろといわれた。結構複雑なプログラムになる

*2:ブレッドボード上で配線がごちゃっとなる