ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
UIAPduino(CH32V003)をブラウザから動かすデモ・練習ページ集。WebHID でのキーボード・マウス練習、アルゴリズム練習ゲーム、Ruby やブロックで動かす環境、Arduino IDE のセットアップ手順まで。
Translation pending
EducationGitHub @tarosayOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
UIAPduino をブラウザから動かすページ集。ブロック・Ruby・C++ のどれでも書けて、WebHID でつながります。インストール不要。
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗UIAPduino(HID ProMicro CH32V003)をブラウザから動かすページ集です。 インストールもアカウントも要りません。Chrome か Edge で開くだけです。
🌐 サイト URL: https://tarosay.github.io/uiap-hid-web/
ブロックで動かす方法はもう一つあって、トップページから Xcratch + UIAPduino にも行けます(リポジトリ)。
ブラウザとマイコンは WebHID API でドライバなしに直接やり取りします。 GitHub Pages で公開しているので、インストールは要りません。
| ページ | スケッチ例 | 状態 |
|---|---|---|
| HID Console | HidPrint.ino | ✅ 公開中 |
| HID-Serial Bridge | HidMonitorTest.ino / HidBridgeTest.ino | ✅ 公開中 |
| HID 接続チェック | スケッチ不要 | ✅ 公開中 |
| ページ | スケッチ例 | 状態 |
|---|---|---|
| SD Filemanager | WebHID_SD.ino | ✅ 公開中 |
| MIDI → MIDB Converter | MidbPlayer.ino | ✅ 公開中 |
| ページ | スケッチ例 | 状態 |
|---|---|---|
| URB Lab | ブラウザ内で生成(コンポーネント選択式) | ✅ 公開中 |
| URB EE Lab | ブラウザ内で生成/ビルド済みファームを直接書き込み | ✅ 公開中(24FC256 / CAT24M01WI で実機確認済み) |
| URB Block Lab | 同梱ファーム 1 本(⚙ 準備 から書き込み) | ✅ 公開中(CAT24M01WI / 24FC256 で実機確認済み) |
Wakayama.rb コミュニティが開発した、Ruby 構文で UIAPduino を制御できる組み込み Ruby 環境です。 mruby のビルドでは rake が必要な mrbgems の取捨選択と統合を、URB Lab はすべてブラウザ内で行います。 PC に Ruby・クロスコンパイラ等のビルド環境を整える必要はありません。
.urb)にコンパイルmain.urb という名前で SD に保存すると、電源投入時に自動実行Tm(絶対周期) — every_ms 100 do … end は「前回から 100ms」ではなく
開始からの絶対時刻で起こすので、何周回しても周期がずれません。Timer で
区間の実測(ms / µs)もできます。SD 版・EE 版の両方で使えますURB EE Lab は、SD カードの代わりに
I2C EEPROM(24FC256 32KB / CAT24M01WI 128KB)にプログラムと $変数 を保存する版です。
CAT24M01WI は A1 の配線でスレーブアドレスを 0x50/0x51 と 0x52/0x53 のどちらにもできます
(24FC256 と同じバスに載せるときは 0x52 側)。
SD カードを使わないぶん SPI が丸ごと空き、その上に載る機能が増えます。
UIAPrubyVm 12,504 B → UIAPrubyEeVm 9,144 B)。
コンポーネントに使える余地が約 1.9 倍になり、Q1 + Se + Np + Ec が同時に載るNp / Nr(NeoPixel) — SPI1 が空いたことで初めて可能になった。DIN はピン 8 固定Se(UART) — GPS 受信やマイコン間通信に使える。ピン 15/16Ev / Ec(EEPROM 変数) — SD 版の Ve / Sv に相当。ファイル操作が
アドレス計算 1 回になり、数値変数は約半分(+1,512 B → +820 B)$変数 の現在値を読み出せる(読み取り専用)。画面に出ている数値配列を CSV で保存できる(添字で揃えて縦に並べる)。
配列の「全部読む」は、途中で読み込みエラーが出ても読めた要素を残して止まった要素から読み直す。
同じ位置で 10 回続けて失敗したら止まり、もう一度押すと続きから読み足すコンポーネントを選んで .ino を生成し Arduino IDE で書き込む道に加えて、
ビルド済みのファームをブラウザから流し込む道を用意しました。
rv003usb ブートローダ(1209:B803)へ WebHID で書き込みます。
| 選ぶもの | 中身 |
|---|---|
| サーボ版(既定) | Pw + Q1 Ad Se Np Us Rn Ec |
| ブザー版 | Tn + Q1 Ad Se Np Us Rn Ec |
| 自分で選ぶ | 従来どおり。コンポーネントを選んで .ino をビルド |
Tn(ブザー)と Pw(サーボ)は同じタイマーの分周器を共有するため同時に選べません。
選ぶのは「ブザーか、サーボか」だけで、ほかは全部入りです。
ファームはページに base64 で埋め込んであり、焼く前に**生成される .ino の SHA-256 を
その場で計算して突き合わせます。**食い違えば書き込まずに止まるので、
「ページだけ新しくてファームが古い」状態で焼くことがありません。
✅ 24FC256(32KB)と CAT24M01WI(128KB)の両方で実機確認済みです (プログラム転送・自動実行・
$変数と配列の読み出し・ブラウザからのファーム書き込み・NeoPixel の動作)。 CAT24M01WI は 64KB 境界(0x10000)をまたぐ読み書きも確認しました。 ピン 6 の ADC / PWM も確認しました(PWM は URB Block Lab の基板で)。 電源を切ってからの永続と、Seのマイコン間通信はこれからです。
✅ CAT24M01WI(0x50/0x51)を載せた基板で実機確認済みです。 同じロットの 2 枚で、ギャラリーの「LED 点滅」「ボタンで LED ON」を書き込んで動くことを確かめました。 ✅ 24FC256(0x50)でも実機確認済みです(ブレッドボード。変数 7 個・記録・配列の読み書き・ 配列の上限 5,410 個・大きすぎる配列と範囲外の番号のエラー)。 24FC512 は見分ける仕組みだけ入れてあり、石が手元に無いので未確認です。
URB Block Lab は、 ブロックを組むと Ruby が出てきて、それが基板の中に入るページです。子ども向けの入口として作りました。
Scratch や Smalruby との最大の違いは、プログラムが PC ではなく基板の中で動くことです。 書き込んでしまえば USB を抜いてよく、電源さえあればそのまま動き続けます (micro:bit の「ダウンロード」・PicoRuby / Arduino の「書き込み」と同じ考え方)。 だからボタンの名前も「動かす」ではなく 「基板に書き込む」 にしてあります。
docs/lib/urb/compiler.js と docs/lib/urb/eeprom.js を両ページで共有)rand で決めた数を入れれば、動くたびに違う角度へ振れます。
ただし「サーボの設定」で決めた幅は効きません(angle は 50Hz・500〜2400µs 固定)。
両方を置いたときは、Ruby の先頭に警告コメントが出ます0x48)でも
10 進でも書けます。値は 0〜255 の普通の数として扱えるよう、読んだあとに ×256、
書く前に ÷256 を生成側で入れています(VM では I2C の値だけ Q16.8 ではなく生のバイトで
出入りするため)。0x50〜0x53 は基板の EEPROM が使っているので、指すと警告コメントが出ますWiremin 自体は n バイトの読み書きも
レジスタ番号なしの送受信も持っていますが、VM に命令が出ていません。そのため対象になるのは
LM75 / TMP102 の温度(MSB がそのまま ℃)、MPU-6050 の加速度・角速度(上位バイト)、
PCA9685 のような書くだけの部品です(x, y) → テープの番号は、x が偶数なら x*8 + (7 - y)、奇数なら x*8 + y)。
出る Ruby は「うしろの色で fill → えがいたマスだけ set」なので、
命令は 6 + 5 × えがいた数 バイトで済みます(全部えがいても 331 B)。
1 マスごとに show が走って絵が描かれていく様子が見えないよう、
np.auto = false で止めてから最後に 1 回だけ送ります。
このブロックを置くと LED は 64 個として組み立てます(「NeoPixel を ◯ 個使う」で
それより少なく指定していたときは、Ruby の先頭に警告コメントが出ます)0〜7 を 64 文字)。色そのものはブロックに並んだ 8 つの色えらび(いろ)が持つので、
描いたあとに色を変えると絵の色も変わります。面を開くと、マスの右に大きな色の見本が
2 列 × 4 段で出るので、えらんでからマスを押します。
真っ白から描きはじめます。 0 番の色(既定は白)が何も描いていないところの色で、LED も白く光ります。
「絵を消してはじめから」(前の「全部消す」)は、絵を消して真っ白にし、ずらしも戻すボタンです。
色(本体の「いろ」と、えらんでいる色)はそのまま残します(同じ色で描きなおせるように)。
8 番目の色は 「けす」(既定は明るさ 0=光らない)で、
黒ではなく ✕ の見た目にしてあります(LED では黒は出ないので)。明るさ 0 の色は、どの番号でも
この見た目になります。面を開いている間は、ブロック本体の「いろ」とボタンは薄くなって押せません。
絵を動かせます。 絵の右の十字で上下左右に 1 マスずつずらせます(8 マスまで)。
はみ出たところは見えなくなるだけで、反対へずらすと戻ります。ずらして空いたところは斜線になり、
描けません(ずらしても描ける範囲は広がりません)。LED には 0 番の色(白)で送ります。
↻ で右に 90 度まわし、 で左右・上下に裏返します(元の絵だけが変わり、ずれはそのまま)。
は、いま見えている絵を元の絵にした新しいブロックを、
どこにもはめずにすぐ右下に置きます(斜線だったところも白になり、描けるようになります)。
ずれていないときは押せません。パラパラ漫画は、ブロックを複製して「待つ」を挟みながら並べ、
1 コマずつずらして作ります。
値は元の絵 64 文字のあとに、ずれているときだけ を付けます(前の版の 64 文字だけの値も読めます)。
は「全部塗り」しかできない(Ruby 側は 3 引数のみ)ので、
、残りを 1 マス 5 バイトで置きます。
実測で、りんごの絵(3 色)が 175 B、全部同じ色なら 25 B、8 色を総当たりにした最悪で 305 B。
プログラム領域は 10,240 B なので、ぶん入ります複数のタブ・URB EE Lab からも同じ基板に同時につながり、どこからでも停止 / 再開できます。 ただし基板とのやり取りは 1 つずつで、ほかのタブが書き込んでいる間は、書き込み・停止・再開を断ります (「ほかのタブが基板に書き込んでいます」と出ます。終わってから押し直してください)。
BASE(GPIO / wait_ms / if / unless / until / case-when / loop / for / while / && / || / puts "文字列" / warn デバッグ出力 / def(引数付き最大2個) / require)= 12,964 B。
そこに必要な機能だけを足して、16 KB の Flash に収めます。
| ID | 内容 | Flash 増分 |
|---|---|---|
| Q1 | Q16.8 固定小数点演算(四則演算・比較・case/when・ラムダ式) | +592 B |
| Tn | Tone — 周波数制御(ブザー・メロディ) | +476 B |
| Pw | PWM デューティ比(モータ・サーボ・LED調光) | +548 B |
| Ad | ADC アナログ入力(整数 0〜255) | +328 B |
| Us | 超音波センサ HC-SR04(距離 cm) | +156 B |
| I2 | I2C / Wire(SDA=pin3 / SCL=pin4・100kHz) | +1,448 B |
| Rn | 乱数 rand / srand(引数なしの srand は電源を入れたときの RAM の中身を種にする) | +264 B |
| Tm | 絶対周期 — ずれない周期(every_ms)と時間計測(Timer) | +384 B |
| Ve | 変数の拡張 — 数値SD変数($永続変数・3つ目以降の数値変数・数値配列。確認は warn) | +1,516 B |
| Sv | SD変数・数値出力(PRINT_REG・文字変数・to_s。Ve の機能を含む) | +2,832 B |
warn 変数は数値を DEVICE LOG へ送るデバッグ出力(Ruby のKernel#warn= stderr に相当)。 数値の文字列化をブラウザ側で行うため Sv 不要で使えます(Q1+Sv 構成のみ Flash 16KB 超過のため非搭載 —puts/pで代替)。
# LED チカ
led = GPIO.new(2, GPIO::OUT)
loop do
led.toggle
sleep(0.2)
end
# ボタンでLED制御
led = GPIO.new(2, GPIO::OUT)
button = GPIO.new(11, GPIO::IN | GPIO::PULL_UP)
loop do
if button.low?
led.on
else
led.off
end
end
# アナログ値で LED の点滅間隔が変わる(Ad 単独)
led = GPIO.new(2, GPIO::OUT)
sensor = ADC.new(0) # 対応ピン: 0, 1, 12, 15, 16
loop do
v = sensor.read # 0〜255 の整数
led.toggle
wait_ms v * 2
wait_ms 20
end
# HC-SR04 超音波距離センサ(配線: TRIG→pin3(PC1) ECHO→pin4(PC2) VCC→5V GND→GND)
sonar = Ultrasonic.new(3, 4)
loop do
puts sonar.read # 距離 (cm) を HID コンソールへ出力(0 = 範囲外)
sleep(0.5)
end
# $ で始まる変数は SD カードに保存され、電源を切っても残る(Sv)
$count = $count + 1
s = $count.to_s
msg = "count="
msg << s
puts msg
# def 引数付き(コンパイル時に定数として展開、Q1 不要)
def blink(pin, ms)
led = GPIO.new(pin, GPIO::OUT)
led.write(1)
sleep(ms)
led.write(0)
sleep(ms)
end
blink(2, 0.5)
blink(10, 0.25)
# 多重代入: 2 変数を 1 行で初期化(Q1 コンポーネント必要)
led = GPIO.new(2, GPIO::OUT)
on_ms, off_ms = 200, 800
loop do
led.on
wait_ms on_ms
led.off
wait_ms off_ms
end
TinyVM 命令セット・URB1 フォーマット・ピン配置の全リファレンスは URB Lab ページ内に掲載しています。
| Arduino ピン | CH32V003 | PWM | ADC | 用途 |
|---|---|---|---|---|
| 2 | PC0 | ✅ | — | LED 出力(基板上 LED) |
| 3 | PC1 | — | — | SDA(I2 コンポーネント)/ HC-SR04 TRIG 推奨 |
| 4 | PC2 | — | — | SCL(I2 コンポーネント)/ HC-SR04 ECHO 推奨 |
| 5 | PC3 | ✅ | — | PWM / Tone ブザー |
| 11 | PD1 | — | — | タクトスイッチ |
| 0, 1, 12, 15, 16 | PA1/PA2/PD2/PD5/PD6 | — | ✅ | アナログ入力 |
| 6 | PC4 | ✅* | ✅* | ⚠ SD カード SS 専用 — 使用不可 |
| 7 / 8 / 9 | PC5/PC6/PC7 | — | — | ⚠ SD カード SCK/MOSI/MISO 専用 — 使用不可 |
* ハードウェアは PWM・ADC 対応だが、SD カード搭載版では SS として占有されるため使用不可。
| ページ | スケッチ例 | 状態 |
|---|---|---|
| Echo Test | WebHIDTest.ino | ✅ 公開中 |
| Keyboard Practice | KeyboardPractice.ino | ✅ 公開中 |
| Keyboard Practice 2 — switch 文 | KeyboardSwitch.ino | ✅ 公開中 |
| Mouse Practice | MousePractice.ino | ✅ 公開中 |
| Mouse Practice 2 — GetPos | MousePractice2.ino | ✅ 公開中 |
| Maze Solver | MazeSolver.ino | ✅ 公開中 |
| Snake Solver | SnakeSolver.ino | ✅ 公開中 |
| Rock Dodge | RockDodge.ino | ✅ 公開中 |
| Snake VS | SnakeVS.ino | ✅ 公開中 |
0x50/0x52 パケットをデコードしてテキスト・バイナリを WebCom 通信へ転送(HidMonitorTest スケッチ向け)HidBridgeTest スケッチ向け)0x01 Feature Report)を送信し UIAPduino の WaitAvailable() を解除hid.Print() / hid.Println() / hid.Clear() 出力をブラウザでリアルタイム表示(緑端末 UI)0x01 Feature Report)を送信し UIAPduino の WaitAvailable() を解除0x53 Ready 通知を受信してログ表示hid.Recv() で受け取りnavigator.hid の有無 / window.isSecureContext / location.protocol / userAgent。
使えないときは、PC の Chrome・Edge で開く/https:// で開き直す、を案内(Android は別の案内)requestDevice({ filters: [] }) をボタン 1 回につき 1 回、ほかの await より先に呼ぶ(クリック直後でないと出せないため)。
絞り込まないので、選ぶ画面がそもそも出るかが分かる。SecurityError・NotAllowedError・選ばれなかったとき、それぞれに意味と次にやることを出す。
同じ段に「このサイトで許可済みの機器」(getDevices()。開いた時点・USB の抜き挿し・チェックのあとに取り直す)open() してすぐ close()。開けなければ、ほかのアプリ・ほかのブラウザが使っていないか、挿し直しを案内する。
このページが開いたものだけを閉じる1209:D004「UIAPduino WebHID」。arduino_core_ch32 で作ったプログラムが名乗る番号1209:B803、OS の画面では「32V003」。UIAP が付けた番号。終わらせる処理をしない限り続く?mode=boot(URB Block Lab の「⚙ 準備」から)… 冒頭は「ファームウェアを書き込む前の確認です。ボタンを押しながら挿して、すぐ離してください」。
32V003(1209:B803)なら ✔「OK ファームウェアを書き込める状態です」、ふだんの状態(1209:D004)や別の機器なら !で挿し直しを案内する。
一覧に何も選ばれなかったときも、ボタンを押しながら挿し直すよう案内するKNOWN の表。いまは 1209:D004・1209:B803)だけ。
それ以外の機器は「異常」と言わず、灰色で「このページが知っている番号ではありません」と生の値を出す。番号は KNOWN に 1 行足せば増やせるproductName(空文字なら「(空文字)」)/ vendorId / productId(10 進と 16 進)/ usagePage/usage(collections の全数)を表示。
失敗時は error.name と error.message の両方を出すWebHIDTest.ino をページ内でシンタックスハイライト表示Keyboard.print() で文字列を入力KEY_LEFT_ARROW)で移動して文字を修正KEY_BACKSPACE で文字を削除KEY_RETURN で改行KEY_HOME で行頭に移動して文字を挿入case・break の使い方を実際に動かしながら学べる.ino に座標を直接埋め込む形式で、マウス HID の仕組みを体験できるhidPrint() などのスタンドアロン関数で HID コンソールへ出力hid.GetPos(x, y) でカーソル座標を動的取得し、相対移動量を計算する発展版hidPrint() スタンドアロン関数を Hid クラスのメソッドとして実装し直す C++ OOP の練習hid.Print() / hid.Println() / hid.GetPos() / hid.Recv() を持つ Hid クラスを Hid.h / Hid.cpp に分離CMD_DEL / CMD_RMDIR)SDmin.h(軽量 SD ライブラリ)を使用し、LFN(長いファイル名)にも対応WebHID_SD.ino を確認・ダウンロード可能.midb バイナリに変換・ダウンロード.midb 形式: MIDB マジック + [uint16_t 遅延ms][uint8_t データ長][MIDIバイト列] の繰り返し.midb を SD カードに入れ、MidbPlayer.ino を書き込んだ UIAPduino SD に接続した SAM2695 で再生snake.sendDir(dx, dy) で次の方向を返すだけSnakeHID クラス(SnakeHID.h)に通信をカプセル化、C++ クラス設計の練習も兼ねる#define PLAYER_NAME)CMD_DIR を待ってから次のティックへ進むので、
USB の遅延や計算時間では勝敗が決まらない(2 秒タイムアウト・3 回連続で反則負け)SnakeVSHID クラス(SnakeVSHID.h)に通信をカプセル化maze.sense(x, y) / maze.moveTo(x, y) の 2 関数だけでアルゴリズムを実装できるMazeHID クラス(MazeHID.h)に分離し、C++ クラス設計の練習も兼ねるスケッチ名/スケッチ名.ino 構成の ZIP として取得。Arduino IDE でそのまま開けるnavigator.hid レベルで自動検知)Chrome または Edge(WebHID / Web Serial API 対応ブラウザ)— これだけで使えるページもあります
Arduino IDE 2.x(スケッチを自分でビルドする場合)
UIAPduino ボードパッケージ(スケッチを自分でビルドする場合)— Board Manager に以下の URL を追加してインストール
https://raw.githubusercontent.com/tarosay/board_manager_files/main/package_uiap_hid_index.json
| 対象 | 必要バージョン | 理由 |
|---|---|---|
| URB Lab(SD 版) | v1.2.15 以降 | SDmin のランダムアクセス API と v1.2.7 の ADC ピン修正。v1.2.14 まではピン 11(PD1)が IO として働かない |
| URB EE Lab | v1.2.15 以降 | NeoPixel の回転・減光が NeoPixelmin::getPixels()(v1.2.13)を使う。v1.2.14 まではピン 11(PD1)が IO として働かない |
URB EE Lab のビルド済みファームを書き込むだけなら、Arduino IDE もボードパッケージも要りません。
com0com(HID-Serial Bridge を使う場合のみ)— 仮想 COM ペアドライバ(Windows 用)
スケッチ名/スケッチ名.ino の構成になり、Arduino IDE でそのまま開ける)
(または File → Examples → WebHID → WebHIDTest から直接開く)[Web ブラウザ] [UIAPduino]
sendFeatureReport() ─── EP0 ──────────► usb_handle_user_data()
Control Transfer ↓
32 バイト(v1.1.5 以降) WebHID.recv() / hid.Recv()
inputreport イベント ◄─── EP3 ────────── WebHID.send() / hid.Print()
Interrupt IN ↑
8 バイト / 10ms usb_handle_user_in_request()
| 方向 | エンドポイント | プロトコル | サイズ |
|---|---|---|---|
| Web → デバイス | EP0 | Control Transfer (Feature Report) | スケッチの recv バッファサイズに依存 |
| デバイス → Web | EP3 | Interrupt IN | 8 バイト / パケット |
Feature Report サイズについて
arduino_core_ch32 v1.1.5 で Feature Report サイズが 16 → 32 バイト に変更されました。
スケッチ内のWebHID.recv(buf, sizeof(buf))に渡すバッファサイズが、
USB ディスクリプタに登録される Feature Report サイズになります。
ブラウザは接続時にディスクリプタを読み取り、そのサイズに合わせたsendFeatureReport()のみ受け付けます。
各ページはデバイス接続時にサイズを自動検出し、UI に反映します。
ボードパッケージ Feature Report サイズ arduino_core_ch32 v1.1.3 以前 16 バイト arduino_core_ch32 v1.1.5 以降 32 バイト
USB Low Speed の制約
Interrupt エンドポイントの最大パケットサイズは 8 バイト固定。
16 バイト以上を返す場合は 8 バイトずつ複数回WebHID.send()を呼ぶ。
| 用語 | 区間 | 技術 |
|---|---|---|
| HID通信 | UIAPduino ↔ ブラウザ | USB HID(WebHID API) |
| WebCom通信 | ブラウザ ↔ 仮想COMポート | Web Serial API |
| VirtualCOM通信 | 仮想COMペア内部(COM8 ↔ COM9) | com0com |
| COMモニタ通信 | 仮想COMポート ↔ モニタアプリ | シリアル通信 |
| マーカー | 名称 | 方向 |
|---|---|---|
0x50 | UIAPduino → ブラウザ | |
0x51 | GetPos | 双方向 |
0x52 | Write | UIAPduino → ブラウザ |
0x53 | Ready | UIAPduino → ブラウザ |
0x01 | 接続通知 | ブラウザ → UIAPduino |
Print(0x50) — hid.Print() / hid.Println() / hid.Clear()
| byte | 内容 |
|---|---|
| 0 | 0x50(マーカー) |
| 1 | flags: 0x80=続きあり / 0x04=クリア |
| 2〜7 | テキスト本体(最大 6 文字、0x00 埋め) |
※ 改行は 0x0A をテキストに含めて送信(NL フラグは廃止)
Write(0x52) — hid.Write()
| byte | 内容 |
|---|---|
| 0 | 0x52(マーカー) |
| 1 | flags: 0x80=続きあり |
| 2 | ペイロード長(0〜5) |
| 3〜7 | バイナリペイロード |
Ready(0x53) — hid.Ready()(任意使用)
| byte | 内容 |
|---|---|
| 0 | 0x53(マーカー) |
| 1〜7 | 0x00(予約) |
接続通知(0x01) — HID接続時にブラウザが送信
| byte | 内容 |
|---|---|
| 0 | 0x01(接続通知マーカー) |
| 1〜 | 0x00(未使用) |
UIAPduino 側の hid.WaitAvailable() がこれを検出して処理を開始する。
docs/ ← GitHub Pages のルート
index.html ← ポータルページ(デモ一覧・WebHID 解説)
echo.html ← Echo Test デモ
keyboard.html ← Keyboard Practice(コメント外し形式)
keyboard2.html ← Keyboard Practice 2(switch 文形式)
mouse.html ← Mouse Practice(固定座標)
mouse2.html ← Mouse Practice 2(GetPos / Hid クラス)
maze-solver.html ← Maze Solver(迷路探索アルゴリズムの練習)
snake.html ← Snake Solver(経路探索アルゴリズムの練習)
rock-dodge.html ← Rock Dodge(リスクとリターンの判断)
snake-vs.html ← Snake VS(対戦アルゴリズム / vs CPU・2P 対戦)
hid-console.html ← HID Console(デバッグ / ユーティリティ)
hid-serial-bridge.html ← HID-Serial Bridge(com0com 経由シリアル中継)
hid-test.html ← HID 接続チェック(ボタン 1 つの簡易チェック。requestDevice / open / getDevices と判定)
sd-file.html ← SD Filemanager(SD カードファイル管理)
midi-to-midb.html ← MIDI → MIDB Converter(SAM2695 用)
uiapruby.html ← URB Lab(コンポーネント選択式 Ruby → URB1 コンパイラ + TinyVM 実行環境)
uiapruby-ee.html ← URB EE Lab(保存先が I2C EEPROM の版。NeoPixel / UART / EEPROM 変数ビューア / ファーム書き込み)
uiapruby-block.html ← URB Block Lab(Blockly でブロックを組む子ども向けの入口。.rb で保存 / 読み込み、?rb= でギャラリーから開く)
lib/
prism/ ← @ruby/prism WASM(Ruby の AST 解析)
blockly/ ← Blockly 一式(Apache-2.0。圧縮済みファイルをそのまま同梱)
urb/
compiler.js ← Ruby AST → URB1 コンパイラ(EE Lab と Block Lab で共有)
eeprom.js ← WebHID で EEPROM に読み書きする接続(同上)
flasher/
rv003usb_webflasher.js ← rv003usb ブートローダへの書き込み(MIT。上流をそのまま同梱)
sketchBins.js ← ビルド済みファーム 6 種を base64 で内包(tools/embed-bins.mjs が生成)
blockBin.js ← URB Block Lab 専用ファーム 1 本(tools/build-block-bin.mjs が生成)
rv003usb_reader.js ← ブートローダから Flash を読み出して照合する(フラッシャから読み出し部分だけ写したもの。MIT)
knownBins.js ← これまでに配ったファームのハッシュ一覧(tools/gen-known-bins.mjs が生成)
favicon.svg ← 全ページ共通ファビコン
images/
com0com.jpg ← com0com Setup GUI スクリーンショット
WakayamarbLOGO.png ← Wakayama.rb コミュニティロゴ
24x24みかん.png ← sv-dotart サンプルのドット絵原図
UIAPduinoBlock.png ← URB Block Lab のロゴ(256px 版も同梱)
urb-block-icon-32.png ← URB Block Lab のファビコン(ロゴのパズルのブロックだけ、32×32)
urb_block_banner.png ← URB Block Lab の SNS リンクカード画像(og:image、1734×907)
urbgallery.png ← URB ギャラリーの絵(384px 版を URB Block Lab のギャラリー案内で使用)
UIAPDuinoICON.png ← UIAPduino のアイコン(256px 版も同梱)
sketches/ ← スケッチ置き場(Arduino IDE 風サブフォルダ)
WebHIDTest/
WebHIDTest.ino ← Echo Test スケッチ(16 バイト Feature Report)
HidBridgeTest/
HidBridgeTest.ino ← HID-Serial Bridge テストスケッチ(Raw エコーバック)
Hid.h ← Hid クラス宣言
Hid.cpp ← Hid クラス実装
HidMonitorTest/
HidMonitorTest.ino ← HID-Serial Bridge Protocol モード用スケッチ
Hid.h ← Hid クラス宣言
Hid.cpp ← Hid クラス実装
KeyboardPractice/
KeyboardPractice.ino ← Keyboard Practice スケッチ(正解)
KeyboardSwitch/
KeyboardSwitch.ino ← Keyboard Practice 2 スケッチ(正解)
MousePractice/
MousePractice.ino ← Mouse Practice スケッチ
MousePractice2/
MousePractice2.ino ← Mouse Practice 2 スケッチ
Hid.h ← Hid クラス宣言
Hid.cpp ← Hid クラス実装
HidPrint/
HidPrint.ino ← HID Console デモスケッチ
Hid.h ← Hid クラス宣言
Hid.cpp ← Hid クラス実装
MazeSolver/
MazeSolver.ino ← 迷路探索アルゴリズム(メインスケッチ)
MazeHID.h ← MazeHID クラス(WebHID 通信を担当)
SnakeSolver/
SnakeSolver.ino ← スネーク経路アルゴリズム(メインスケッチ)
SnakeHID.h ← SnakeHID クラス(WebHID 通信を担当)
RockDodge/
RockDodge.ino ← 岩よけ+アイテム取得アルゴリズム(メインスケッチ)
RockDodgeHID.h ← RockDodgeHID クラス(WebHID 通信を担当)
SnakeVS/
SnakeVS.ino ← 対戦スネークアルゴリズム(メインスケッチ)
SnakeVSHID.h ← SnakeVSHID クラス(WebHID 通信を担当)
WebHID_SD/
WebHID_SD.ino ← SD Filemanager スケッチ(32 バイト Feature Report)
MidbPlayer/
MidbPlayer.ino ← MIDI (.midb) 再生スケッチ(32 バイト Feature Report)
UIAPSerial.h ← 軽量 USART1 クラス(宣言)
UIAPSerial.cpp ← 軽量 USART1 クラス(実装)
UIAPrubyVm*/ ← URB Lab TinyVM ファーム(コンポーネント組み合わせ別の動作確認済みビルド。
配布はページ内の generateIno がブラウザで生成)
Measure_*/ ← コンポーネント別 Flash サイズ計測用スケッチ
tools/
gen-ino.js ← uiapruby.html の generateIno を抜いて .ino を出す検証用
embed-bins.mjs ← URB EE Lab の配布ファームを作る。generateIno →
arduino-cli → .bin → base64 を一連で回し
docs/lib/flasher/sketchBins.js を生成する
gen-known-bins.mjs ← git の履歴から配布ファームのハッシュを集め、knownBins.js を生成する
(embed-bins.mjs と build-block-bin.mjs が最後に呼ぶ)
README.md
tools/embed-bins.mjsはnpm run buildに繋いでいません。.binを作るには arduino-cli が要るためです。生成物はリポジトリに追跡させ、generateInoを直したときだけ リポジトリのルートでnode tools/embed-bins.mjsを走らせてください。 走らせ忘れると、ページ側の SHA-256 照合が書き込みを止めます。
HidBridgeTest / HidMonitorTest / HidPrint スケッチで共通して使用する Hid クラスのメソッド一覧。
| メソッド | プロトコル | 説明 |
|---|---|---|
Print(const char* s) | 0x50 | テキスト送信(改行なし) |
Print(int v) | 0x50 | 整数送信(改行なし) |
Println(const char* s = "") | 0x50 | テキスト送信 + 改行(0x0A) |
Println(int v) | 0x50 | 整数送信 + 改行(0x0A) |
Clear() | 0x50 CLEAR | 画面クリア |
Write(const uint8_t* buf, uint8_t len) | 0x52 | バイナリ送信(0x00 含むデータも正確に転送) |
Send(const uint8_t* buf, uint8_t len) | Raw | マーカーなし Raw 送信 |
Ready() | 0x53 | 準備完了通知(任意) |
Recv(uint8_t* buf, uint8_t maxLen) | — | Feature Report 受信。戻り値: 受信バイト数 |
WaitAvailable(uint32_t timeoutMs = 0) | — | Feature Report 到着まで待つ。データを消費しない。0 = 無限待ち |
GetPos(int16_t& x, int16_t& y) | 0x51 | カーソル座標取得。500 ms タイムアウト |
LTO(Link Time Optimization)について
CH32V003 は Flash 16 KB。LTO が有効なため、スケッチで使用しないメソッドはビルド時に自動削除されます。
URB Block Lab — 「基板のファームウェアを調べる」で、いま配っている版が「まだ公開していない版」と出ていたのを直した
knownBins.js は、作ったときに git の履歴にあるファームウェアにしか日付とコミットを付けない。
コミットは自分自身の番号を中に書けないので、ビルドと同じコミットに入る照合表では、いま配っている版の記録が必ず空になる。
これまでは、コミットのあとに照合表を作り直してもう一度コミットしていたが、2026-10-10 以降の 4 回でこれが抜け、
公開中のページが、いま配っている 7 本すべてを「まだ公開していない版」と出していたblockBin.js)を照合表に足すようにした。
照合表を作り直し忘れても、いま配っている版が「どれとも一致しない」にならない。
書き換えが要るかどうかは、もともと照合表ではなくこのファームウェアと比べて決めているURB Lab / URB EE Lab / URB Block Lab — rand で小さい数が出やすかったのを直し、範囲の外はコンパイルエラーにした
rand(0..199) なら 0〜55)。
余りのもとが最後の欠けた段に入ったときは捨てて引き直すようにし、どの数も同じ確率にした。
範囲の数が 256 の約数(2・4・8・…・128)のときは捨てることが無いので、srand(n) からの並びは前と同じrand(0..499) は 0〜243 になって 250 が出ず、rand(0..255) はいつも 0 になっていた。
引けるのは 0〜254(rand(n) は n が 1〜255、rand(a..b) は 0 ≦ a ≦ b ≦ 254)とし、外れたらコンパイルエラーにした。
もっと広い範囲が欲しいときは rand を 2 回使って組み合わせる。URB Block Lab の乱数ブロックの入力欄の上限は
変えていない(下げると、保存した作品を読み込んだときに黙って丸められ、エラーにならないため)sketchBins.js・blockBin.js・knownBins.js)。
URB Block Lab のファームウェアの版を 4 に上げたので、前のファームウェアの基板には「古い版です」と出るdocs/sketches の UIAPrubyVmRn / UIAPrubyEeVmRn も同じように直したURB Block Lab — 「基板のファームウェアを調べる」で、どれとも一致しないときも書き込みモードのままにした
URB Lab / URB EE Lab / URB Block Lab — 引数なしの srand の種を、電源を入れたときの RAM の中身から作るようにした
srand までにかかる時間が、クロックの数で数えて毎回同じだからだと考えている.bss の終わりから上の RAM は、電源を入れた直後は毎回違う値だった
(起動時に 0 にされるのは .bss まで)。ただし srand の時点で読むと、それまでにスタックが毎回同じ値で
上書きしていて変わらなかったsetup() の最初の行で .bss の終わりから今のスタックの位置までを読んで混ぜ、_seed に取っておく。
引数なしの srand(種 0)は _seed を種にする。srand(n) と、srand を置かないときの動きは変わらないsketchBins.js・blockBin.js・knownBins.js)。
URB Block Lab のファームウェアの版を 3 に上げたので、前のファームウェアの基板には「古い版です」と出るdocs/sketches の UIAPrubyVmRn / UIAPrubyEeVmRn も同じように直したURB Lab(SD 版)— ブザー(Tn)も PWMmin を使わない書き方にして、530〜550 B 小さくした
toneOut(pin, freq) を generateIno に置いた。SD 版はピン 6 が SD の SS 専用で Tone に使えないので、
ピン 6 の分岐は無い(対応ピンは今までどおり 0・2・5・12)pwm=default を外した(生成する .ino の先頭コメントと、ダウンロードする ZIP の sketch.yaml)docs/sketches/UIAPrubyVmTn と UIAPrubyVmQ1Tn も同じように直した(Measure_Tn は Flash 計測用なのでそのまま)tone・frequency・off・鳴らしたままの音の高さの変更が正しく鳴ることを確かめたtoneOut にだけあるピン 6 の分岐で、GCC がピン番号で引く表(CSWTCH.*、160 B)を
作っているため。EE 版からピン 6 の分岐を外すと表が消え、ブザー版(24FC256)は 15,992 B から 15,844 B になるURB EE Lab — ブザー(Tn)を PWMmin を使わない書き方にして、ブザー版を 360 B 小さくした
PWMmin.h を使っていて、
ピンごとに処理を丸ごと書いた Pwm_write・Pwm_stop と、ほぼ同じ関数 2 つ(Pwm_freq_TIM1 / Pwm_freq_TIM2)が入っていたためgenerateIno に、Pw の pwmSetDuty と同じ書き方の toneOut(pin, freq) を 1 つ置いた。
ピンごとに違うのは使うタイマーとレジスタだけなので、それを変数に入れて設定は 1 回だけ書く。
周波数 0 で止めて入力フロートに戻すのは今までと同じ。対応ピンも同じ(0・2・5・6・12)pwm=default を外した(生成する .ino の先頭コメント・
ダウンロードする ZIP の sketch.yaml・tools/embed-bins.mjs)。付けても外しても .bin は同じになることを確かめたsketchBins.js・knownBins.js)。サーボ版は変わらない。
docs/sketches/UIAPrubyEeVmTn も同じように直したtone・frequency・off・鳴らしたままの音の高さの変更が正しく鳴ることを確かめたURB Lab / URB EE Lab / URB Block Lab — 引数なしの srand(「乱数の種をばらばらにする」)が、種をばらばらにしていなかった
srand は、起動のたびに違う並びの乱数にするはずだった(Rn の仕様・ブロックの説明・サンプルのコメント)。
ところがコンパイラは種 0 を送り、ファームウェアは 0 を 1 に直すだけだったので、いつも srand(1) と同じ並びになっていたgenerateIno、SD 版と EE 版の両方): 種 0 を受け取ったら、SysTick->CNT | 1 を種にするようにしたlib/urb/compiler.js と uiapruby.html の中のもの): srand(0) は今までどおり srand(1) と同じ並びに
なるよう、1 にして送る(65536 など、下 16 ビットが 0 になる数も同じ)。種 0 を送るのは引数なしの srand だけsketchBins.js・blockBin.js・knownBins.js)。
URB Block Lab のファームウェアの版を 2 に上げたので、前のファームウェアの基板には「古い版です」と出るdocs/sketches の UIAPrubyVmRn / UIAPrubyEeVmRn も同じように直した(Measure_Rn は Flash 計測用なのでそのまま)URB Block Lab — 「NeoPixel の並び」で、折り返さないマトリックスも選べるようにした
URB Block Lab — 「明るさを ◯ にする」を引き出しの上に移し、絵のブロックで最初に持っている色を赤にした
URB Block Lab / EE Lab — 絵のパレットを「もし」や繰り返しの中でも使えるようにした
np.palette を if / unless / case / while / until の中に書くとエラーにしていた。
基板にはパレットという考え方が無く、np.palette は命令にならない(色はコンパイラが前もって np.paint に入れる)ためlib/urb/compiler.js)が、パレットの表を通る道ごとに追うようにした。
if / case は道ごとに表を分け、合流したところで、道によって色が違う番号を「決まらない」にする。
break・next・return で抜けた道も、行き先で合流させる3.times のように回数が決まっている繰り返しは、抜けたあとに本体の最後の色を使うnp.paint / np.paint_fill が使ったときだけ、エラーにした。
パレットを変えたのと同じ if や繰り返しの中で描けば、その色で描かれる。if の中から、パレットと絵を書いた関数を呼ぶこともできるloop do の中で、絵より後ろで np.palette を変えると、次の周の絵に色が届かず、
エラーも出ずに最初の色のままだった(コンパイラが繰り返しの中を 1 回しか読んでいなかったため)。今は「決まらない」としてエラーになるloop do・while・n.times・break・return のそれぞれで色が決まること/決まらないときにエラーになること、
URB EE Lab のサンプル 45 個(コンポーネントの組み合わせ 2 通り)の命令とエラーが変わらないことを確かめたURB Block Lab / EE Lab — n.times の中で変数を使うと、ループから抜けられなくなっていたのを直した
10.times の中で変数の代入や比較をすると、10.times が終わらず、そのあとの puts に進まなかった(Q1 を選んでいるとき)n.times は回数を R2 に数えていたが、本体の計算がその R2 を一時置き場に使って書きかえていた10.times のあとの puts が出ることを実機で確認したURB Block Lab / EE Lab — 絵の色(パレット)を外から変えるブロックと、np.palette / np.paint / np.paint_fill を足した
lib/urb/compiler.js)に 3 つ足した。
np.palette(パレット番号, 赤, 緑, 青) はコンパイラの中の表を書き換えるだけで、命令を出さない。
np.paint(LED の番号, パレット番号, 赤, 緑, 青) は、表に色があればその色、無ければ (赤, 緑, 青) で NEO_SET_RGB を出す。
np.paint_fill(パレット番号, 赤, 緑, 青) は同じ決め方で NEO_FILL を出す。
each は展開・def は写すので、表はプログラムが動く順に書き換わる。ファームウェアは変わらないnp.palette は if / unless / case / while / until の中ではエラーにした(通るかどうかが書き込む前に分からないため)。
URB Block Lab では「もし」「〜の間 繰り返す」の中に置くと、Ruby の先頭に警告コメントも出すnp.fill / np.set を出す(出る Ruby は変わらない)URB Block Lab — 「?」が消えることがあったのを直した
URB Block Lab — 繰り返しの番号・関数の引数を、NeoPixel の色や番号・関数の引数に入れられるようにした(両端がへこんだ口)
np.fill(i * 10, 0, 0) や
光る(i) のように繰り返しの番号とその計算が書けて、コンパイラも通していたが、ブロックは数を打つ欄だったので書けなかった250 - 番号 × 10 など)r = rand(100..500) → 光る(i))。
定義を替えて引数の数が変わっても、引数に入れてあったものと「呼ぶ前に」の行は残る(無くなった引数の口の分は消える)v = 5 と書いた行が、⊕ を押しただけで v = 0 になっていた。打った数も控えて戻すようにしたlib/urb/compiler.js)を 1 か所直した。 書き込む前に数を決める計算が、かっこ((番号 - 1) * 10)を
読めなかった。かっこの中が式 1 つなら、その値を使う。ふつうの変数が入っていれば今までどおりエラー。
URB EE Lab にも効く(かっこの中が数だけの式は、今までより短い命令になる).rb・ギャラリー・ほかのタブからの貼り付けのどれから開いても同じ。ファームウェアは変わらないURB Block Lab — 「記録の配列」(電源を切っても残る配列、Ruby の $ の配列)を足した
$ の無い配列(v = Array.new(24))しか作れなかった。Ruby では def の中から外の
ふつうの変数は見えないので、展開関数の中で配列を使うと「基板に書き込む」でコンパイルエラーになっていた$名前 = Array.new(個数)・$名前[i] = 値・$名前[i]。
$ の変数は def の中からも見えるので、展開関数の中で使えるrec +ハッシュ)。記録と同じ名前にはならない$ の配列はもともと読めた)URB Block Lab / EE Lab — 動いているプログラムがあると、先に「緊急停止」を押さないと書き込めなかった
wait_ms があるプログラムが動いていると、「基板に書き込む」がほとんどの場合タイムアウトした
(wait_ms 500 を並べた NeoPixel のアニメーションでは、一度も書き込めなかった)wait_ms の delay() の最中は見ない。ページは STOP の 300 ms 後に OPEN_W を送っていたので、待ちの残りが
300 ms より長いと OPEN_W が STOP を上書きし、VM は止まらないまま OPEN_W を読み捨てていた。
「緊急停止」を先に押すと通ったのは、STOP のあとに何も送らないので上書きされなかったからlib/urb/eeprom.js の sendProgram を、止まったのを確かめてから書き込むようにした。
まず OPEN_R で待ち受け中かを見て(止まっていれば応答が来る)、動いていれば STOP を送り、
基板から「止まりました」(0x44 の 0x19)が届くまで STOP 以外を送らずに待つ。
70 秒たっても止まらなければ、書き込まずに知らせる(wait_ms の最大は 65,535 ms)eeprom.js は 2 ページで共有しているので、URB EE Lab の「EEPROM に送信」にも効くURB Block Lab — 4×4 の NeoPixel に絵を描くブロック「4×4 に絵を表示」と、テープのつなぎ方を決める「NeoPixel の並び」を足した
NeoPixel の引き出しの「8×8 に絵を表示」のすぐ下に置いた。作りは 8×8 のパレット版と同じ
(色 8 つ・ずらす・回す・裏返す・この絵からはじめる・絵を消してはじめから)field_neo_paint)に size: 4 を渡して使う。ずらせる量・回す・裏返すは
1 辺のマス数から決めるようにした。8×8 の値(64 文字+@dx,dy)は変わらないfill / set / show / auto)URB Block Lab — 基板のファームウェアが古いと、プログラムが始まるときに知らせる
LOG_UAP_START(0x10)の 2 バイト目に、
ファームウェアの版の番号を載せる(今回が 1)。ページは、同梱ファームウェアの版
(blockBin.js の fwRev)より小さければ、ログに「基板のファームウェアが古い版です…」と出すuiapruby-ee.html の BLOCK_FW_REV。URB Block Lab のファームウェアの動きを変えたら 1 つ上げる。
tools/build-block-bin.mjs は、生成した ino に出た番号を blockBin.js に写す⚙ 準備 でファームウェアを書き込み直すと出なくなるURB Block Lab — 24FC256 でも動くようにした(変数の番地の割り当てを石で分ける)
$ の付く配列は、名前・先頭番地・要素数が同じときだけ値を残す(24FC256 / 24FC512)。
新しい割り当てでは前の配列の個数で位置がずれるので、名前だけでは残さない。
URB Block Lab のブロックには $ の付く配列が無いので、ここは実機で確かめていないtools/build-block-bin.mjs は変数領域の先頭を 10,240 に差し替えるが、スロットの大きさは
2,560 のときに計算した 21,416 B のまま。6 個目は 117,320〜138,735 番地で、131,072 B を 7,664 B 超える。
6 個目の EEPROM 変数が 3,433 個より大きい配列のとき、超えた分がプログラム領域に書かれる。
CAT24M01WI は今までどおりにする段階なので、まだ直していない⚙ 準備 の「24FC256 の基板では動きません」、ページの説明文、
SNS のカード(og:description / og:image:alt)、バナー(urb_block_banner.png)の右下の注意書き、
トップページのカードの注記を、「CAT24M01WI または 24FC256」 にしたURB Block Lab — EEPROM の石を、基板が起動時に自動で見分ける
LOG_UAP_START(0x10)に載せてページへ知らせる。
電源を入れたときに 1 回だけ出る LOG_EE_OK(0x01)ではなく 0x10 にしたのは、
あとから開いたページにも書き込み・再開のたびに届くようにするためURB EE Lab / URB Block Lab / URB Lab(SD 版)— センサの値などを 3 つ目以降の変数に入れるとエラーになっていた
v = sonar.read / v = sensor.readd = t.ms / d = t.usb = ser.read(EE 版のみ)v = rand(...)v = I2C.master_get(...)(SD 版は I2C.slave_get も)v = 条件 ? x : yv = arr[i] と同じ作りにそろえた。
レジスタが埋まっていれば一時レジスタで値を作り、VAR_STORE で EEPROM / SD 変数に書く。
必要なのは Ev / Ec(SD 版は Ve / Sv)だけで、ファームは変わらない$g = sensor.read のように $変数 に直接入れると、レジスタ扱いになって保存されていなかった。
ほかの $変数 と同じく、EEPROM / SD に保存されるようになったdocs/lib/urb/compiler.js(URB EE Lab / URB Block Lab)と docs/uiapruby.html(SD 版)。
両ページのサンプルは、直す前とコンパイル結果が変わらないことを確かめたcompiler.js 側は、v6 = sonar.read を 3 つ目以降の変数に入れるプログラムで、
基板への書き込み・動作まで実機で確認した。SD 版はコンパイル結果の確認のみURB EE Lab / URB Block Lab / URB Lab(SD 版)— x = x の代入で命令を出さない
v2 = v2 が出る。
コンパイラはこれを一時レジスタ経由のコピーにしていて、値は変わらないのに 1 行で 4 命令・18 B を使っていた$変数 を含む)・文字変数・配列変数(arr = arr)が対象。
配列は 0 番目の要素を読んで書き戻す 2 命令、文字変数は自分へのコピー 1 命令が出ていたarr[1] = arr[1] は対象外で、今までどおり命令が出る。
まだ値を入れていない変数の x = x も、今までどおりエラーになるdocs/lib/urb/compiler.js(URB EE Lab / URB Block Lab)と docs/uiapruby.html(SD 版)。
確認はコンパイル結果のみで、実機ではまだURB EE Lab / URB Block Lab / URB Lab(SD 版)— duty / angle / shift に 3 つ目以降の変数を渡すとエラーになっていた
pwm.duty(v)・servo.angle(v)・np.shift(v) はレジスタの変数しか探していなかったため、
EEPROM / SD に置かれた変数を渡すと「引数はリテラルまたは数値変数のみ対応」で止まっていたduty を呼ぶと起きやすかったgpio.write(v) と同じやり方)。
ファームは変わらないangle は、読み込んだレジスタをそのまま計算に使う。別にコピー先を取ると、
R0/R1 が埋まっているときにコピー先と計算用のレジスタが同じ R3 に重なるためdocs/lib/urb/compiler.js(URB EE Lab / URB Block Lab)と docs/uiapruby.html
(SD 版。shift は SD 版に無い)compiler.js 側は、コンパイル・基板への書き込み・動作まで実機で確認した。
SD 版はコンパイル結果の確認のみURB EE Lab / URB Block Lab — ピン 6 に出したはずの PWM が、ピン 12(A3)に出ていた
pwmSetDuty() に、ピン 6(PC4 / TIM1_CH4)の分岐が無かった。
ピン 12(PD2 / TIM1_CH1)用の else に入っていたため、PWM.new(6) やブロックの
「モーター ピン 6」で、ピン 12 に出ていたdocs/sketches/UIAPrubyEeVmPw にも同じ漏れがあったので直したTone はボードパッケージの PWMmin.h を使っていて、
こちらは元からピン 6 に対応しているURB EE Lab / URB Block Lab / URB Lab(SD 版)— ピン 11 が IO として働いていなかった
pinMode() しても GPIO として働かなかった(digitalWrite(11, HIGH) でも 0V)。
v1.2.15 で、pinMode() が PD1 のとき SWIO を自動で切り離すようになったuiapruby.html・uiapruby-ee.html の表記と、生成する .ino の先頭コメント、
docs/sketches/ の URB スケッチ 29 本の先頭コメント
(EE 版 13 本は、前から v1.2.12 のままでページとずれていた)URB Block Lab / EE Lab / Lab(SD 版)— 基板を選ぶ画面に UIAPduino 以外が出ていた
usagePage: 0xFF00 だけだったため、PC 内蔵の HID 機器
(実際に出たのは「HIDI2C Device」)も候補に出て、選べてしまっていた。
選ぶと「つながりました: HIDI2C Device」と出たあと、書き込みのたびに
エラー: Failed to write the feature report. になるlib/urb/eeprom.js の connect() / attach() と docs/uiapruby.html の requestDevice()attach())でも選ばれなくなるHID 接続チェック(hid-test.html)を足した
allow pasting の壁や、1 回の貼り付けで
requestDevice を 2 回呼ぶとユーザー操作の期限が切れて 2 回目が空になる事故がありました。
URL を開いてボタンを 1 回押すだけで同じことが分かるように、ページにしましたgetDevices() を自動で実行し、許可済みの機器を出します(0 件ならそう出ます)requestDevice({ filters: [] }) を 1 回だけ実行します。絞り込まないので、ダイアログがそもそも出るかが分かりますvendorId / productId(10 進と 16 進)と usagePage/usage(正常な UIAPduino は 0xFF00/0x0001)、
失敗したときの error.name と error.message を画面にそのまま出します1209:D004/書き込みモード 1209:B803・OS の画面では「32V003」)を載せました。
書き込みモードは異常ではなく、ファームウェアを書き込むときの正しい状態として判定します1209:D004 は arduino_core_ch32、1209:B803 は UIAP が付けた番号で、同じ CH32V003 でも別の基板・別のコアでは番号が違うことも書きましたhid-test.html のまま)hid-test.html?mode=boot を開き、ページはこの印を見て、書き込みモード(32V003)を正解として案内・判定します。
印の無いとき(トップページや Discord に貼ったリンク)は、2 通りの挿し方を両方出します。
「⚙ 準備」の節の説明も、「基板に書き込む」ではなく「ファームウェアを書き込む」でつまずいた人向けに書き直しましたURB Block Lab — 「⚙ 準備」のダイアログを直した
URB Block Lab — 子どもたちに使ってもらった結果から、お絵描きブロック(パレット版)を直した
↻ で右に 90 度、
⇋ ⇅ で左右・上下のミラー、「この絵からはじめる」で見えている絵を元にした新しいブロックを作ります。
ずらして空いたマスは斜線で、描けません。ファームウェアは変えていません(ページが絵を作って、今までどおり送るだけ)URB Block Lab — 色を 8 つ使って絵を描くブロック「8×8 に絵を表示」を足した
0〜7 を 64 文字)。色はブロックに並べた
8 つの色えらび(いろ)が持つので、描いたあとに色を変えると絵の色も変わります。
面を開くと下に色の列が出るので、えらんでからマスを押します(なぞってまとめて塗るのも同じ)np.fill は「全部塗り」しかできません(Ruby 側は fill(r, g, b) の 3 引数のみ)。
そこでいちばん多く使った色だけを fill でまとめ、残りを 1 マスずつ np.set で置きます。
同じ色を 2 つの番号に入れている人がいるので、番号ではなく出す RGB で数えていますnp.fill / np.set / np.auto / np.show はすべて既存の命令ですURB Block Lab — マスを押したまま動かすと、次のキーボード操作が 1 回無視されていた
pointerdown で塗ったあとに来る click を「1 回捨てる」印で
よけていました。押したまま別のマスへ動かすと、押したマスに click が来ないので
印が残ったままになり、次に Enter / Space で押したマスが塗られませんでしたclick の detail が 0(=キーボードから出た click)のときだけ塗るようにしました。
2 色版・パレット版の両方に入れていますURB Block Lab — 色えらび・8×8 の面が、ブロックの下ではなく「ずっと」の列の下に出ていた
上 374 / 下 441 なのに、
Blockly が置き場所に使った値は 上 373 / 下 714 でしたField.getScaledBBox() です。フィールドに枠(borderRect_)が無いと
ブロックの高さ・幅で代用しますが、その高さは getHeightWidth() で
下につながったブロックを全部含みます。このページの自前フィールド(色えらび・8×8)は
どちらも枠を持っていないので、両方ともずれていましたgetScaledBBox() を、自分が描いた図形の大きさを返すように差し替えました。枠を作る手もありますが、
Blockly の .blocklyEditableField > rect { fill:#fff } が見本の下に白く覗くので、
見た目を変えないこちらにしていますURB Block Lab — ブロックの説明(吹き出し)の折り返しを直した
wrap(説明, 50) をかけ、返ってきた行を
1 行 1 個の <div> にしますが、この wrap は /\s+/ で切って組み直すので
半角スペースのある場所にしか改行を入れられません。日本語の説明にスペースは
数字や英字のまわりにしか無いため、そこで折れます。しかも切れ残った行は 50 字
(全角なら 100 字ぶんの幅)になり、そのあと画面の幅でもう一度折り返されるので、
二重に折れて不揃いになっていましたBlockly.Tooltip.setCustomTooltip() で中身の描き方を差し替え、wrap を通さずに
文字をそのまま入れるようにしました。折り返す場所はブラウザが決めます
(ブラウザは「(」を行末に置かない・「。」を行頭に置かないといった日本語の決まりを知っています).blocklyTooltipDiv { max-width: min(30em, calc(100vw - 32px)) } で決め、
line-break: strict を足しました。短い説明はこれまでどおり中身なりの幅に縮みますBlockly.utils.string.wrap を差し替えても効きません。 圧縮版の呼び出し口は内部の関数を
直接見ていて、公開されている wrap はその写しだからですURB Block Lab — 8×8 の NeoPixel に絵を描くブロックを足した
NeoPixel の引き出しに 「8×8 に表示」 を足しました。ブロックの上に 8×8 の見本が乗っていて、
押すと 64 マスの面が開きます。マスを押すと裏返り、押したままなぞるとまとめて塗れます
(micro:bit の「LED 画面に表示」と同じ操作です)
色は えがく色 / うしろの色 の 2 つで、どちらも既存の色えらび(色・鮮やかさ・明るさ)です。 色を変えると、ブロックの上の見本もその場で塗り直します。 「ついている / 消えている」と呼ぶと、消えているのに色を選べるのがおかしくなるので、 絵として見た言い方にしてあります(うしろの色の既定は黒=消灯)
テープは 64 個を折り返し(蛇行)でつないである前提です。0 番は右上で、上の行は右から左、 次の行は左から右へ進みます(実機で確かめた並び)。
07 06 05 04 03 02 01 00
08 09 10 11 12 13 14 15
23 22 21 20 19 18 17 16
24 25 26 27 28 29 30 31
39 38 37 36 35 34 33 32
40 41 42 43 44 45 46 47
55 54 53 52 51 50 49 48
56 57 58 59 60 61 62 63
画面の (x, y) からテープの番号への変換(y が偶数なら y*8 + (7 - x)、奇数なら y*8 + x)は
ブロック側で行うので、絵を描く人は折り返しを気にしなくて済みます
出る Ruby は np.auto = false → np.fill(うしろの色) → えがいたマスだけ np.set(番号, r, g, b)
→ np.show → np.auto = true です。64 マス全部を set にすると 320 B になりますが、
うしろの色を fill でまとめるので 6 + 5 × えがいた数 バイトで済みます
(プログラム領域は 10,240 B。斜め線 8 個で 65 B、全部えがいても 331 B)
np.auto をすでに「しない」にしてあるときは、auto の行を出しません(二重に止めないため)
このブロックを置くと NeoPixel.new(64) で組み立てます。「NeoPixel を ◯ 個使う」で
64 より少なく決めていたときは、黙って書き換えると理由が分からないので、Ruby の先頭に
警告コメントを出してから 64 に上げます
ファームウェアは変えていません。同梱ファームはもともと leds: 64(docs/lib/flasher/blockBin.js)で、
np.fill / np.set / np.auto / np.show はすべて既存の命令です
URB Block Lab — OGP の説明文に、動く基板を書いた
ブロックでつくる Ruby × 電子工作。UIAPduino を楽しく動かそう で、
UIAPduino さえあれば動くと読めていました。実際には EEPROM(CAT24M01WI、0x50/0x51)が要ります⚙ 準備(大人の方へ) の中だけで、リンクを見た人には届きません。
og:description と <meta name="description"> を
ブロックをつなぐと Ruby になって、基板の中で動きます。動かすには UIAPduino と EEPROM(CAT24M01WI)が必要です。
にしましたURB Block 基板 という呼び方を README に書いていましたが、
誰も使っていない名前で、初めて見る人はそこでつまずきます。README からも消し、
CAT24M01WI の基板 のように、載っている石で言うようにしましたurb_block_banner.png)の右下に ※ EEPROM(CAT24M01WI)も必要です を足しました。
もとからあった 3 つの文(「ブロックでつくる Ruby × 電子工作」「UIAPduino を楽しく動かそう」
「つくる・うごかす・ひろがる!」)はどれも正しいので、書き換えずに注意書きだけを足しています。
も が「UIAPduino のほかにも」を受けるので、離れた右下にあっても意味が立ちますog:image:width / og:image:height を実寸に直しましたog:image:alt に絵の中の文字を写しました。画像を出さない設定の人にも ※ の一行が届きますURB Block Lab — ブロックに「?」ボタンを付けて、説明を読めるようにした
Blockly.Tooltip.HOVER_MS を書きかえても効かないので、出す時刻だけこちらで持ち、
吹き出しそのものは Blockly.Tooltip.display() に描かせていますhelpUrl を持っていて、
英語のドキュメントへ飛ぶためです#feffcc。大きさは HELP_SIZE ひとつを変えれば、丸も字も位置も付いてきますURB Block Lab — 「最初だけ」「ずっと」の 2 個目から先を無効にした
.rb の読み込み、
どの作り方でも同じです。生きているのは上にあるほうで、Ruby を作るときも同じ順で先頭を採るので、
色が付いているブロックと動くブロックが食い違いません# ⚠ 「ずっと」は 1 つだけです(2 つ目から先は動きません) と出ますURB Block Lab — ファビコンをパズルのブロックの絵にした
favicon.svg)で、タブを見ても URB Block Lab だと分かりませんでしたimages/UIAPduinoBlock.png)から緑と青のブロックだけを抜き出し、
images/urb-block-icon-32.png(32×32)を作りました。基板まで入れると 16px で穴がつぶれて、何の絵か分からなくなるためですURB Block Lab — 「と表示する」の出力が届いたら、下の引き出しを開くようにした
puts の出力は「▲ ログ / コンソール」を押さないと見えませんでしたloop do の中で出し続けても開くのはその 1 回だけで、閉じれば次に書き込むか再開するまで開きませんURB Block Lab — タブをまたいでブロックをコピー / 貼り付けできるようにした
.rb を 2 つのタブで開くと
同じ ID ができます。ID を残すと、片方で名前を変えた変数に黙って付いてしまうためです。
名前と種類だけにして、貼り付け先で名前で探し直しますかず と記録の かず など)があるときは、貼る側を かず2 にずらします
(すでにあれば かず3)。同じものを何度貼っても、同じ かず2 に付きます# ⚠ 展開関数「…」が ありません と出ます。同じ名前の関数を定義するブロックを貼ると 手順2 のようにずれますURB Block Lab — .rb を別の名前で保存しても、作品名とタブの見出しが変わらなかった
.rb を開く」は戻していました).rb を外して作品名にするようにしました。
保存ダイアログが出るブラウザ(Chrome / Edge)だけです。ダウンロードとして保存されるブラウザでは、
ページが付いたファイル名を知ることができませんURB Block Lab — SNS にリンクを貼ったとき、画像つきのカードが出るようにした
og:*)が無かったためですuiapruby-block.html に OGP タグと twitter:card(summary_large_image)を入れました。
X・Facebook・LINE・Slack・Discord など、OGP を読むサービスで同じカードになります
UIAPruby / タイトル URB Block Lab | UIAPrubyブロックでつくる Ruby × 電子工作。UIAPduino を楽しく動かそうimages/urb_block_banner.png(1731×909、新規追加)<title> を URB Block Lab | UIAPduino から URB Block Lab | UIAPruby にしました。
タブの名前は開いた直後に JS が「作品名 | URB Block Lab」に書き換えるので見えませんが、
SNS は JS を動かさずにこちらを読むためです?v=1 などを付けて貼ると読み直しますURB Block Lab — ギャラリー案内の絵から「♥24」などの数を消した
images/urbgallery.png を 1448×1086 に、images/urbgallery-384.png を 384×288 に作り直しました。
384px 版は 256 色にしぼって約 36KB にしていますuiapruby-block.html の <img> の高さを 307 から 288 にしました転送 — sendFeatureReport のリトライを 5 回から 10 回にした
lib/urb/eeprom.js の send() を、1 回目の送信とやり直し 9 回の合計 10 回にしました。
やり直しの前の待ちは 20 / 50 / 100 / 200 / 200 / 200 / 200 / 500 / 500ms です
(倍々を続けると 10 秒を超えるので 200ms で抑え、最後の 2 回だけ長めに待つ)。
失敗が続いたときに諦めるまでの合計は、約 370ms から約 1.97 秒になりますsend() を使うので、同じく効きますURB EE Lab — 変数の「全部読む」が途中で失敗しても、続きから読むようにした
OPEN_R し直して続きを読みます。
読みかけの要素(4 バイトに満たない分)は捨てて、その要素の頭から読み直しますURB Block Lab — 基板に入っているファームの版を調べられるようにした(大人の方へ)
⚙ 準備 に 「基板のファームウェアを調べる」 を足しました。書き込みモードの基板から Flash を 16 KB 読み出し、
これまでに配ったファームと照合して、どの版かを出します。読むだけで書き換えませんURB Block Lab — つながっていなくても「■ 緊急停止」「▶ 再開」を押せるようにした
URB Block Lab — 下の引き出し(ログ / コンソール)を、エラーのときだけ自動で開くようにした
docs/lib/flasher/knownBins.js は、tools/gen-known-bins.mjs が git の履歴にある
blockBin.js / sketchBins.js の全版から作ります(いまは 15 件)。URB EE Lab のファームも見分けられます。
embed-bins.mjs と build-block-bin.mjs が最後にこれを呼ぶので、ビルドすれば照合表も更新されますrv003usb_reader.js に分けました。同梱のフラッシャから、停止・読み出し・アプリ起動の
3 つだけを写しています。フラッシャ本体は変えていませんEE 版ファーム — 起動待ちをさらに短くして 1 秒にした
setup() の待ちを delay(2500) → delay(1000) にしました
(URB EE Lab・URB Block Lab の両方)。同梱ファーム 7 本を作り直し、URB EE Lab の説明文も「1 秒」に合わせていますEE 版ファーム — 電源オンからプログラムが走るまでの待ちを 2.5 秒短くした
setup() の delay(5000) を delay(2500) にしました(uiapruby-ee.html の generateIno)。
電源を入れてから動き出すまでの間が長かったためです。
待ちのあとに EEPROM の確認と LED 3 回点滅(900 ms)が続くのは変わりませんgenerateIno から作っているので、両方に効きますsketchBins.js の 6 本と blockBin.js の 1 本)。
サイズは 7 本とも変わっていません。URB EE Lab の ZIP で出る .ino も delay(2500) になりますURB Block Lab を本運用に — 「作成中」の透かしを外した
転送 — 2 つのタブから同時に基板とやり取りしないようにした(URB Block Lab / URB EE Lab)
lib/urb/eeprom.js に Web Locks(navigator.locks)による排他を入れました。
書き込み・RUN・STOP・変数ビューアの読み出しはロックを取ってから行い、
ほかのタブがやり取り中なら待たずに断ります(「ほかのタブが基板に書き込んでいます」)tarosay.github.io)のページどうしだけです。
基板は 1 台の前提で、2 台つないでいても同時には書き込めませんコンパイラ — sensor.read などの結果が R0 決め打ちで、変数を壊していた
print a0.read / puts sonar.read / warn sensor.read / warn t.ms / if button.low? /
if ser.available? は、読み取り結果を 必ず R0 に入れてから 出力・判定していました。
R0 は 1 つ目の数値変数が座る場所なので、その変数が読み取り値に化けますprint i と print a0.read を出すと、
次に表示される i が毎回「前回の A0 の値 + 50」になった。表示のたびに i が A0 の値へ
置き換わり、そこから 50 回(5 秒ぶん)足されていたため。$v0[i] の書き込み先も飛ぶので、
記録した配列自体も壊れるADC_READ pin=1 -> R2 / GPIO_READ pin=11 -> R2 になることを確認if button.low? も同じバグでした。R0 に変数がある状態でボタンを見るだけで壊れます転送 — sendFeatureReport にリトライを入れた
CMD_READ を 83 回送ります。EP0 コントロール転送は単発で
失敗することがあり、1 回でも落ちると読み出し全体が
エラー: Failed to write the feature report. で終わっていましたevery_ms の待ちは wait_ms と違って中でコマンドを見ないため、
周期 100ms のあいだデバイスがコマンドを取らないことが背景にありますCMD_READ 519 回)の読み出しが
実機で通ることを確認URB EE Lab — 変数ビューアに CSV 保存を足した
137.00 形式(Q16.8)URB Lab(SD 版)にも同じ修正を入れた
docs/uiapruby.html は lib/urb/compiler.js を共有せず自前のコピーを持っているため、
レジスタ破壊のバグがそのまま残っていた。EE 版と同じ 6 箇所を修正
(SERIAL_AVAILABLE は SD 版に無いので 6 箇所)sendFeatureReport のリトライも入れた。SD 版は変数ビューアが無いので読み出しの負荷は
無いが、プログラム転送は CMD_WRITE を何十回も送るので同じ取りこぼしが起きるPRINT_REG に整数部 0〜255 の制限を明記し、API リファレンスの
GPIO_READ pin, R0 / ADC_READ pin,R0 / ULTRASONIC_READ trig,echo,R0 を
「空きレジスタ」に修正(EE 版と同じ 4 箇所).urb のバイト列で
18 00 02(ADC_READ pin=0 → R2)・19 00 02(PRINT_REG → R2)・
04 0b 02(GPIO_READ pin=11 → R2)になっていることを確認URB EE Lab — ピン 6 の「実機未検証」を外した
ad-read サンプルのコメントの対応ピンに 6 を追加(0, 1, 6, 12, 15, 16)「記録」(電源を切っても残る変数)のブロックを足した
warn $count だけではエラー)、
さらに宣言の順が変わると EEPROM のスロットがずれて記録が消えます。
ブロックを並べ替えても順が動かないよう、変数を作った順で先頭に固定していますcharCodeAt(0) & 0xFF)で
書くため、日本語のままだと EEPROM の中で化けて、基板の変数一覧でも読めません。
英数字だけの名前はそのまま、日本語の名前は画面の名前から作った rec**** にします
(同じ名前なら いつでも同じ記録になります)I2C マスターのブロックを足した
regs[dst] = (int32_t)val; / regs[src] & 0xFF)、読んだら ×256、書く前に ÷256 して、
アナログ入力や NeoPixel の色と同じ 0〜255 にそろえました。書くほうは元の変数を割ってから
掛けて戻します(一時変数を作ると R0/R1 を食うため)0x48 / 72)。範囲外や数でない入力は
ブロックが受け付けません。0x50〜0x53 は基板の EEPROM が使っているので警告コメントを出しますWiremin は n バイトもレジスタ番号なしの
送受信も持っていますが、VM に命令が出ていないためです番号を変えながら回す繰り返しを 2 つ足した
(1..3).each do |i|)と
「つぎの数を 順に 〔数〕 に入れて 繰り返す」([10, 20, 30].each do |ms|。⊕ で個数を増やす)を
足しましたfor ではなく each を出します。 Ruby では for は勧められない書き方で、
for i in 1..3 と (1..3).each do |i| は同じ 21B です。Ruby タブは読み物でもあるので
each にしましたwait_ms i / np.set(i, …) /
a[i] = i / i * 100 は通り、if i > 1 と warn i は通りません
(どちらも「Q16.8: 左辺は数値変数である必要があります」等。いったん変数に入れれば通ります)break / next はこの 2 つの中では使えません(展開されるため break outside of loop)。
loopTypes に登録していないので、置いてもブロック側が無効にします3.times do |i| と 1.upto(3) はコンパイラが読めないので、番号が要るときはこの 2 つを使います問いかけのダイアログを、ページの見た目にそろえた
prompt / confirm で、ページの中でそこだけ素っ気ない灰色の枠でした。
「準備」と同じ形の <dialog> を用意し、Blockly.dialog.setPrompt / setConfirm / setAlert
でそちらへ通していますalert / confirm(8 か所)も同じ入れ物にしました。
.rb の保存・読み込み、URB EE Lab への受け渡し、ギャラリーからの読み込みです配列のブロックを足した
b = a[i] + 1 はコンパイラが読めません
(a[i] = a[i] + 1 と if a[i] > 5 は読めます)。この形を見つけたら、
Ruby の先頭に警告コメントを出しますArray.new(n) は不可)、EEPROM 変数は全部で 6 個まで
(配列 1 つで 1 個ぶん)です繰り返しに while と break / next を足した
while。ドロップダウンで until)と
「繰り返しを抜ける / 次の繰り返しへ」(break / next)を「繰り返し」に足しました。
それまで「◯ 回繰り返す」しかなく、回数の決まらない繰り返しが書けませんでしたBlockly.Msg で差し替え、
「ずっと」と「〜の間 繰り返す」を loopTypes に登録しました。登録しないと、正しく置いても
標準ブロックが自分を無効にしてしまいますcontrols_whileUntil は
「繰り返す:続ける条件 ⟨…⟩」と、条件より先に言葉が来て日本語の順になりません「関数」のブロックを追加した
def を出すブロックが 1 つも無かったので、「関数」のカテゴリを足しました。
「展開関数を定義」(引数 0 / 1 / 2 個)・「展開関数を呼ぶ」・「判定を定義 ◯ は〈条件〉」
(def 名前? … return 条件)・「判定 ◯」の 6 個ですdef がぜんぶインライン展開だからです。
TinyVM に呼び出し・戻りの仕組みが無く、本体は呼び出しの場所へ丸ごと写されますreturn 1 行)です変数のブロックを直した
0)を入れた。
空のままで数を打ち込めませんでした。Blockly 標準の変数の一覧は
「増やす」にしか影を付けないので、registerToolboxCategoryCallback('VARIABLE', …) で足しています
(Blockly 13 の Variables.flyoutCategory() が返すのは XML ではなく JSON です)F['math_change'] が無く、
置いても何も生成されていませんでした。x = x + 1 の形で出します(コンパイラは += を読みません)サーボの角度を変数で渡せるようにした/比べるブロックに数を打てるようにした
rand で決めた角度に振れます。
角度が変数だとページ側で duty を計算できないので angle(変数) をそのまま出します
(コンパイラは Q1 と frequency(50) を要求。どちらも満たしています)。
「サーボの設定」の幅は効かないので、置いてあるときは先頭に警告コメントを出しますlogic_compare と math_arithmetic の丸い差し込み口に影のブロックを入れた。
空のままだと数を打ち込めず、わざわざ「計算」から数のブロックを運ぶ必要がありましたURB ギャラリーから作品を開けるようにした
同梱ファームを 0x50/0x51 版に戻した。 tools/build-block-bin.mjs の CHIP を
M01_52 から M01 にしてリビルド(15,004 B。残り 1,380 B)
URB Block Lab に「作成中」の透かし。 0x50/0x51 版をまだ実機で動かしていないので、 そのことを画面に出す。確認できたら消す
ツールボックスの「変数」の下に URB ギャラリーへの入口。 別のタブで開くので、 組みかけの作品から離れません
uiapruby-block.html?rb=<id> に対応。 urb-gallery に
並べた作品を、新しい作品として読み込みます。題名は works.json から引きます
渡すのは作品の id だけで、URL は渡しません。取りに行く先はページ側が固定で持っています
(GALLERY_BASE = '/urb-gallery/')。同じ tarosay.github.io の中なので、CORS は関わりません
URB Block Lab を追加 — ブロックをつないで基板に書き込む
docs/uiapruby-block.html。 素の Blockly(Zelos レンダラ)でブロックを組むと
Ruby が出てきて、URB EE Lab と同じ経路で EEPROM に書き込まれます。
プログラムが基板の中で動くことが Scratch / Smalruby との違いで、
ボタンの名前も「動かす」ではなく 「基板に書き込む」(動かすのは電源で、ボタンではない)docs/lib/urb/ へ切り出し。uiapruby-ee.html の中にあった
2,186 行を compiler.js / eeprom.js に移し、2 ページで共有します。
両方に同じコードを置くと片方だけ古くなるためです.rb で保存 / 読み込み。 出てくるのはそのまま動く Ruby で、末尾に
# urb-block/1 … のコメントとしてブロックを deflate + base64 で畳んで入れてあります。
読み込みはそのコメントだけを見るのでブロックの位置まで完全に復元でき、
マーカーが無ければ読み込まずに知らせます。壊れていたときは元の状態へ戻します.rb のファイル名にもなります⚙ 準備(大人の方へ)。 ファームウェアの書き込みはヘッダから外し、手順つきのダイアログへ。
基板 1 台につき一度きりの作業で、押し間違えると基板が書き込みモードのまま残るためです■ 緊急停止 / ▶ 再開。 引き出しのバーから基板を止めたり動かし直したりできます。
wait の無いループを走らせていると書き込みが通らないことがあり、その復帰用です。
どのタブからでも、URB EE Lab からでも同じ基板に効きますnavigator.hid.getDevices() を使うので選択ダイアログは出ません。
これがないと、新しいタブは一度書き込むまで puts が出てきませんでしたtools/build-block-bin.mjs)。構成は
Q1 Pw Ad Se Nr Us Rn Ev の 15,004 B(残り 1,380 B)。
ブロックが吐く Ruby は冗長になりやすいので、プログラム領域を 2,560 B → 10,240 B に拡張しています
(EE_VAR_BASE は Flash にも RAM にも影響しません)URB Lab / URB EE Lab — 新コンポーネント Tm(絶対周期)を両方に追加
sleep を並べて周期を作ると、本体にかかった時間のぶん毎周ずれていく。
every_ms は起点を持ち、「前回起点 + 周期」で進めるので誤差が累積しない。
1000 周まわしても n × 周期 がそのまま経過時刻になるevery_ms 100 do … end と、
loop do の中に置く文の形 every_ms 100。**バイトコードは同じ 1 命令Timer で区間の時間を測れる — t.ms(上限 89.4 秒 / 1ms)と
t.us(上限 8.38 秒 / 1µs)。読んでも起点は動かないので同じ区間を両方読める。
区間を区切るのは t.resetevery_ms と Timer の起点は
完全に独立で、周期の境目で Timer が区切られることはないEVERY_MS 0x47 / TIMER_RESET 0x48 / TIMER_MS 0x49 / TIMER_US 0x4A。
番号は決定 27(新規の未使用領域に連続確保・既存番号は使い回さない)に従うTm にチェックを入れて .ino をビルドする。
6 種の .bin と inoSha256 は 1 バイトも変わっていないtm-blink / tm-jitter / tm-react。3 つとも Tm 単独で動くURB EE Lab — CAT24M01WI(128KB)を実機確認し、アドレスを選べるようにした
ee_write は 32B ページごと、ee_fill は 128B キャッシュを
境界で切り詰めながら、デバイスアドレスを 0x52 → 0x53 に切り替える)Tn/Pw × 石 3 種の 6 種になった。
EE_DEV_BASE は命令の即値に埋まるだけなので、Flash サイズは 1 バイトも変わらない
(0x50 版と 0x52 版の .bin は 4 バイトしか違わない)URB EE Lab — ビルド済みファームをブラウザから直接書き込めるようにした
rv003usb ブートローダ
(1209:B803)へ WebHID で書き込む。選ぶのは「ブザーか、サーボか」だけTn/Pw × 石の 4 種(当時)。base64 でページに内包し、
.bin はファイルとして置かない。生成は tools/embed-bins.mjs が
generateIno → arduino-cli → .bin → base64 まで一連で行う.ino の SHA-256 を突き合わせる。**食い違えば書き込まずに止まるので、
ファームの作り直し忘れをそのまま配ることがないNeoPixel を Np / Nr に分割し、SHIFT と DIM を小さくした
Np(9 命令) = 置く・塗る・ずらす・暗くする・自動表示の切り替え。+1,392 BNr(11 命令) = Np + 虹(rainbow)と hsv。+2,196 B。Np の上位集合SHIFT(回転)と DIM(減光)は、やりたいのがバイト列の操作なのに、1 画素ごとに
32bit へ組み立て直していた。NeoPixelmin::getPixels()(ボードパッケージ v1.2.13)で
バッファに直接触れる形にし、SHIFT 208→116 B / DIM 300→124 Bnp.shift(-1) → 11 歩)と % の換算はコンパイラ側へ移した。
Ruby の書き方は変わらないnp.auto = false — 自動表示を止められるようにした(NEO_AUTO 0x46、+52 B)
show() していたため、1 コマの途中経過が見えていた。
64 個だと 1 コマ描くのに 131 ms かかり、LED が 1 個ずつ埋まる様子が見えるnp.show だけが送る。それまで無意味だった np.show が意味を取り戻したnp-shift / np-dim を追加(np-rainbow は Nr 用に移動)Flash 使用量の表示を .bin 基準に直した
.text + .data しか数えず、Flash に載る
.init(160 B) と .init_array(4 B) を含まない。上限との比較が 160 B 甘く出ていたFLASH_BASE を 9,144 → 9,304 に修正実機確認(24FC256) — ブラウザからのファーム書き込み、NeoPixel の動作、
np.auto の効果を確認。
URB EE Lab(uiapruby-ee.html)を追加 — 保存先を I2C EEPROM に替えた版
$変数 を保存Np(NeoPixel) と Se(UART) を新設。
I2 は EEPROM アクセスに必須なため BASE に統合、I2C スレーブは廃止Ve / Sv は Ev / Ec に改名(Sv の S は SD の S だったため)UIAPrubyVm(12,504 B / RAM 844 B)比で −3,360 B$変数 を型・要素数・永続属性つきで表示する。
数値は Q16.8 から n.nn に変換。配列は「〇番目から全部読む」+「中止」。読み取り専用CMD_OPEN_R(0x04) を 24bit アドレス指定に拡張(+24 B)。変数領域へ直接シークするためKeyboard Practice の USB 設定・スケッチ例の場所の誤記を修正
keyboard.html の記載が実態と合っておらず、ZIP をそのまま使うとコンパイルが通らない状態だった
Tools → USB: Keyboard+Mouse → Keyboard+Mouse+WebHID。KeyboardPractice.ino は
#include <WebHID.h> を使うため、WebHID なしの kbd では WebHID.h の #error で停止するsketch.yaml の FQBN も usb=kbd → usb=kbdwebFile → Examples → **WebHID** → KeyboardPractice → Keyboard。
KeyboardPractice / KeyboardSwitch は libraries/Keyboard/examples/ にある
(libraries/WebHID/examples/ にあるのは WebHIDTest だけ)keyboard2.html も同じスケッチ例の場所の誤記を修正(USB 設定は元から正しい)sketches/KeyboardPractice/KeyboardPractice.ino のヘッダコメントも同様に修正usb=kbd はビルド失敗、usb=kbdweb は成功(4712 B / 28%)Snake VS — 2P 対戦を追加 + 開始演出(カウントダウン・効果音・陣地可視化)
PLAYER_NAME が
同じなら警告(どちらの機体か判別できず記録も混ざるため)PLAYER_NAME のハッシュと開始座標から生成。P1/P2 で開始座標が入れ替わるので
2 台の名前が同じでも必ず別の乱数列になる(同名でも決着 90% を確認)requestAnimationFrame だけで駆動していたため、
タブを裏に回すと試合が固まっていた。タイマーによるフォールバックを追加Snake VS 公開 — UIAPduino のアルゴリズムが CPU と陣地を取り合う対戦スネーク
x ≠ 15−x が常に成立し、2 匹が同じ行・列に並ばない(開幕の正面衝突が構造的に起きない)uint8_t cell[16][16] 1 枚と座標を (y<<4)|x に詰めた bfsQ[256] に変更。
668B(32%)まで下げて挑戦者用に 1,380B を確保Rock Dodge 公開 — 岩をよけながら得点アイテムを拾うプラクティス
CMD_TICK を列ごとのアイテム値配列にして 1 行に複数アイテムを置けるようにした
(送信 21 バイトのため受信バッファは 32 バイト必須)#define PLAYER_NAMEURB Lab — 新コンポーネント Ve(変数の拡張 — 数値SD変数)を追加
$count などの数値永続変数 / 3つ目以降の数値変数(揮発・SD 自動配置)/
数値配列($付きで永続)。値の確認は warn(DEVICE LOG)puts の数値出力(PRINT_REG)・文字変数・to_s は従来どおり Sv(コンパイルエラーで案内)URB Lab — サーボ angle() を 50Hz 標準タイミング化 + ファーム MUL_Q16 の乗算バグ修正
a * b 全般。変数 angle が 128° 以上で不正 duty になっていた)servo.frequency(50) が必須(違うとコンパイルエラーで案内)。
8bit PWM のため分解能は約 7°/ステップ。SG90 実機で 0〜180° 全域動作を確認済みtools/gen-ino.js の旧ファイル名(urb-lab.html)参照を修復スケッチ ZIP に sketch.yaml を同梱 — Arduino IDE 2.1+ でボード設定が自動選択される
sketch.yaml(default_fqbn: 1行)を同梱:
URB Lab / SD Filemanager / MIDI → MIDB / HID Console / Keyboard 1・2 / Mouse 1・2 /
Snake Solver / Maze Solver / Echo Test / HID-Serial Bridgedefault_fqbn のみの yaml は --fqbn 指定あり/なしのどちらのビルドも正常
(過去にビルドを壊したのは profiles 系の記述を含む yaml で、今回の形式は問題なし)URB Lab — ラムダ式対応(コンパイル時インライン展開)+ Q1 チェック漏れ修正
f = ->(x) { x < 15 } で定義し、
以下の場所で使用可能。呼び出し位置へコンパイル時にインライン展開されるため
実行時オーバーヘッド・追加 Flash なし
case d / when f / when ->(x) { x < 15 } — case 対象が引数に渡り条件として展開if between.call(d, 5, 10) — if / while / until / unless / 三項演算子の条件
(複数引数・&& / || も可)y = double.call(n) — 数値式(戻り値 = 本体の式の値)wait_ms half.call(500) — 引数がすべて定数ならコンパイル時に計算され、
リテラルを書ける場所ならどこでも使えるd = 1.0(数値代入)と if d < 15(比較演算)が
Q1 未選択でもコンパイルできてしまい、BASE ファームで実行時「不明なオペコード」に
なっていた(LOAD_Q16 / CMP_*_Q16 は Q1 命令)。コンパイル時に Q1 を案内するエラーを
表示するよう修正。d = sonar.read / rand / wait_ms d * 10 など Q1 不要の経路は従来どおりURB Lab — case/when のレンジ対応 + else 節が消えるバグを修正(コンパイラのみ・VM 変更なし)
when 0...15(終端含まず)/ when 1..3(終端含む)/ 始端なし when ..0 /
終端なし when 20.. then のレンジ比較に対応。多値との混在(when 0...3, 10)も可when 0, 1, 2, ...)よりバイトコードが大幅に小さいelseClause ではなく consequent を参照していたため、
case-when 導入以降 else の中身がエラーも出ずに消えていた)URB Lab — warn デバッグ出力を追加(Sv 不要で数値を DEVICE LOG へ)
warn d / warn sonar.read で
レジスタ生値(Q16.8 下位 24bit)を既存の hidLog パケット(type 0x20)で送信し、
数値→文字列変換はブラウザ側で実施 → Sv(+2,832B)なしでデバッグ出力が可能にwarn: 14 / warn: 14.25 形式で表示(整数はそのまま・小数部があれば小数表示)hidLog() に noinline を付与(LTO のインライン展開を抑制、▲20B)SD Filemanager / MIDI → MIDB Converter — スケッチダウンロードを ZIP 形式に統一
スケッチ名/スケッチ名.ino 構造)に変更
WebHID_SD.zip(WebHID_SD.ino)MidbPlayer.zip(MidbPlayer.ino + UIAPSerial.h + UIAPSerial.cpp).midb や SD カード内ファイルのダウンロードは従来どおり単体ファイルのままURB Lab — ボードパッケージ v1.2.7 対応・解説文の修正
print(0) 修正 = PRINT_REG が使う Print クラスの影響)main.urb 自動実行の開始が「電源オンから 5 秒後」である旨を追記(2 箇所)URB Lab — ソースエディタ ファイル操作・整形・スクロール改善
.rb ファイルを読み込み(Chrome/Edge では showOpenFilePicker() でファイルハンドルを取得し上書き保存に対応).rb ファイルをドロップして読み込みshowSaveFilePicker() でファイル名・場所を指定して保存do...end / if / until / while / def / class 等)に応じたインデントを算出= 前後のスペースを自動正規化(== / => / += 等は対象外)URB Lab — Tn の PWMmin 化(▲580B 削減)・ピンバリデーション追加
tone()/noTone() を廃止し PWMmin.h で実装
pwm=default が必要。ブラウザ生成コードに自動付加PWM.new / Tone.new で有効ピン(0/2/5/12)をチェック
PIN_SS=6)のため使用不可 → コンパイルエラーURB Lab — 構文拡張・def 引数付き・多重代入・コンポーネントチェック完備
until cond — while の条件を反転した構文case; when cond — 条件式による case 分岐(条件なし case)case x; when val — 数値等値比較(Q1 必須)if a && b / if a || b — 複合条件(短絡評価)def 引数付き対応(限定的): 引数最大 2 個・数値リテラルのみ。コンパイル時に定数展開するため Q1 不要
def blink(pin, ms) ... end のように定義し blink(2, 0.5) で呼び出すa, b = 1, 2(Q1 必須): 2 変数を 1 行で初期化rand / srand がコンポーネント未選択時にエラーを出すよう修正index.html: ボードマネージャ URL 欄に「コピー」ボタンを追加Coming Soon の整理・ブラウザ警告・戻るリンク統一
uiapruby.html に WebHID 非対応ブラウザ(Firefox / Safari)向けの警告バナーを追加
(コンパイルと .ino / .urb ダウンロードは利用可能な旨を併記)uiapruby.html / midi-to-midb.html の「← UIAPduino WebHID Lab」戻るリンクを
ヘッダー最上部(左上)へ移動し、全 12 ページで位置を統一URB Lab 全面刷新 — コンポーネント選択式へ
uiapruby.html を URB Lab として全面リニューアル(旧 urb-lab.html を改名。旧ページ
_uiapruby.html / ruby-to-urb.html と専用スケッチ UapRunner / UIAPrubyRunner /
UIAPrubyRunnerStandard は削除 — git 履歴から参照可)$ 永続変数(SD カード保存・電源断でも保持)・文字列変数・配列・
to_s / << 連結・PRINT_REG。24×24 ドット絵デモ(sv-dotart)sensor.read が整数 0〜255 を返すように(旧 0.00〜0.99 を廃止)。
ADC を直接レジスタ制御に書き換え Flash +708 → +324 B.urb)に改称、自動実行ファイル名は main.urbsm_seek / sm_write_at)を
利用。ボードパッケージ v1.2.5 以降が必須index.html のトップ導線を「UIAPduino SD をお使いの方へ」パネルへのページ内リンクに変更UIAPruby — HC-SR04 超音波距離センサ対応
UIAPrubyRunner.ino に ULTRASONIC_READ (0x1A) オペコードを追加
Ultrasonic.new(trig, echo) / puts sonar.read で距離 (cm) を HID コンソールへ出力pulseIn() / micros() は uint64_t soft-lib を引き込むため不使用。SysTick->CNT(32bit, 48MHz)直読みで実装uiapruby.html のコンパイラ・UI を対応
Ultrasonic.new(trig, echo) 認識・バイトコード生成UIAPruby Lab 公開・ADC 対応
uiapruby.html を新規追加 — Ruby 構文 → UAP1 バイトコード変換・実行環境
puts / print / p / putc 出力)UIAPrubyRunner.ino に ADC_READ (0x18) と PRINT_REG (0x19) オペコードを追加
ADC.new(pin) / puts sensor.read で ADC 値を HID コンソールへ出力images/WakayamarbLOGO.png)をヘッダーに追加Feature Report サイズ変更(16 → 32 バイト)対応
arduino_core_ch32 v1.1.5 で Feature Report サイズが 16 → 32 バイトに変更されたことに伴う HTML 側の修正。
sendFeatureReport() に渡す Uint8Array のサイズを 16 → 32 バイトに修正keyboard.html / keyboard2.html / mouse.html / mouse2.html / snake.html / maze-solver.htmlhid-console.html / hid-serial-bridge.html / sd-file.html(計 13 箇所)Maze Solver — EP0 並行送信バグ修正
startGame() を async 化し、連続する 3 回の sendFeatureReport() を逐次 await するよう修正inputreport イベントハンドラを非同期シリアルキュー(enqueueCommand / _flushCmdQueue)経由に変更し、EP0 の並行アクセスを防止sendFeature() に 3 回リトライ(20 ms 間隔)を追加Snake Solver — setInterval 並行実行バグ修正
setInterval + async tick() の組み合わせで前の tick 完了前に次の tick が起動するバグを修正tickBusy フラグを追加して tick の重複実行を防止sendFeature() に 3 回リトライ(20 ms 間隔)を追加SD Filemanager — ディレクトリ削除機能追加
CMD_RMDIR (0x0A) をブラウザ・スケッチ両側に実装(空ディレクトリのみ削除可能)WebHID_SD.ino に CMD_RMDIR ケースを追加SDmin.h に sm_rmdir() を追加(内部共通関数 _sm_del_entry() で Flash 増加を約 20 バイトに最小化)全ページのスケッチダウンロードを ZIP 形式に統一
スケッチ名/ フォルダ内に全ファイルを格納する Arduino IDE 対応構造
HidPrint.zip → 展開すると HidPrint/HidPrint.ino, HidPrint/Hid.h, HidPrint/Hid.cpp通信インターフェイスの用語定義
「Serial」という言葉の混同を避けるため、通信区間ごとに用語を定義した。
HID通信 / WebCom通信 / VirtualCOM通信 / COMモニタ通信
Hid クラスの大幅拡充(HidBridgeTest / HidMonitorTest / HidPrint 共通)
WaitConnect() を廃止し WaitAvailable(uint32_t timeoutMs = 0) に改名
recv() から available() に変更し データを消費しない 設計にWrite() メソッド(0x52 プロトコル)追加Ready() メソッド(0x53 プロトコル)追加0x02 フラグ方式から 0x0A in text 方式に統一HidMonitorTest スケッチ新規追加
Protocol モード(hid.Print/hid.Println)に特化したスケッチ。
USB: WebHID Only。WaitAvailable() + Ready() + カウンタ送信。
hid-serial-bridge.html の改修
0x01 Feature Report)を送信し WaitAvailable() を解除hid-console.html の改修
0x01 Feature Report)を送信し WaitAvailable() を解除0x53 Ready 通知を受信してログ表示0x0A in text)に対応しつつ旧仕様(0x02 フラグ)後方互換を維持docs/ に新しい HTML ファイルを作成(例: docs/newdemo.html)<a href="index.html">← UIAPduino WebHID Lab</a>
docs/sketches/スケッチ名/スケッチ名.ino(以降は同フォルダに .h / .cpp も追加可)として配置docs/index.html にリンク付きカードを追加(Coming Soon カードがあればそれを置き換える)README.md を更新 — 忘れやすいので 4 箇所すべて:
| リポジトリ | 説明 |
|---|---|
| urb-gallery | URB ギャラリー — みんなの作品(.rb を並べて Block Lab で開く) |
| arduino_core_ch32 | UIAPduino Arduino コア(WebHID ファームウェア含む) |
| board_manager_files | Board Manager 用インデックス JSON |
| Wakayama.rb | UIAPruby 開発元 — 和歌山発 Ruby コミュニティ |
MIT License — 詳細は LICENSE を参照
⇋⇅@dx,dynp.fill@dx,dy)です。
テープのつなぎ方も 8×8 と同じで、縦に折り返し(蛇行)、0 番は左下、左の列は下から上、
次の列は上から下です
(画面の (x, y) → テープの番号は、x が偶数なら x*4 + (3 - y)、奇数なら x*4 + y)。
このブロックを置くと LED は 16 個として組み立てます(8×8 と両方置いたときは 64 個)。
「NeoPixel を ◯ 個使う」でそれより少なく指定していたときは、Ruby の先頭に警告コメントが出ます(0..6).each の中で「パレット番号 〔番号〕 を 赤 〔番号〕×30 …」とすると、0〜6 番が順に変わります。
絵のブロックも、パレットで決まった色で見えます。 「いろ」の見本とマス、描く面の色が、
その絵のブロックに着いたときのパレットの色になります。外から決まった見本には右上に白い丸の印が付き、
絵のブロックの中では変えられません。繰り返しの中などで通るたびに色が変わる絵は、1 回目に通るときの色で見せます。
Ruby では np.palette(パレット番号, 赤, 緑, 青) で、パレットのブロックが 1 つでもあると、絵のブロックは
np.paint(LED の番号, パレット番号, 赤, 緑, 青) / np.paint_fill(…) を出します(パレット番号の色が決まっていればそれ、
無ければ絵のブロック自身の色)。パレットの表は書き込む前にコンパイラが持つだけで、命令は増えません。
「もし」や繰り返しの中でも使えます。 基板にはパレットという考え方が無く、色はコンパイラが前もって決めます。
そのため、パレットを変えたのと同じ「もし」や繰り返しの中の絵(関数を呼んだ先の絵も含む)は、その色で描かれます。
通ったかどうかで色が変わる絵(「もし」の中で変えた色を、「もし」の外の絵で使うなど)は、書き込むときにエラーになります(0..25).each の中で赤を「〔番号〕 × 10」にすれば、だんだん明るくなります。
ふつうの変数(乱数を入れた変数など)は、動いている途中で値が決まるので、形が合わずはまりません$変数 で、URB EE の一番の特徴です。
「記録 〔スコア〕 を ⟨1⟩ 増やす」「◯ に 書きかえる」「記録 〔スコア〕」の 3 つ。
宣言($score = $score)はブロックに出さず、生成側が Ruby の先頭にまとめて出します。
読むだけの使い方ができるようにするためと、宣言の順が変わると EEPROM のスロットがずれて
記録が消えるためで、順番は変数を作った順に固定します(あとから増やしても前の記録は動きません)。
「最初だけ」の中で数に書きかえていると、電源を入れるたびにその値になります。それを警告コメントで
知らせます(「もし」で囲ってあるときは、そうなるとは限らないので出しません)a[i + 1])も使えます。
中身は全部 0 から始まり、個数はブロックに打った数だけです(変数では決められません)。
名前は普通の変数と別の型にしてあるので、変数の一覧には出てきません。
EEPROM 変数は全部で 6 個までで、配列 1 つで 1 個ぶん使います。
計算のブロックの中に配列の値を入れた形(b = a[i] + 1)だけはコンパイラが読めないので、
Ruby の先頭に警告コメントが出ます。
配列に入る数は石で決まります。 24FC256 は 5,410 個まで(24FC512 は 13,602 個まで)。
超えると「配列が大きすぎて、基板に入りません(合計 ◯ 個、入るのは 5,410 個まで)」と出て、
プログラムは始まりません。番号が個数の外のとき(4 個の配列の 10 番など)は、
「配列「配列」の 10 番は ありません(0〜3 番まで)。プログラムを止めました」と出て止まります。
CAT24M01WI には、この 2 つのチェックはまだ入っていません(下の「必要な EEPROM」を参照)。
個数の多い配列は、始まる前に全部を 0 にするので時間がかかります
(1 個の書き込みに最大 5 ms。5,000 個なら最大で 25 秒ほど。その間は緊急停止も効きません)$ の配列($名前 = Array.new(個数))で、
「記録の配列 〔点数〕 を 〈4〉 個 つくる」「記録の配列 〔点数〕 の 〈0〉 番 を ⟨0⟩ にする」「記録の配列 〔点数〕 の 〈0〉 番」の 3 つ。
ふつうの配列は展開関数の中から見えません(Ruby の def の決まり)が、記録の配列は見えるので、
展開関数の中で配列を使うときはこちらを使います。配列と同じく EEPROM 変数 1 個ぶんを使いますn.times)のほかに、
「⟨条件⟩ の間 / になるまで 繰り返す」(while / until)、
「繰り返しを抜ける / 次の繰り返しへ」(break / next)、
「〈1〉 から 〈3〉 まで 〔番号〕 を変えながら 繰り返す」((1..3).each do |i|)、
「つぎの数を 順に 〔数〕 に入れて 繰り返す」([10, 20, 30].each do |ms|)ですdef が
コンパイルのときに呼び出しの場所へ丸ごと写される(インライン展開。TinyVM に呼び出し・
戻りの仕組みがありません)からですdef 光る(n) … np.set(n, n * 50, 0, 0))。
関数を呼ぶときは、引数とは別に ⊕ で「呼ぶ前に」の行を何行でも足せます(引数があってもなくても)。
引数に繰り返しの番号、「呼ぶ前に」の行に乱数を入れた変数、のように混ぜて渡せます。 呼ぶ直前にその変数へ値を入れておくと、写された本体がそのまま読みます。数でも変数でも
式でも置けますが、Ruby の引数ではなく同じ変数を共有しているだけで、そのぶん変数の枠
(R0/R1 の 2 つ、3 つ目からは EEPROM 変数)を使いますdef 名前? … return 条件)。
じぶんを呼ぶ形(再帰)は写しが終わらないので、呼び出しの輪を見つけたら Ruby の先頭に
警告コメントを出して、その呼び出しは出しませんもし ⟨変数⟩ < ⟨30⟩ のように、「計算」から数のブロックを運ばずに書けます.rb で保存 / 開く。 出てくるのはそのまま動く Ruby で、末尾のコメントにブロックが畳んで入っています。
読み込むときはそこだけを見るので、ブロックの位置まで完全に元通りになります。
URB Block Lab で保存した .rb でなければ、その旨を出して読み込みませんかず2 のように名前をずらします?rb=<作品の id> を付けて開くと、
URB ギャラリーの作品を新しい作品として読み込みます。
受け取るのは id だけで、取りに行く先(/urb-gallery/works/)はページ側が持っているので、
リンクで知らない場所を読ませることはできません⚙ 準備(大人の方へ) — ファームウェアの書き込みはここに入れてあります。基板 1 台につき一度だけ。
開くと必ず先頭(手順)から表示します。「閉じる」・Esc のほか、外側をクリックしても閉じます
(書き込み・調べている最中は、外をクリックしても閉じません)⚙ 準備 の中) — 書き込みモード(ボタンを押しながら USB)の基板から
Flash を読み出し、これまでに配ったファームと SHA-256 で照合して、どの版が入っているかを出します。
読むだけで書き換えません。ファームに版番号を持たせていないので、すでに配った基板も見分けられます。
このページと同じ版でなければ(古い版・URB EE Lab のファームウェア・どれとも一致しないもの)、
書き込みモードのまま「ファームウェアを書き込む」へ案内します(USB を挿し直さずに、そのまま書き換えられます)⚙ 準備 の一番下) — 「HID 接続チェックを開く」ボタンで
HID 接続チェック を別タブで開きます。
「ファームウェアを書き込む」の一覧に基板が無い・書き込めないときに、ボタンを押しながら挿した基板をブラウザがどう見ているかを自分で確かめられます。
ここから来る人のほとんどはファームウェアを書き込む前なので、?mode=boot を付けて、チェックの案内と判定を書き込みモード向けにしています■ 緊急停止 / ▶ 再開 — 引き出しのバーから、基板で動いているプログラムを止めたり動かし直したり
できます。「基板に書き込む」は、プログラムが止まったのを確かめてから書き込むので、書き込む前に押す必要はありません。
**基板につながっていなくても押せます。**押すと基板を選ぶ画面が出て、選んだら STOP / RUN だけを送ります(書き込みはしません)puts)の出力が最初に届いたときです。
出力が続いても開くのはその 1 回だけなので、閉じれば次に書き込むか再開するまで開きません(ブロックを隠さないため)。
書き込みの経過を見たいときは「▲ ログ / コンソール」で開きます$ の付く配列は、名前・先頭番地・要素数が全部同じときだけ値を残します
(前の配列の個数を変えると位置がずれるので、名前だけでは残しません)Q1 Pw Ad Se Nr Us Rn Ev)で、プログラム領域を広げた
専用ファームを同梱しています(tools/build-block-bin.mjs が生成。15,528 B、残り 856 B)