UIAPduinoをch32funで使う方法
UIAPduinoの開発環境として,初心者にとって最も簡単なのはおそらくArduino IDEである. 新しい種類のマイコンを使うたびに,そのマイコンの仕様を勉強するのは大変だが, arduinoは,マイコンの種類をあまり意識せずに使えるという点で,優れていると思う. UIAPduinoのArduino環境は,WCH社のArduino環境を用いており,少い重いという欠点がある. また,USBを使ったプログラムを作ることができない.
もう一つのUIAPduinoの開発環境が,ch32funであり,軽くて機能も充実しているが, ch32funでプログラムを組むには,CH32V003について多少の知識が必要となる. 実は,UIAPduinoのUSBによる書き込みは,ch32funのrv003usbを使ってソフト的に実現している. 同様に,ch32funでrv003usbを使うと,USBを利用するようなプログラムも作ることができる. ちなみに,PlatformIOでは,ch32funを使うことができるらしいが,私は使ったことが無い.
ch32funでUIAPduinoを使うには, UIAPduinoのbootloaderは,ch32funのbootloaderとProductIDが異なるので,minichlinkでの書き込み時のコマンドにオプションを指定する必要がある. そこで,ch32fun/ch32fun.mkの中の
FLASH_COMMAND?=$(MINICHLINK)/minichlink -w $< $(WRITE_SECTION) -b
という行を,
FLASH_COMMAND?=$(MINICHLINK)/minichlink -c 0x1209b803 -w $< $(WRITE_SECTION) -b
に変更する. すると,普通のch32funと同様にUIAPduinoを使うことができる. minichlinkをUIAPduinoのものと入れ替えても良いのだが.
ch32funでUIAPduinoを使うもう一つの方法を紹介しておこう. AlexanderManderaさんの環境は,arduino IDEからch32funを使えるようにしたものなので,これを使うと,Arduino IDEからch32funを通して,UIAPduinoを使うことができる. Arduino IDEでファイル-環境設定として,追加のボードマネージャのURLに
https://alexandermandera.github.io/arduino-wch32v003/package_ch32v003_index.json
を入れて, ツール-ボード-ボードマネージャで"ch32"などと検索すると,“WCH Boards"が出てくるので,インストールするとこの環境が使えるようになる. そして,UIAPduinoを使えるように,以下のようにして書き込みソフトをUIAPduinoのもので上書きする.
cp ~/.arduino15/packages/UIAP/tools/minichlink-2982dfd/1.0.0/minichlink ~/.arduino15/packages/alexandermandera/tools/minichlink/1.0.0/
この環境を UIAPduinoの環境と比較をしてみよう. ファイル-スケッチ例-01.Basics-Blinkの例に,
#define LED_BUILTIN 2
を加えてUIAPduinoでコンパイルすると,6972バイトとなる. スケッチ-コンパイルしたバイナリを出力としてできるbinファイルのサイズは7140バイトである. ツール-ボード-WCH Boards-CH32V003として,環境を変えた場合のbinファイルは1640バイトである. ファイルサイズは四分の一となり,プログラムがかなりコンパクトになってることが分かる. ch32funがベースになっているので,うまく設定すればrv003usbも使えるかも知れない. このように,UIAPduinoの環境よりも,こちらの方が良いようにも思えるが,必ずしもそうとは言えない. この環境では,digital IOとSerialはarduinoと同じように使えて,i2cは少し違う形式で使うことができるが,analog IOなどはまだ使えない. また, ch32funも古いものを使っており, しばらく更新が止っているので,進展はあまり望めないように思われる. digital IOとSerialしか使わなくて良い場合を除いて,UIAPduinoの環境を使っておくのが良いのでは無いだろうか. なお上の例で,ピン番号の代わりにPC0などを使う場合には,C0としなければならないことに注意しないといけない.
UIAPduinoを試してみた
picoRuby
ESP32を使うときには,私は主にmicropythonを使っていた. C言語よりはpythonの方が楽なので. micropythonでは,binaryを書き込んだら,pythonのコードをマイコンが実行してくれる.
esp32ではmrubyというrubyを使うことも出来るが,rubyのコードをPC側でコンパイルしてマイコンに書き込む必要がある. 手順も複雑なので,素人向では無いと感じて,手を出さなかった. mrubyも進化しているようで,mruby/cという小さなRAMで動かせるものも開発されているが,大まかな使い方はmrubyと同じようである.
mruby/cについて調べていたら,picoRubyというものもあることを知った. microの次はnanoなのに,それを飛ばしてpicoになったのは何故かなと思ったら,raspberry pi pico用に開発されたものだからのようだ. 使い方はmrubyと似ているのかなと予想したが,micropythonと同じように使うことができる. それなら使ってみようかなということで,試してみることにした.
raspberry pi picoが必要だが,手元にあるRP2040-zeroを使うことにした. まず,binaryをここから最新のものをdownloadして,展開する. pico用とpico2用があるが,今回は前者に対応しているのでそれを選ぶ. daily buildなどは無いようなので,最新のコードのbinaryが必要な場合は,自分でbuildしないといけない. BOOTを押しながらUSBに接続すると,RPI-RP2というmediaがマウントされるので,そこにuf2ファイルをコピーする. インストールはこれで終了である.
しばらく待ってからRESETを押すと,/dev/ttyACM0が出来ているので,ターミナルソフトで接続する. linuxだと,例えば以下のコマンドである.
gtkterm -p /dev/ttyACM0 -s 115200
lsなどの簡単なコマンドや,rubyを使うためのirbが使える. まずは簡単な計算をやってみて,micropythonと同じ感覚で使えることを感じた. Lチカをしようと思ったけど,RP2040のLEDは簡単では無いようなので,電圧のON/OFFをやってみた.
pin = GPIO.new(1, GPIO::OUT)
10.times{pin.write(1);sleep 1;pin.write(0);sleep 1}
esp32用のpicorubyもあるけど,binaryが無かったので,今回は見送った. binaryも公開して貰えると,素人でも始めやすくなって,使う人が増えると思うので,公開してくれると助かるけどな. しかし,esp32用のpicorubyは,netには対応していないようである. esp32のwifiが使えるようになったら,micropythonの代わりにpicorubyを使って行きたい. 開発が進むのを待つことにしよう.
WeActStudioのCH32V003開発ボード
WCH社のCH32V003というマイコンを時々使うようになった. 当初は,ArduinoにWCHサポートをインストールして使っていたが,ソフトで実装したUSBを使うことができるch32funを使うようになった. 特にUSB用のbootloaderを書き込むと,以降はWCHLinkを使わずにUSBから書き込みが出来て便利である. しかし,マイコンそのものを使ってUSBを使えるようにするには,USBを繋げるようにしたり,3.3Vを作ったり,33Ωと1.5kΩの抵抗を接続したりしないといけないので,それなりの手間がかかる. そこで,CH32V003を使ったマイコン開発ボードを試してみることにした. いくつかの開発ボードが作られているようだが,小型で手に入りやすいという理由から,WeActStudioのものを使ってみることにした.
WeActStudioからは様々なボードが発表されており,それらはAliexpressから入手できる. 今回はCH32V003F4U6 Mini Core Boardを選んで, USBは通常は電源の供給のみであるが,回路図を確認すると,少し改造するとUSB通信が出来るように設計されていることが解る. 基板のUSBと書いてあるところの近くに三つの空きのランドがあるが,USBという文字に近い方の二つには33Ω,残りの一つに1.5kΩのチップ抵抗を半田付する. そして,ch32funのrv003usbでは,以下のように設定する.
#define USB_PORT D #define USB_PIN_DP 3 #define USB_PIN_DM 4 #define USB_PIN_DPU 5
WCHLinkをつなぐための端子もあるので,それを使ってプログラムすることができ, rv003usbのbootloaderを使う場合にも,最初はそれを使って書き込む. 空きのランドの形が,半田で繋いで短絡しやすいようになっていたので,最初は短絡して試したがうまくいかず,回路を追い掛けたら抵抗が内蔵されていないので,それを半田付する必要があることに気が付いた.
PD5がUSBのDPUに使われてしまうために,USBを利用するときには,使えるピンの数は3つ減ってしまう. DMを3.3Vに直結すれば,PD5を開放できるのだが,それはこのボードでは簡単には実現出来無い. また,PD7がNRSTとして使われているために,スイッチとコンデンサに接続されており,これらを切り離してPD7を独立した入力ピンとして使えないのも残念なところである. そのため,実質的に使えるピンの数は,14である.
WeActStudioのCH32V003開発ボードでUSBを使うためには,二種類のチップ抵抗を用意して,それらの三つを半田付するというのが,少し面倒だが,ICから準備するよりはかなり楽になる. CH32V003を使ってUSBが扱えるマイコンボードであるUIAPduinoは,安価な上に半田付なども無しでUSBからプログラムを書き込めるようなので,このマイコンでUSBを使おうとしている人は,このボードの方が良いかも知れない. 入手経路が限られているために,これまで使ったことは無いのですが.
arduino nanoのVin
ステッピングモーターをマイコンで動かそうとして,どのマイコンを使うか迷ったが,小型のarduino nanoを使うことにした. モーターのドライバーには,GNDと信号と電源を供給する必要があるが,ピンの順番の関係で,RSTの配線をカッターで切断して,そこに電源をつなぐことにした. Vinという端子があったので,それがUSBから電源として入力された信号を出す端子だろうと思って,それを電源として使ったら,モーターのトルクが非常に小さくなってしまった. 電圧を測ると,2Vぐらいしか出ていない. 調べてみると,Vinという端子は,そこに外部電源をつなぐための端子であることが分かった. つまり,arduino unoでは,ACアダプターをつなぐ端子があるが,その代わりに使う端子のようだ. 結局,5VがUSBの電源に対応するようなので,それを使ったら無事に動いた.
こういった単純な作業に使うマイコンボードとしては,小型で安いnanoが楽かなと思う. 小型のマイコンボードとしては,arduino pro microやesp8266ボードやesp32ボードに加えて,ch552ボードなどを使って来た. UIAPduinoなんかも安くて良さそうだけど.
localhostと127.0.1.1
127.0.0.1は自分自身を表すIPだが,debianでマシン名に対応するIPは127.0.1.1となっている. つまり,自分自身には,127.0.0.1と127.0.1.1と割り当てられているIPが対応している. サーバーを立てているPCから,そのサーバーにアクセスしたときには,上記のどのIPを使うかによって,サーバーから見た接続先が異なっている.
例えば,rubyでserve側で
require "socket" s=TCPServer.new(3030) p s.accept.peeraddr
としてから,client側で
require "socket"
s=TCPSocket.open('localhost',3030)
とすると,serve側には
["AF_INET", 37666, "127.0.0.1", "127.0.0.1"]
などと表示される. 一方,localhostの代わりに,割り当てられたIPを指定すると,割り当てられたIPが表示される.
今回苦しんだのが,127.0.1.1にアクセスした場合の振る舞いである. 私の2009/1/16のブログを見るとその時のrubyでは,127.0.1.1と表示されたようである. しかし,最近のrubyでは,127.0.0.1と表示されるように変わったようである. 昔書いたプログラムを新しいPCで動かそうとして,なかなか思ったように動かなかったが,これが原因だったようである.
Python-FuでGimpのFilter
Gimpで画像を処理させるときに,以前はScript-Fuを使っていてscheme言語で書くのが難しかったが,最近はPython-Fuを使えるようになって,楽になった. ちなみに私がpythonを使うのは,micropythonかPython-Fuが主な気がする. 少しは慣れて来たのだが,Filterなどの高度な処理をPython-Fuから行う方法が分からなかった. Gimp3.0になったし,新たに調べてみたら,やり方が分かったので,書いておきたい.
まず,画像の一部を選択した状態にする. Filters - Development - Python-Fu - Python Consoleからコンソールを開いて,以下のコマンドを実行すると,medianフィルターが適用される.
img=Gimp.get_images()[0]
lyr=Gimp.Image.get_layers(img)
chl=Gimp.Selection.save(img) #unselect layer
Gimp.Image.set_selected_layers(img,lyr)
drw=Gimp.Image.get_selected_drawables(img)[0]
flt = Gimp.DrawableFilter.new(drw, "gegl:median-blur", "")
fc = flt.get_config()
fc.set_property("radius", 10)
drw.append_filter(flt)
filterやそのpropertyの名前は,GEGLのサイトで調べることができる. get_configで作ったものに対してset_propertyをするという少し回りくどい設定をしてから,適用する. append_filterでは元の画像を保持したままfilterが非破壊に適用されますが,元の画像を保持する必要が無いときにはmerge_filterを使って下さい.