← UIAPduino WebHID Lab
All in Browser — Ruby Parser 同梱 Ruby × 電子工作

URB EE Lab

数百円のマイコンで始めるRuby電子工作。
コンポーネントを選んで .ino をダウンロード、 ブラウザでRubyをコンパイルしてEEPROMへ転送するだけ。
独自の TinyVM がバイトコード(.urb)を実行。インストール不要。クラウド不要。

Powered by Wakayama.rb — 和歌山発Rubyコミュニティ
⚠️ このページのデバイス接続機能は Chrome または Edge でのみ動作します。
WebHID API は Firefox・Safari では利用できません。Chrome / Edge で開き直してください。
(Ruby のコンパイルと .ino / .urb のダウンロードはこのブラウザでも利用できますが、デバイス接続・EEPROM 転送・HID コンソールは利用できません)
UIAPrubyとは? — はじめての方へ
数百円から始めるRuby電子工作

「Rubyで電子工作をやってみたい」——そう思っても、 高価なボード、複雑なセットアップ、専用ソフト… とハードルを感じていませんか?

UIAPruby は、そのハードルをぐっと下げます。
UIAPduino(290円、CH32V003ベース)に I2C EEPROM(24FC256 なら数十円)を合わせて、ハードウェアは数百円。 あとは手持ちのChrome/Edgeブラウザだけ。 普段書いているRubyの文法でLEDを光らせ、ブザーを鳴らし、センサーを読み、 電源を切っても消えない変数($count)やドット絵の配列まで扱えます。

マイコンで Ruby といえば mruby。でも mruby のビルドには Ruby と rake が必要で、 Arduino IDE だけでは完結しません。 URB Lab は、その rake の役割をブラウザに移しました。 コンポーネント(mruby の mrbgems に相当)を選ぶと、 必要な機能だけを組み込んだ単一の .ino が生成され、Arduino IDE でそのまま書き込めます。 PC に mruby のビルド環境(rake の構成やクロスコンパイラ)を整える必要はありません。

Rubyコードのコンパイルもブラウザの中——@ruby/prism でコードを解析し、 独自の軽量バイトコード(.urb)に変換。 WebHIDで EEPROM へ直接転送し、マイコン上のTinyVMが実行します。
インストール不要・クラウド不要。すべてブラウザの中で完結。

Rubyist が電子工作へ踏み出す入口を、 Wakayama.rb が作りました。mruby ボード GR-CITRUS に続く、二つ目の扉です。

✏️ Rubyコードを書く ⚙️ ブラウザ内コンパイル 📤 EEPROMへ転送 ▶ TinyVMが実行

⚡ クイックスタート(4ステップ)

  1. 1
    スケッチをダウンロードして書き込む(初回のみ)
    この下の「コンポーネント選択」で使いたい機能を選び、 UIAPrubyEeVm***.ino をダウンロード。 Arduino IDEでUIAPduinoに書き込みます。
    書き込み時は、UIAPduino のボタンを押しながら USB ケーブルを挿し、 ブートローダーを起動した状態にしてから書き込んでください。
    FQBN: UIAP_HID:ch32v:CH32V003:pnum=V14,usb=webhid,opt=oslto
  2. 2
    Rubyコードを書く
    エディタにRubyコードを入力します。サンプルボタンですぐ試せます。
    例:led = GPIO.new(2, GPIO::OUT) → D2ピンをLED出力に設定
    loop do led.toggle; sleep(0.5); end → 0.5秒ごとに点滅
  3. 3
    「コンパイル」ボタンを押す
    ブラウザ内でRubyコードをAST解析し、TinyVM用 .urb バイトコードへ変換します。
    ✓ OK と表示されれば生成完了です。
  4. 4
    EEPROM に送信 → RUN
    USBケーブルでUIAPduinoを接続し「📤 EEPROM に送信」をクリック。 未接続ならデバイス選択ダイアログが自動で開きます。転送後「▶ RUN」で実行開始。
    💡 EEPROM に書いたプログラムは、 電源投入から 5 秒後に自動実行されます(ファイル名の指定は不要です)。

