mrubyc_arduinoのbuiltin symbolを削減

mrubyc_arduinoでコンパイルしたバイナリを眺めていたら、最後の方にいくつもの文字列が保存されていることに気が付いた。 それらはエラーメッセージやメソッド名に対応している。 メソッド名などは、内部ではsymbolとして取り扱われているが、それらを_autogen_builtin_symbol.hで取り込んでいる。 これらのbuiltin symbolをプログラムに組込むことによって、約6kほどのflash容量を消費している。 これを削減できれば、コンパイルサイズを小さくできるのでは無いかと思い付いて、試してみた。 他のクラスの多くは、c_*.cなどのファイルで定義されているが、 Symbolクラスについては、symbol.cの中で定義されている。 Symbolでは、文字列と内部で使う数値を対応させているが、 builtin symbolでは、その数値はMRBC_SYMID_*という定数として定義されており、 MRBC_SYM()というマクロで呼び出している。 その変換を行うために、symbolの文字列のデータがプログラム上に保存されている。 それ以外のSymbolでは数値はhash関数を用いて計算され、それがメモリ上に保存される。 そして、これらのSymbolは、method名を処理するために使われている。 マイコンでは、使うmethodの種類はそれほど多く無い場合がほとんどで、使うSymbolの数も少なくなり、使う可能性のあるbuiltin symbolをすべてflash上に保存するのは無駄にも思えるが、 メモリの使用量を減らすために、flash上にbuiltin symbolを保存しているようだ。 私がmruby/cで使おうとしているマイコンの多くは、メモリよりもflashが不足している。 そのため、flashの使用量を減らす工夫をいろいろとして来た。 その一つが、autogen_class.hで使わないmethodと対応する関数をコメントアウトして、これらのメソッドを消してしまう方法である。 これらのメソッドの名称もbuiltin symbolとして登録されているが、それらは消してしまって問題無いはずである。 そこで、autogen_class.hなどの中で登録されているmethodのみを_autogen_builtin_symbol.hに残すプログラムを作ってみた。 fld="/home/user/Arduino/libraries/mrubyc_arduino-main/src/" fl=Dir.entries(fld).grep(/^_autogen_class/) fl=fl.reject{|l|l=~/float/} fl<<"vm.c" sym=[] fl.each{|fn| d=open(fld+fn,"r"){|f|f.read} d=d.gsub(/\/\*.*?\*\//m,"") sym+=d.split(/\n/).grep(/MRBC_SYM\((.+?)\)/){$1} } sym=sym.uniq fo="_autogen_builtin_symbol." d=open(fo+"org","r"){|f|f.readlines} dd=sym.map{|e| d.index{|l|l=~/\/\/\s*MRBC_SYMID_#{e}\s*=/} }+ sym.map{|e| d.index{|l|l=~/^\s*MRBC_SYMID_#{e}\s*=/} } dd=dd.sort out=[] d.each_with_index{|l,i| out<<l if dd.include?(i) or not l=~/MRBC_SYMID_/ } i=0 out=out.map{|l| (l=~/^\s*MRBC_SYMID_/) ? l.sub(/=\s*\d+/){"= #{i+=1}"}: l } open(fo+"h","w"){|f| f.puts out} ユーザーのフォルダを示す~が使えなかったので、ユーザー名はuserとしました。 autogen_class.hの/ */のコメントを除去してから処理するようにしていますが、マクロのifや//のコメントには対応しておりません。 Floatは除去する前提なので、Floatのmethodは取り込んでいません。 元の_autogen_builtin_symbol.hを_autogen_builtin_symbol.orgという名前に変えて、スクリプトを実行すると、新たな_autogen_builtin_symbol.hが出来ます。
Read more...

ArduinoでCH32X035のUSBSerial

CH32X035をArduinoから使うときには、通常はWCHサポートを使うが、それだけではCH32X035のUSBSerialは使えない。 WCH社が公開している CH32X035EVT には、 MounRiver Studio用のプログラムの例がある。 これをArduinoで活用することも可能だろうが、どのようにして組み込むかを検証するのはそれなりに面倒であろう。

いろいろと探していたら、CH32X035_USBSerialというライブラリを発見した。 これは、Arduinoでスケッチ-ライブラリをインクルード-ライブラリを管理…-CH32X035_USBSerialを選択してインストールできる。 Arduinoのスケッチは、こんな感じである。

#include <CH32X035_USBSerial.h>
using namespace wch::usbcdc;

void setup() {
  USBSerial.begin();
  USBSerial.waitForPC(); // Wait for host connection
  USBSerial.println("USB CDC ready!");
}
void loop {
  if(USBSerial.available()){ USBSerial.read(); }
}

しかし、このライブラリはWCHサポートでは動かず、そのフォークを使う必要がある。 環境設定で以下のURLを加えて、それをインストールする。

https://raw.githubusercontent.com/jobitjoseph/CH32_Arduino_Core/main/board_manager/package_ch32_index.json

ボードはCH32 EVT boards supportからCH32X035を選ぶ。 オリジナルのWCHサポートではCH32V EVT boards supportとなっているので、“V"の有無で区別ができる。 少し調べたところでは、WCHのgithubのファイルと比較して、 system/CH32X035/SRC/Peripheral/src/ch32x035_misc.cと system/CH32X035/SRC/Startup/startup_ch32x035.S などを更新しているようである。 コンパイルして、バイナリを出力して、wchispで書き込むと、USBSerialが使えるようになる。

USBSerialを組み込んだときと組み込まないときで、コンパイルしたときのサイズを比較すると、3k弱の違いである。 以前、CH32V203でTinyUSBを組み込んでみたときには、10kぐらい増加したので、条件の違いはあるが、このライブラリはUSBSerialにしては、それなりにコンパクトだと言えるだろう。 以後、CH32X035でUSBSerialが必要な時には、このライブラリを使ってみようと思う。 このライブラリはCDCしか対応していないので、USBの他のデバイスを作ることは出来無いが、参考にはなるかも知れない。

Read more...

mruby/cでメソッドの制限

mrubyc_arduinoで、使用するflashを節約するためには、floatを無効にするとか、マルチタスク機能を削除するなど、いくつかの方法がある。 もう一つの方法は、使えるメソッドを減らすことである。

mruby/cではrubyのクラスやメソッドは、主にc言語で実装されているが、その一部はrubyで書かれたコードをmrbcでバイナリにして組み込むことによって実現している。 これがmrblibであり、そのバイナリのサイズは約4.5kである。 ch32v203でmrubyc_arduinoを使ったときには、mrblibを拡張flashに移動することによって、メインのflashを節約したが、これを組み込まないこともできる。 mrblibを組み込まなければ、必要なflashは約4.5kぐらい減る上に、mruby/cに必要なメモリの量も少なくなる。 以前、ESP8266で実験したときには、mrblibを組み込む場合にはmruby/c用に5kほどのメモリを確保しないといけなかったが、mrblibを組み込まない場合には2kでも動かすことができた。

しかし、mrblibを組み込まない場合には、そこで定義されていたメソッドが使えない。 mruby/cで使うことのできる クラス・ライブラリ の中で、下の表がmrblibで定義されているメソッドである。

Enumerable collect, map, each_with_index
Array all?, any?, collect!, map!, delete_if, each, each_index, index, find_index, none?, reject!, reject, reverse_each, select, filter, select!, filter!, sort!, sort
Hash each
Numeric times, upto, downto
Object loop
Range each
String each_byte, each_char, ljust, rjust, each_line
これらのメソッドの中で、個人的によく使うのは、map,each,times,loopなどだろうか。 mrblibを組み込ま無いことによって、これらは使えなくなるが、性能の限られたマイコンで使えないメソッドがあるのは仕方無いだろう。

一方、c言語で実装されているmethodを使わないようにするには、 autogen_class*.hのmethod_symbols_とmethod_functionsにある要素をコメントアウトすれば良い。 すると、コンパイル時の最適化でこれらは除かれるのである。 取り除いてはいけないメソッドもあるかも知れないが、ほとんど使わないけどコードが長くなりそうなメソッドを消せば、flashの節約になるだろう。

問題なのは、あまりメソッドを減らしすぎると、rubyっぽく無くなってしまうことである。 機能の限られたマイコンで動かすrubyとして、最低限必要なメソッドはどれかというのは、人によって意見が別れるだろう。

さらにflashの使用量を減らすためには、 マイコンには必要ないと思われるクラスを消すということも考えられる。 そのままではうまく働かないものの、 FloatやStringを無効にする指定はvm_config.hで定義されている。 Floatについては、2026/4/15のブログに書いてあるように修正すれば、無効にできるが、Stringは他のコードでも使われていることが多く、無効にするのは諦めている。 それと同様に、マイコンで使う必要性が低いクラスを無効にしてしまうことも出来るだろう。 例えば、Hashをマイコンから使う機会は少ないように思うが、SrtingやHashはmrblibにも定義が書かれているので、これらを無効にするのは単純には出来無いだろう。

2026/5/12追記 Hashはキーワード引数の処理に使われているので、消すことは出来無さそうだ。

Read more...

ArduinoでCH32X035のi2c

CH32X035はWCH社の比較的新しいマイコンで、安いのにflashやメモリもそれなりにあり、USBも使える。 このマイコン用にArduinoからI2Cを使おうとしたら、少し苦労したので、その解決法について書きたい。

ArduinoでCH32マイコンを使うには、WCHサポートをインストールする必要がある。 それを使うと、CH32X035も使えるようになるのだが、I2Cなどはまだ対応できていないようで、そのままではエラーが出て使うことが出来無かった。

WCHサポートの最新のリリースは2023年12月に出たもので、それ以降はリリースされていないものの、それ以降にも若干の更新が行われている。 いくつかのファイルを最新版に入れ替えると、CH32X035でもWireを使ったプログラムのコンパイルができることが分かった。 入れ替える必要のあるファイルは、 arduino_core_ch32/variants/CH32X035/CH32X035G8U/ のvariant_CH32X035G8U.hとPeripheralPins.c、 arduino_core_ch32/cores/arduino/ch32/ のPinNamesTypes.hとanalog.cppとanalog.hとtimer.cとtimer.h である。 これらで ~/.arduino15/packages/WCH/hardware/ch32v/1.0.4の 対応するファイルを上書きするのである。 動作は確認していないが、きっと動くと信じることにする。

Toneなども最新のリリースには無いので、同じところから最新版を取って来る必要があった。 もしかすると、すべてのファイルをgithub上の最新版に入れ替えた方が良いのかも知れない。 ch32x035については、まだusbをArduinoから使えていないので、その方法を探そうと思う。

Read more...

ESP8266用のmrubyc_arduino

mruby/cをESP32で使っているという記事はよく見掛けるが、ESP8266で使っているという情報はあまり見掛けない。 ESP8266には、プログラムを載せられるflash領域が1Mと、 システム用も合わせてメモリは96kあり、 mrubyc_arduinoを使うためのスペックを十分に備えている。 標準的な機能に加えて、wifiもmruby/cから使えるようになったので、 ESP8266をmrubyc_arduinoから使う方法をまとめておこうと思う。 mrubyc_arduinoのライブラリのインストールは2026/5/3のブログとほぼ同じだが、vm_config.hにはwifiも組み込む。 #include "mrbc_wifi.h" ArduinoでESP8266を使えるようにするには、 設定のURLに以下を追加して、ボードマネージャーからesp8266を検索してインストールする。 http://arduino.esp8266.com/stable/package_esp8266com_index.json 自分の使うボードを撰択して、メモリのオプションは 「16KB+48KB IRAM and 2nd Heap (shared)」とするのが、httpsにアクセスできるようにするコツである。 ESP8266は十分な大きさのflashがあるので、mrubyc_arduinoのカスタマイズは不要で、Floatも使える。 但し、バイトオーダで32binを有効にしなければならない。 #define MRBC_REQUIRE_32BIT_ALIGNMENT 私は試していないが、Mathなども組み込むことが出来るかも知れない。 Arduinoのスケッチは、以下のようにした。 #include <mrubyc.h> #define MEMORY_SIZE (1024*10) static uint8_t memory_pool[MEMORY_SIZE]; #define FLASH_CODE 0x40280000 //esp8266 int hal_write(int fd, const void *buf, int nbytes) { Serial.print((char*)buf); return (nbytes); } int hal_flush(int fd) { return 0; } unsigned char hal_read(int fd) { while (Serial.available() == 0); return Serial.read(); } void setup() { Serial.
Read more...

mrubyc_arduinoでESP8266からhttps

一週間と少し前にArduinoを使ってESP8266からhttpsにアクセスできることは確認できたが、その機能をmrubyc_arduinoに組み込むのに苦労していた。 Arduinoで動いたコードをmruby/cから呼び出せるようにして、プログラムは間違っていないように見えて、httpにはアクセスできるけど、httpsだとうまく行かないという症状になり、原因がなかなか分からなかった。 プログラムをいじったりしてもほとんど症状が変らずに、諦めかけていたが、httpsの処理にはメモリを沢山使うということを思い出して、メモリの設定をいじったらうまく行くようになった。 wifiはmruby/cの標準的な機能では無いので、どのようなクラスを定義すべきかから考える必要があり、 mrubyc-esp32-wifiやmrubyc-esp32などを参考にした。 ヘッダファイルmrbc_wifi.hは、代わり映えがしないが、以下のようにした。 #ifndef _MRBC_WIFI_H #define _MRBC_WIFI_H #include <Arduino.h> #ifdef __cplusplus extern "C" { #endif #include "mrubyc.h" void mrbc_init_class_wifi(void); #ifdef __cplusplus #endif #endif メインのmrbc_wifi.cppでは基本的なmethodを定義した。 #include "mrbc_wifi.h" #include <ESP8266WiFi.h> extern "C" { void c_wifi_connect(mrb_vm *vm, mrb_value *v, int argc){ if(argc>1) WiFi.begin( mrbc_string_cstr(&v[1]), mrbc_string_cstr(&v[2]) ); } void c_wifi_disconnect(mrb_vm *vm, mrb_value *v, int argc){ WiFi.disconnect(true); } void c_wifi_connected(mrb_vm *vm, mrb_value *v, int argc){ SET_BOOL_RETURN( WiFi.status() == WL_CONNECTED ); } void c_wifi_ip(mrb_vm *vm, mrb_value *v, int argc){ IPAddress ip=WiFi.
Read more...

ch32v203用のmrubyc_arduino

ch32v203には、公式なflashが64kと、さらに非公式で160kのflashが搭載されている。 mrubyc_arduinoに標準のAPIを組み込むと64kほどになるので、ch32v203はmrubyc_arduinoを使ってみるのに最低限の機能を有したマイコンの一つと言えるだろう。 ch32v203でmrubyc_arduinoを動かすための情報については、 これまでにこのブログにいろいろなことを書いて来たが、 その使い方をここにまとめておこうと思う。 まず、Arduinoでmrubycが使えるようにライブラリを追加する。 mrubyc_arduino をzipとしてdownloadして、「スケッチ-ライブラリをインクルード-.ZIP形式のライブラリをインストール」からインストールする。 そのライブラリに標準のAPIを追加するために、 以前紹介した私が作ったmrbc_*.*やoutputbuffer.cを ~/Arduino/libraries/mrubyc_arduino-main/src にコピーする。 また、これらを取り込むように、mrubyc.hに以下を追加する。 #include "mrbc_gpio.h" #include "mrbc_adc.h" #include "mrbc_pwm.h" #include "mrbc_i2c.h" #include "mrbc_spi.h" #include "mrbc_uart.h" #include "mrbc_get.h" ここで、ファイル名はmrbc_*に統一したので、過去のブログとはファイル名が若干異なっている場合があるので注意して欲しい。 ch32やESP8266では、バイトオーダのオプションを変更する必要があり、 vm_config.hの中の以下の行を、コメントアウトを外して有効にする。 #define MRBC_REQUIRE_32BIT_ALIGNMENT これで、mrubyc_arduinoの準備は完了である。 次に、Arduinoでch32を使えるようにパッケージを追加する。 設定のURLに以下を追加して、ボードマネージャーからch32を検索してWCHサポートをインストールする。 https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json WCHサボートのリリースにはToneなどが無いので、 最新版からTone.*とHardwareTimer.*を持って来て、~/.arduino15/packages/WCH/hardware/ch32v/1.0.4/cores/arduino/にコピーする。 これらのファイルを取り込むように、そのフォルダにあるwiring.hのHardwareTimer.hとTone.hのincludeをuncommentする。 Arduinoでは、ボードを撰択して、最適化のオプションはsmallest with LTOとしておく。 最後に、mrubyc_arudinoをch32v203用にカスタマイズする。 まず、そのままだと64kのflashに収まり切らないので、いくつかの機能を削って、工夫をする。 floatを消すために、vm_config.hのMRBC_USE_FLOATを0にして、2026/4/15のブログに書いたようにいくつかのファイルを修正する。 Taskも消すために、2026/4/20のブログに書いたようにrrt0.hとrrt0.cを修正して、_autogen_class_rrt0.hを削除する。 実行するタスクは一つだけになったので、vm_config.h中で指定されているMAX_VM_COUNTを1にする。 mrblibをメインのflashから消すために、mrblib.cを削除する。 これで、64kに収まるようになる。 Single Wire Debugを標準入出力にするために、2026/5/2のブログに書いたようにswd.hとswd.cを作って、Arduinoのスケッチと同じフォルダに置く。 Arduinoのスケッチは以下のようにした。 #include <mrubyc.h> #include "swd.h" #define MEMORY_SIZE (1024*10) #define MRBLIB_CODE 0x8010000 //ch32v203 #define FLASH_CODE 0x8012000 //ch32v203 extern const uint8_t mrblib_bytecode[] = { 0x52,0x49,0x54,0x45,0x30,0x33,0x30,0x30,0x00,0x00,0x00,0x41,0x4d,0x41,0x54,0x5a, 0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x25,0x30,0x33,0x30,0x30, 0x00,0x00,0x00,0x19,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05, 0x11,0x01,0x38,0x01,0x69,0x00,0x00,0x00,0x00,0x45,0x4e,0x44,0x00,0x00,0x00,0x00, 0x08,}; static uint8_t memory_pool[MEMORY_SIZE]; static volatile char inbytes=0; static volatile uint8_t last=' '; extern "
Read more...

ch32v203のSWD機能

mrubyc_arduinoでは、hal_writeに何らかの出力命令を定義しておくと、それが標準出力として取り扱われる。 標準出力には通常はSerialを使うことが多いが、SerialはUARTからも使えるので、標準出力は他の出力に割り当てることができる。 CH32マイコンでは、Single Wire Debug(SWD)機能があり、プログラムの書き込みもこの機能を使って行うことができるが、入出力としても使うことができる。 この機能をArduinoから扱うことができれば、これをmrubyc_arduinoの標準入出力に割り当てることが可能になる。 ch32v203について、SWD機能の使い方について調べてみた。 SWD機能については、ch32v203のリファレンスマニュアルにも使い方がほとんど書いてないので、その機能を使っているプログラムのソースから使い方を読み取るしか無い。 まず、Arduinoのpackageの中を調べてみたが、この機能についての記述は見付からなかった。 そこで、WCH社のプログラムを調べてみると、EVT/EXAM/SRC/Debug/に、この機能についての関数が定義されていることを発見した。 Arduinoでも同様のファイルは、packages/WCH/hardware/ch32v/1.0.4/system/CH32V20x/SRC/Debug/にあるのだが、こちらの方が古いファイルのようで、若干の違いがあり、その機能についての関数が無い。 新しい方のdebug.cには、アクセスするためのアドレスや、初期化と出力に対応する関数が、以下のように定義されている。 #define DEBUG_DATA0_ADDRESS ((volatile uint32_t*)0xE0000380) #define DEBUG_DATA1_ADDRESS ((volatile uint32_t*)0xE0000384) void SDI_Printf_Enable(void) int _write(int fd, char *buf, int size) これらをArduinoにうまく組み込めば、使えるようになりそうなことまでは分かった。 一方、このSWDのデータを表示するLinuxで使えるツールとしては、ch32funのminichlinkが便利である。 しかし、minichlinkと上記のdebug.cとは相性が悪いようだ。 そこで、ch32funで使われているSWDのコードを使うことにした。 そのためのヘッダとして、swd.hを作った。 #ifndef __CH32_SWD_H #define __CH32_SWD_H #include "stdio.h" #ifdef __cplusplus extern "C" { #endif #define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. #define DMDATA0 ((volatile uint32_t*)0xe0000380) #define DMDATA1 ((volatile uint32_t*)0xe0000384) void poll_input( void ); int _write(int fd, const char *buf, int size); void SetupDebugPrintf( void ); #ifdef __cplusplus } #endif #endif そして、このファイルをincludeして、 ch32fun.
Read more...

mrubyc_arduinoにUART

mruby/cの標準的なAPIで、mrubyc_arduinoにまだ組み込んでいないのは、UARTだけになっていた。 標準入力を使えるようにしたので、UARTの必要性が感じられなくて、なかなかやる気にならなかったが、ようやくUARTも作ってみた。 今回もC言語とC++とArduinoとrubyの仕様の違いに苦しめられたが、なんとか完成した。 まずmrbc_uart.hでは、getsのときの最大の文字数を定義した。 #ifndef _MRBC_UART_H #define _MRBC_UART_H #include <Arduino.h> #ifdef __cplusplus extern "C" { #endif #include "mrubyc.h" #define UART_GETS_MAX 256 void mrbc_init_class_uart(void); #ifdef __cplusplus } #endif #endif ArduinoではSerialも通常はC++で書かれているので、メインのコードのファイル名はmrbc_uart.cppとして、様々なメソッドを定義した。 unit番号に応じてSerialやSerial1などを何らかの変数に入れて、それを使ってコマンドを実行したかったが、C++のオブジェクトのポインタを使うと何が起こるか分からなかったので、まずはswitch-caseで分岐するようにして書いたので、冗長になってしまった。 その際、モードの設定のswitch-caseでbreakを忘れたために、パリティ付に設定されて二文字目以降が文字化けして、その原因を見付けるのに苦労した。 また、ArduinoではSerialのモードはSERIAL_8N1などで設定するのだが、この型がマイコンによって異なっていたので、それを格納する変数を定義するときに、decltypeを用いた。 getsはreadBytesUntilを使えば簡単に書けそうに思ったけど、はまってしまった。 ArduinoのreadBytesUntilではsizeを指定しないといけなくて、改行コードが取り除かれるという点が、rubyのgetsとは異なる。 一文字以上が入力されるのを待って、timeoutを指定して、readBytesUntilで読み取ることにしたらうまくいった。 しかし、やはり冗長なのが気に入らないので、なんとかクラスのポインタを使って、それをrubyのUARTオブジェクトに保存して、以下のように比較的短くすることができた。 #include "mrbc_uart.h" extern "C" { typedef struct UART_HANDLE { decltype(Serial) *unit_serial; } UART_HANDLE; void c_uart_setmode(mrbc_vm *vm, mrbc_value v[], int argc){ UART_HANDLE *handle = (UART_HANDLE *)v[0].instance->data; decltype(SERIAL_8N1) myUARTSettings=SERIAL_8N1; MRBC_KW_ARG( baudrate, baud, data_bits, stop_bits, parity, flow_control, txd_pin, rxd_pin, rts_pin, cts_pin ); int32_t baud_rate = 9600; int datb = 8; int stpb = 1; int prty = 0; if( MRBC_KW_ISVALID(baudrate) ) baud_rate = mrbc_integer(baudrate); if( MRBC_KW_ISVALID(baud) ) baud_rate = mrbc_integer(baud); if( MRBC_KW_ISVALID(data_bits) ) datb = mrbc_integer(data_bits); if( MRBC_KW_ISVALID(stop_bits) ) stpb = mrbc_integer(stop_bits); if( MRBC_KW_ISVALID(parity) ) prty = mrbc_integer(parity); switch(prty){ case 0: myUARTSettings=(stpb<2)?
Read more...

ESP8266でArduinoからhttpsにアクセス

ESP8266は十年ちょっと前に発売されたが、簡単にwifiにつなげるということで、私も十年前ぐらいから使い始めた。 その頃は、まだhttpが主流だったので、ArduinoIDEを使ってESP8266からhttpにアクセスするIoT機器などを作ったりしていた。 しばらくすると、ESP8266でmicropythonを使えるようになり、プログラムはpythonの方が楽なので、ESP8266はmicropythonから使うようになった。 その頃に、ESP32やmrubyの事を知って、ESP32は使ってみたが、mrubyは敷居が高い気がして使って来なかった。 昨年、久々にIoT機器を作る必要性が出て来たが、ほとんどのサイトはhttpsとなっていた。 始めはESP8266を使おうとしたけど、メモリ不足のためかmicropythonからはhttpsにアクセスすることは出来無かった。 結局、ESP32でmicropythonを使ってhttpsにアクセスして、IoT機器を作った。 ちなみにその後、アクセスしていたwebサーバが更新されたようで、通信が不安定になったので、原因を調べないといけないのだけれど、まだできていない。 しかし、ESP8266でhttpsにアクセスできないとなると、ESP8266を使う用途が非常に限定されてしまう。 最近、mruby/cをArduinoから扱うようになって、mruby/cやArduinoはmicropythonよりメモリの使用量が少ないはずだから、mrubyc_arduinoならESP8266でもhttpsにアクセスできるのでは無いかと思うようになった。 それを確かめる準備として、まずはArduinoからhttpsにアクセスする方法を試してみた。 少し調べてスケッチ例のESP8266WiFi-HTTPSRequestを見付けたが、これはあらかじめ証明書を準備しておく方法で、面倒な上に期限がある。 もう少し探すと、 6年前の記事 を見付けて、この方法なら証明書なども不要で、いつでもアクセスできそうだったので、これを元に試してみた。 Arduinoの宣言部分では、ライブラリを組み込んで、wifiやアクセスしたいサイトの情報を書いておく。 #include <ESP8266WiFi.h> #include <WiFiClientSecure.h> const char* ssid = "SSID"; const char* password = "PASSWORD"; const char* host = "host"; String url = "/index.html"; httpsを読み取ってファイルの内容を返す関数は以下のように定義した。 String https_get(String host, String url){ BearSSL::WiFiClientSecure client; client.setTimeout(500); client.setInsecure(); if (!client.connect(host.c_str(), 443)) { Serial.println("failed"); return "failed"; } client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "
Read more...