🔧 必要なハードウェア

  • UIAPduino(CH32V003ベース)+ EEPROM 基板
  • I2C EEPROM: 24FC256(32KB)または CAT24M01WI(128KB)
  • USBケーブル(Micro-B または Type-C)
  • LED / タクトスイッチ / ブザーなど(実験用)

💻 必要なソフトウェア

  • Google Chrome または Microsoft Edge(最新版)
  • このページ — WebHID対応ブラウザのみ動作
  • ビルド済みファームを書き込む場合は、以下は要りません。
    このページの「ビルド済みファームを直接書き込む」から書き込めば、Arduino IDE もボードパッケージも不要です。
  • Arduino IDE(自分でビルドする場合のみ
  • UIAP_HID ボードパッケージ(自分でビルドする場合のみ
    v1.2.13 以降
    v1.2.13 で NeoPixelmin::getPixels() が入り、NeoPixel の回転・減光がこれを使います。
    ボードマネージャURL: https://raw.githubusercontent.com/tarosay/board_manager_files/main/package_uiap_hid_index.json
📌 ピン配置リファレンス
UIAPduino EE 版 対応ピン一覧(クリックで開く)
Arduinoピン番号 CH32V003ポート PWM ADC 用途・備考 UIAPruby記法
2PC0 LED出力(基板上LED) GPIO.new(2, GPIO::OUT)
3 / 4PC1 / PC2 ⚠ SDA / SCL — EEPROM 専用(占有)
5PC3 PWMブザー(圧電ブザー推奨) Tone.new(5)
6PC4 SD 版から解放 — GPIO / PWM / ADC(A2) ADC.new(6) / PWM.new(6)
7PC5 SD 版から解放 — GPIO GPIO.new(7, ...)
8PC6 NeoPixel DIN(Np 選択時は専用)。未選択時は GPIO NeoPixel.new(12)
9 / 10PC7 / PD0 HC-SR04 推奨(9=TRIG, 10=ECHO)。GPIO 可 Ultrasonic.new(9, 10)
11PD1 タクトスイッチ(PULL_UP使用) GPIO.new(11, GPIO::IN | GPIO::PULL_UP)
0, 1, 12PA1/PA2/PD2 アナログ入力(ADC対応ピン) ADC.new(0)
15 / 16PD5 / PD6 ADC(A5/A6) ⟷ Se 選択時は UART TX/RX 専用(排他) ADC.new(15) / Serial.new(9600)
3(SDA)・4(SCL) は EEPROM がバスを使い続けるため、GPIO には使用できません。
SD 版で塞がっていた 6・7・8・9 は EE 版で解放されました。8 は Np 選択時のみ NeoPixel 専用になります。
Se(UART)を選ぶと 15/16 が TX/RX になり、ADC は 0, 1, 6, 12 の 4 本になります。
EEPROM の配線(クリックで開く)— アドレス 0x50 / 0x52 の決め方

スレーブアドレスは 1010 A2 A1 A0 R/W で決まります。 A0 / A1 / A2 をすべて GND に落とす1010000 = 0x50A1 だけ 5V に上げる1010010 = 0x52 です。
24FC256 は 0x50 で使います。CAT24M01WI は 0x50/0x510x52/0x53 のどちらでも使えるので、上の「搭載する EEPROM」で選んだ側が ファームに焼き込まれます。24FC256 と CAT24M01WI を同じバスに載せるときは、 ぶつからないよう CAT24M01WI を 0x52 側にしてください。
CAT24M01WI がアドレスを 2 つ使うのは、128KB を 2 バンクに分けて 17 ビット目を スレーブアドレス側に入れているためです。

5V GND UIAPduino CH32V003 5V GND D3 / PC1 — SDA D4 / PC2 — SCL SDA / SCL のプルアップは UIAPduino 側にあります(外付け不要) I2C EEPROM 24FC256 / CAT24M01WI SDA (5) SCL (6) 0x50 / 0x52 A1 = GND → 0x50 / 5V → 0x52 VCC (8) VSS (4) A0 (1) / A2 (3) WP (7) A1 (2) は GND で 0x50、5V で 0x52(下の表)
EEPROM 側つなぎ先理由
SDA (5)UIAPduino ピン 3(PC1) ファームが固定で使う。GPIO には開放されない
SCL (6)UIAPduino ピン 4(PC2) 同上
VCC (8)5V EE 版は全て 5V 動作。SD が無くなり 3.3V 系が不要になった
VSS (4)GND
A0 (1)GND 24FC256 では A0。CAT24M01WI では NC(A16 に使われ外に出ていない)。 どちらも GND でよい
A1 (2)GND なら 0x50
5V なら 0x52
ここでアドレスが決まる。上の「搭載する EEPROM」で選んだ側と 合わせること。食い違うと起動時に「EEPROM 検出 FAIL」で止まる
A2 (3)GND 0x50 / 0x52 のどちらでも GND
WP (7)GND 24FC256 は未接続にできない(データシートに「VSS または VCC に 接続しなければならない」)。CAT24M01WI は内部プルダウンで 0
プルアップ抵抗は外付け不要です。 UIAPduino が SDA / SCL をプルアップしています。EEPROM は 4 本 (SDA・SCL・VCC・GND)と、GND に落とすアドレス/WP ピンだけで動きます。
ボードパッケージ同梱の I2C サンプル(Wiremin_EEPROM_24FC256 など)には 「4.7 kΩ を SDA/SCL から Vcc へ」と書かれていますが、あれは UIAPduino 以外の環境も含めた 一般的な説明です。Wiremin.h は PC1 / PC2 を AF オープンドレインに設定するだけで、 マイコン内部のプルアップは使っていません。
⚠ EE 版のファームは Wiremin_begin_fast() を呼び、400 kHz で動きます (5V 動作のため。決定 20)。
自作の基板や外部デバイスを長い配線でぶら下げる場合は、この速度で波形が保つかを見てください。
同じバスに他の I2C デバイスをつなぐとき — EEPROM が使うアドレスは避けてください。24FC256 は 0x50、 CAT24M01WI は選んだ側の 0x50 と 0x51、または 0x52 と 0x53 の 2 つを占有します(128KB を 2 バンクに分けて 17 ビット目がスレーブアドレス側に入るため)。
EE 版では I2C スレーブになれません。 自分のプログラムが EEPROM から読めなくなるため、コマンドごと持っていません。
コンポーネント選択

選択内容が下のエディタのサンプルと .ino ファイルに反映されます。

ビルド済みファームを直接書き込む

Arduino IDE でビルドしなくても、ビルド済みのものをブラウザから UIAPduino に書き込めば、そのまま UIAPruby が使えます。
選んだファームに入っているコンポーネントには自動でチェックが入ります。

BASE
GPIO / 制御フロー / Print
デジタル入出力・ループ・条件分岐・文字列出力
常時含む
EEPROM
搭載する EEPROM
スロットの大きさ(=配列の最大要素数)が変わります
Np
NeoPixel の LED 数
RAM は 1 個 3 バイト。多いほど show() 中に割り込みを止める時間が延びます(64 個で約 2ms)
Flash 使用量(CH32V003: 16384 bytes)
12,816 / 16,384 bytes (78%) — BASE のみ
サンプルコード — クリックすると下のエディタに読み込まれます(選んだコンポーネントに応じて増えます)
BASE
Ruby ソースエディタ
⏳ @ruby/prism WASM 読み込み中...

UIAPruby — Ruby構文を @ruby/prism でAST解析し、UIAPduino TinyVM用 URB1 バイトコードへ変換します。
UIAPduino 上では Ruby VM を実行しません。
.rb ファイルをエディタにドラッグ&ドロップするか、「開く」ボタンで読み込めます。

ライブラリ管理 (require / require_relative)
登録されたライブラリを require "name" または require_relative "name" で読み込めます。
コンパイル結果
— 未コンパイル
命令数
URB サイズ (bytes)
推定実行時間 (ms)
ダウンロード時のファイル名(デバイス側にファイル名は無く、常に自動実行)
URB ファイル操作
LED: D2 (PC0) / PWM Buzzer: D5 (PC3) / Button: D11 (PD1 PULL_UP) から試してください。
⚠ D3(SDA) D4(SCL) は EEPROM 専用です。D6/D7/D8/D9 は SD 版と違い使用できます(D8 は Np 選択時のみ NeoPixel 専用)。
💡 EEPROM に書いたプログラムは、UIAPduino に電源を入れるだけで自動実行されます(ファイル名は不要)。
自動実行が始まるのは、電源オンから 5 秒待ってからです。
USB 接続・RUN ボタン操作なしで単体動作するので、完成したスクリプトの運用に便利です。
EEPROM 変数ビューア
未接続 — 押すとデバイスを選べます
EEPROM の 6 スロットに保存されている $変数 の現在値を読み出します。読み取り専用で、値は変更しません。
型・要素数・永続属性は EEPROM 先頭の URB1 メタデータから、変数名と値は各スロットから取得します。
未接続のときは、このボタンでデバイス選択ダイアログが開き、接続してからそのまま読み出します。
配列は先頭 20 要素を表示します。「〇番目から全部読む」で末尾まで読み出せます(時間がかかるので途中で「中止」できます)。
「CSV で保存」は画面に出ている数値配列を、絶対添字で揃えて縦に並べて書き出します。開始位置や要素数が変数ごとに違っても、値の無いところは空欄になります。
プログラム実行中は読み出せません。先に「■ STOP」を押してください。
Device Log
未接続
UIAPrubyEeVm***.ino を書き込んだ UIAPduino + EEPROM 基板を USB 接続し、「デバイスに接続」を押してください。
HID Console
💻 UIAPruby print / puts / p / putc 出力
URB1 フォーマット

ファイルヘッダー(8 バイト)

オフセット
サイズ
内容
0x00
4 bytes
magic "URB1" (0x55 0x52 0x42 0x31)
0x04
1 byte
version = 1(変数なし) / 2(変数メタデータあり)
0x05
1 byte
flags = 0
0x06
uint16 LE
code_size (bytecode のバイト数)

変数メタデータ(version = 2 のみ、ヘッダー直後)

フィールド
サイズ
内容
var_count
1 byte
変数の個数(最大6)
type
1 byte
0=数値 1=文字 2=数値配列 3=文字配列。bit7=永続($var: 電源を切っても値を保持)
count
uint16 LE
要素数(数値/文字は1)
name
可変
変数名(null終端、最大16文字)。実行時は EEPROM スロット先頭 20 バイトに書かれ、$永続値の所属を決める

TinyVM 命令セット(リトルエンディアン)

Opcode
命令
引数
サイズ
0x00
END
1
0x01
WAIT_MS
uint16 ms
3
0x02
GPIO_MODE
uint8 pin, uint8 mode (0=IN 1=OUT 2=IN_PULLUP 3=IN_PULLDOWN)
3
0x03
GPIO_WRITE
uint8 pin, uint8 value
3
0x04
GPIO_READ
uint8 pin, uint8 reg
3
0x05
TONE_FREQ
uint8 pin, uint16 freq
4
0x06
JMP
int16 relative_offset
3
0x07
JZ
uint8 reg, int16 relative_offset
4
0x08
JNZ
uint8 reg, int16 relative_offset
4
0x09
GPIO_TOGGLE
uint8 pin
2
0x0A
LOAD_Q16
uint8 reg, int32 value
6
0x0B–0x0E
ADD/SUB/MUL/DIV_Q16
uint8 dst, uint8 src
3
0x0F–0x11
CMP_LT/GT/EQ_Q16
uint8 lhs, uint8 rhs, uint8 out_reg(>= <= != はコンパイラが補命令 + JNZ に変換)
4
0x12
WAIT_MS_REG
uint8 reg, uint16 mul — delay(mul) をレジスタ整数部の回数だけ繰り返す(変数の時間待ち)
4
0x15
LOAD_BOOL
uint8 reg, uint8 value
3
0x16
PRINT_STR
uint8 flags, uint8 len, byte[len] str (flags: 0x01=newline 0x02=inspect)
3+N
0x17
HALT
uint8 error_code
2
0x18
ADC_READ
uint8 pin, uint8 reg → 整数 0〜255(Q16.8 整数部)ピン: 0,1,6,12,15,16
3
0x19
PRINT_REG
uint8 flags, uint8 reg → Q16.8 を "n.nn" 形式で出力 (flags: 0x01=newline)。整数部は 0〜255(1 バイト)で、256 以上は折り返す(299 → 43.00)。それより大きい値は warn を使う
3
0x1A
ULTRASONIC_READ
uint8 trig, uint8 echo, uint8 reg → Q16.8 cm (0=タイムアウト) HC-SR04
4
0x1E
I2C_MASTER_INIT
—(バスは起動時に初期化済み。BASE に常駐)
1
0x1F
I2C_MASTER_GET
uint8 addr, uint8 reg, uint8 dst_reg(0x50〜0x53 は EEPROM が占有)
4
0x20
I2C_MASTER_SET
uint8 addr, uint8 reg, uint8 src_reg
4
0x21
RAND
uint8 min, uint8 max, uint8 dst_reg → Q16.8 整数 (min〜max-1) max=0 は 0〜255
4
0x22
SRAND
uint16_le seed — 乱数シード設定 (0 → 1 に補正)
3
0x23
PWM_DUTY
uint8 pin, uint8 duty (即値 0〜255)
3
0x24
PWM_BASE_FREQ
uint8 pin, uint16 freq — PWM 基準周波数 (PSC 設定)
4
0x25
VAR_LOAD
uint8 var_idx, uint8 reg — EEPROM 変数 → レジスタ
3
0x26
VAR_STORE
uint8 var_idx, uint8 reg — レジスタ → EEPROM 変数
3
0x27
VAR_LOAD_IDX
uint8 var_idx, uint8 idx_reg, uint8 reg — 配列要素 → レジスタ
4
0x28
VAR_STORE_IDX
uint8 var_idx, uint8 idx_reg, uint8 reg — レジスタ → 配列要素
4
0x29
TO_S
uint8 src_reg, uint8 var_idx — Q16.8 → 文字列変数(EEPROM)
3
0x2A
PWM_DUTY_REG
uint8 pin, uint8 reg — duty = レジスタ Q16.8 の整数部 (Q1 必須)
3
0x2B
VAR_STR_SET
uint8 var_idx, uint8 len, byte[len] — リテラル → 文字変数(Ec)
3+N
0x2C
VAR_STR_COPY
uint8 dst_idx, uint8 src_idx(Ec)
3
0x2D
VAR_STR_CAT
uint8 dst_idx, uint8 src_idx — 連結(Ec)
3
0x2E
VAR_STR_CAT_LIT
uint8 var_idx, uint8 len, byte[len] — リテラルを連結(Ec)
3+N
0x2F
VAR_PRINT
uint8 flags, uint8 var_idx — 文字変数 → HID コンソール(Ec)
3
0x30
VAR_STR_CMP
uint8 var_idx, uint8 out_reg, uint8 len, byte[len](Ec)
4+N
0x31
VAR_STR_CMP_V
uint8 a_idx, uint8 b_idx, uint8 out_reg(Ec)
4
0x32
WARN_REG
uint8 reg — レジスタ生値(Q16.8 下位24bit)を DEVICE LOG へ送信(warn デバッグ出力・文字列化はブラウザ側。EE 版は全構成で使用可)
2
0x33
SERIAL_BEGIN
uint32 LE baud(Se。TX=D15, RX=D16)
5
0x34
SERIAL_WRITE
uint8 即値(Se)
2
0x35
SERIAL_PRINT
uint8 flags, uint8 len, byte[len](Se。flags 0x01=CRLF)
3+N
0x36
SERIAL_AVAILABLE
uint8 dst_reg(Se)
2
0x37
SERIAL_READ
uint8 dst_reg — 1 バイトを Q16.8 整数として(Se)
2
0x38
SERIAL_WRITE_REG
uint8 reg — レジスタ整数部を送信(Se)
2
0x39
SERIAL_READ_LINE
uint8 var_idx, uint8 delim, uint16 timeout_ms — 1 行 → 文字変数(Se+Ec。STOP 応答あり)
5
0x3A
SERIAL_PRINT_REG
uint8 flags, uint8 reg(Se+Ec)
3
0x3B
SERIAL_PRINT_VAR
uint8 flags, uint8 var_idx(Se+Ec)
3
0x3C
NEO_BEGIN
uint8 count — LED 数を渡して初期化(Np。DIN=D8)
2
0x3D
NEO_SHOW
—(Np)
1
0x3E
NEO_BRIGHTNESS
uint8 0-255 — 非破壊(Np)
2
0x3F
NEO_SET_RGB
uint8 idx, r, g, b(Np)
5
0x40
NEO_FILL
uint8 start, count(0=最後まで), r, g, b(Np)
6
0x41
NEO_CLEAR
—(Np)
1
0x42
NEO_RAINBOW
uint8 offset 0-100 — 虹をバッファに作る(Np)
2
0x43
NEO_SHIFT
uint8 step 0〜(個数-1) — バッファを回す(Np)
2
0x44
NEO_DIM
uint8 scale — 残す割合 (scale+1)/256。破壊的(Np)
2
0x45
NEO_SET_HSV
uint8 idx, h, s, v(各 0-100)(Np)
5
0x46
NEO_AUTO
uint8 0=抑止 / 1=自動表示(Np)
2
0x47
EVERY_MS
uint8 slot, uint16 ms — 起点から ms 経つまで待ち、起点を「前回起点 + ms」に進める。既に過ぎていたら起点を現在時刻にして待たない(Tm)
4
0x48
TIMER_RESET
uint8 slot — 起点を現在時刻にする(Timer.newt.reset は同じ命令)(Tm)
2
0x49
TIMER_MS
uint8 slot, uint8 reg — 起点からの経過 ms を Q16.8 整数部で。起点は動かない。上限 89.4 秒(Tm)
3
0x4A
TIMER_US
uint8 slot, uint8 reg — 起点からの経過 µs を Q16.8 で。上限 8.38 秒を超えたら 0x7FFFFFFF で張り付き(Tm)
3
0x4B
NEO_SHIFT_REG
uint8 reg — 歩数をレジスタで。負も剰余も実行時に 0〜(個数-1) へ畳む(Nr)
2
0x4C
NEO_ORDER
uint8 並び(2bit×3)— 送る 1・2・3 番目に使う元の色。既定 0x24 = 入れ替えなし。以後の書き込みに効く(Nr)
2
JMP/JZ/JNZ の offset は命令直後位置からの相対バイトオフセット (int16)。
レジスタ R0–R3 は int32_t。Q16.8 固定小数: 1.0=256, 0.5=128。
MUL_Q16 は int32 乗算 — 積が ±32768 未満まで正確(2026-07-12 以前のファームは int16 制限で ±128 以上のオペランドが壊れるバグあり。要再書き込み)。
UIAPruby API リファレンス

GPIO / PWM / I2C / その他

Ruby 記法変換後命令Phase
led = GPIO.new(2, GPIO::OUT)GPIO_MODE pin=2 OUTPUT1
button = GPIO.new(11, GPIO::IN | GPIO::PULL_UP)GPIO_MODE pin=11 INPUT_PULLUP1
led.on / led.high / led.write(1)GPIO_WRITE pin, 11
led.off / led.low / led.write(0)GPIO_WRITE pin, 01
led.toggleGPIO_TOGGLE pin1
buzzer = Tone.new(5)GPIO_MODE pin=5 OUTPUT1
buzzer.frequency(440)TONE_FREQ pin, 4401
buzzer.off / buzzer.frequency(0)TONE_FREQ pin, 01
buzzer.tone(440, 0.2)TONE_FREQ 440 → WAIT_MS 200 → TONE_FREQ 01
button.low? / button.high?GPIO_READ pin, 空きレジスタ + JNZ/JZ2
sleep(0.2) / wait_ms(200)WAIT_MS 2001
wait_ms n * 100 / sleep(n) — 変数の時間待ちWAIT_MS_REG reg, 100(掛け算はファームウェア側)1
print / puts / p / putcPRINT_STR3
warn d / warn sonar.read — DEVICE LOG へデバッグ出力(Ec 不要・全構成で使用可)WARN_REG reg3
raise "msg" / raise unless condPRINT_STR + HALT4
def name … endインライン展開5
break / nextJMP loop_end / loop_start6
g = 0.1 * 0.5 / Q16.8 演算LOAD_Q16 + MUL_Q16 …7
if d < 15 — 比較演算(< > == >= <= !=)※Q1 必須CMP_LT/GT/EQ_Q16 + JZ/JNZQ1
case d / when 0, 10 — 値の列挙 ※Q1 必須CMP_EQ_Q16 + ジャンプ(OR 展開)Q1
when 0...15 / when 1..3 — レンジ ※Q1 必須CMP_LT/GT_Q16 ×2 + ジャンプ(範囲比較)Q1
f = ->(x) { x < 15 } — ラムダ式の定義コンパイル時登録(バイトコードなし)
f.call(d) / when f / when ->(x){…} — ラムダ呼び出し本体をインライン展開(下記参照)
require_relative "path"compile-time include8
motor = PWM.new(2)GPIO_MODE pin=2 OUTPUTPw
motor.frequency(500) — 基準周波数(省略時 1kHz)PWM_BASE_FREQ pin, 500Pw
motor.duty(255) — リテラル 0〜255PWM_DUTY pin, 255(即値)Pw
motor.duty(speed) — 変数 ※Q1 必須PWM_DUTY_REG pin, regPw
servo.angle(90) — リテラル 0〜180 ※要 frequency(50)(50Hz・0.5〜2.4ms、分解能約7°)PWM_DUTY pin, 19(コンパイル時計算)Pw
servo.angle(pos) — 変数 ※Q1 必須・要 frequency(50)Q16 演算 + PWM_DUTY_REG pin, regPw
sensor = ADC.new(0) ピン: 0,1,6,12,15,16(Se 選択時は 15/16 不可) (初期化なし)Ad
puts sensor.read / print sensor.readADC_READ pin,空きレジスタ + PRINT_REGAd
sonar = Ultrasonic.new(9, 10) 第1引数=TRIG, 第2引数=ECHO(空いている GPIO ピン。3/4 は EEPROM 専用で不可)GPIO_MODE trig OUT + GPIO_MODE echo INUs
puts sonar.read / print sonar.readULTRASONIC_READ trig,echo,空きレジスタ + PRINT_REGUs
$count = $count + 1$変数は EEPROM に永続保存 ※Q1 必須VAR_LOAD + ADD_Q16 + VAR_STOREEv
数値変数の3つ目以降(R0/R1 あふれ)— EEPROM に自動配置 ※Q1 必須VAR_LOAD / VAR_STOREEv
数値配列 arr = Array.new(10) / arr[i]$付きで永続) ※Q1 必須VAR_LOAD_IDX / VAR_STORE_IDXEv
puts $count / puts g — 数値出力 ※数値変数は Q1 必須(デバッグなら warn が Ev だけで使える)VAR_LOAD + PRINT_REG / PRINT_REGEc
I2C.master_init / v = I2C.master_get(0x10, 0) / I2C.master_set(0x10, 0, v) — 0x50〜0x53 は EEPROM が占有I2C_MASTER_*BASE
ser = Serial.new(9600) TX=15, RX=16(ADC の 15/16 と排他)SERIAL_BEGINSe
ser.write(65) / ser.write(b)(変数)SERIAL_WRITE / SERIAL_WRITE_REGSe
ser.print "x" / ser.puts "x"(puts は CRLF 付き)SERIAL_PRINTSe
if ser.available? / b = ser.readSERIAL_AVAILABLE / SERIAL_READSe
ser.print t / ser.puts line — 数値・文字変数の送信SERIAL_PRINT_REG / SERIAL_PRINT_VARSe+Ec
line = ser.gets(13, 1000) — 1 行受信(デリミタ, タイムアウトms。既定 10, 1000)SERIAL_READ_LINESe+Ec
np = NeoPixel.new(12) DIN=8 固定・個数は設定値までNEO_BEGINNp
np.set(0, 255, 0, 0) / np.hsv(0, 50, 100, 100) / np.fill(r,g,b) / np.clearNEO_SET_RGB / NEO_SET_HSV / NEO_FILL / NEO_CLEARNp
np.rainbow(20) / np.shift(1) / np.dim(20) / np.brightness(30) — 既定では 1 命令ごとに自動で showNEO_RAINBOW / NEO_SHIFT / NEO_DIM / NEO_BRIGHTNESSNp
np.auto = false — 自動 show を止める。以後は np.show だけが送る(np.auto = true で戻す)NEO_AUTONp
np.shift(step) — 歩数を数値変数で。負も剰余も実行時に畳む(要 Q1)NEO_SHIFT_REGNr
np.seen('B', 'G') — テープの色の並びを直す。「赤が B に、緑が G に見える」と答える形('R' / 'G' / 'B' のリテラルのみ)NEO_ORDERNr
n = rand(6) — 0〜5 の整数RAND 0,6,RnRn
n = rand(1..6) — 1〜6 の整数RAND 1,7,RnRn
srand(42) — シード設定SRAND 42Rn
every_ms 100 do … end — 絶対周期でループ。本体が何 ms かかっても周期は 100ms のまま本体 + EVERY_MS s0,100 + JMPTm
every_ms 100loop do の中に文として置く形。書き方が違うだけで同じ 1 命令EVERY_MS s0,100Tm
t = Timer.new — 起点をセット。every_ms の起点とは別物で、周期の境目で区切られることはないTIMER_RESET s1Tm
d = t.ms / u = t.us — 起点からの経過。読んでも起点は動かないので同じ区間を両方読めるTIMER_MS / TIMER_USTm
t.reset — 起点を今にし直す。区間を区切るのはこれTIMER_RESETTm
warn t.ms — 経過時間を DEVICE LOG へTIMER_MS + WARN_REGTm

ラムダ式(コンパイル時インライン展開)

TinyVM にクロージャは存在しません。ラムダ式はコンパイル時に呼び出し位置へインライン展開され、 展開結果は通常の比較・演算命令になります(実行時オーバーヘッドなし・追加 Flash なし)。
使い方説明必要
near = ->(x) { x < 15 }定義。本体は式1つだけ。バイトコードは出力されない
case d
when near / when ->(x) { x < 15 }
case 対象 d が引数 x に渡り、本体が条件として展開されるQ1
if between.call(d, 5, 10)if / while / until / unless / 三項演算子の条件で使用可。複数引数・&& / || も OKQ1
y = double.call(n)数値式として使用(戻り値 = 本体の式の値)Q1
wait_ms half.call(500)引数がすべて定数ならコンパイル時に計算され、リテラルを書ける場所(sleep / servo.angle 等)ならどこでも使える
制約: 本体は式1つのみ(複文は不可)/引数は数値リテラル(定数式)または変数のみ/ 再帰呼び出し不可/デフォルト値・可変長・キーワード引数は不可。いずれもコンパイルエラーで案内されます。