# MBC-Pro Sensors protocol v2 (plain text for AI assistants) — generated by _build/gen-reference.mjs Shared (all products): I2C write [id] then read 2*k bytes = k int16 little-endian; undefined id = -32768; snapshot every 10 ms. mBlock: UART 38400; send [id] -> [lo][hi][id^lo^hi]; commands E0~EE ack [00][00][id]; FD pack-all [AA][N][N x int16 LE][xor]. F0 deviceId: 低 byte = 出廠 I2C 位址(換位址後不變),高 byte = hw[0](通道數/顆數/類別) / low byte = factory I2C address (unchanged after re-addressing), high byte = hw[0] (channels / sensors / variant) F1 protoVer: 本版 = 2(SPIKE 模式 8 v[1]、EV3 ID 封包同一個數字) / 2 for this release (same number reported in SPIKE mode 8 v[1]) F2 fwVer: 主版×100 + 次版(例 102 = 1.2) / major×100 + minor (e.g. 102 = 1.2) F3 status: b0 就緒,其餘各產品定義(見各產品 flags) / b0 = ready; other bits per product (see flags) F4 seq: 每 10 ms 快照 +1,0~255 循環(2.56 秒一圈,不能拿來偵測重開機;不動 = 模組忙) / +1 every 10 ms snapshot, wraps 0~255 (2.56 s per cycle, not usable for reboot detection; frozen = module busy) F5 uptime: 開機後秒數,到 32767 停住(約 9 小時);數字變小 = 重開機過 / seconds since boot, saturates at 32767 (~9 h); a drop means the module rebooted F8 setAddress: [F8][新位址 0x08~0x77][新位址取反],存 EEPROM,重開機後生效;[F8][0x00][0xFF] = 回出廠位址(共識 B-5) / [F8][new 0x08~0x77][~new], saved to EEPROM, takes effect after reboot; [F8][0x00][0xFF] = back to factory address EF reboot: [EF][0xA5];mBlock 先回 ACK 再重開 / [EF][0xA5]; mBlock sends ACK first, then reboots ## 神攝手 學校版(舊版,停止支援) / Vision Sensor (School Edition) (legacy, no longer supported) (id cam_school, I2C 0x4C, hw0 1, model CAMSCH) hosts: ev3, spike, i2c, mblock, mvision, microbit values: 01 hue: 色相 / hue; range -1~100; S1 取樣點色相 0~100(色相環 0~240 等比縮放);−1 = 黑白灰(飽和度 < 10);S1 沒設定 = 0 / hue of sample point S1, 0~100 (hue ring 0~240 scaled); −1 = black/white/grey (saturation < 10); 0 when S1 is not set; EV3 mode0[0],mode1[0],mode2[0],mode3[0],mode5[0]; SPIKE mode0 b0,mode0 b1,mode5 v0,mode9 v0lo; mVision slot0 02 saturation: 飽和度 / saturation; range 0~100; S1 取樣點飽和度 0~100 / saturation of sample point S1, 0~100; EV3 mode1[1],mode2[1],mode5[1]; SPIKE mode9 v0hi; mVision slot1 03 value: 明度 / brightness; range 0~100; S1 取樣點明度 0~100 / brightness (HSV value) of sample point S1, 0~100; EV3 mode1[2],mode2[2]; SPIKE mode9 v1lo; mVision slot2 04 motion: 動態 / motion; range 0~100; 全畫面動態量 0~100(畫面變化越多越大) / whole-frame motion 0~100 (more change = larger); EV3 mode1[3],mode2[3]; SPIKE mode0 b1,mode0 b0,mode9 v1hi; mVision slot3 05 blobX: 色塊 X / blob X; range 0~100; 色塊中心 X 0~100,左 = 0;沒找到 = 0 / blob centre X 0~100, left = 0; 0 when not found; EV3 mode1[4],mode4[0]; SPIKE mode0 b2,mode0 b2,mode6 v0,mode7 v2,mode9 v2lo; mVision slot4 06 blobY: 色塊 Y / blob Y; range 0~75; 色塊中心 Y 0~75,下 = 0、上 = 75;沒找到 = 0 / blob centre Y 0~75, bottom = 0, top = 75; 0 when not found; EV3 mode1[5],mode4[1]; SPIKE mode0 b4,mode0 b4,mode6 v1,mode7 v2,mode9 v2hi; mVision slot5 07 blobW: 色塊寬 / blob width; range 0~100; 色塊寬 W 0~100;0 = 沒找到 / blob width W 0~100; 0 = not found; EV3 mode1[6],mode4[2]; SPIKE mode9 v3lo; mVision slot6 08 blobH: 色塊高 / blob height; range 0~75; 色塊高 H 0~75;沒找到 = 0 / blob height H 0~75; 0 when not found; EV3 mode1[7],mode4[3]; SPIKE mode9 v3hi; mVision slot7 09 blobArea: 色塊面積 / blob area; range 0~7500; W×H(0~7500);沒找到 = 0 / W×H (0~7500); 0 when not found; SPIKE mode0 b6,mode0 b6,mode6 v2,mode9 v4; mVision slot8 0A found: 有找到色塊 / blob found; range 0~1; 1 = 畫面裡有目標色的色塊(W > 0),0 = 沒有 / 1 = a blob of the target colour is in view (W > 0), 0 = none; mVision slot9 status F3: bit0 ready: 恆 1(相機進選單時值不更新,但仍 1) / always 1 (values freeze while the camera menu is open) bit1 found: = 值 0A / same as value 0A assumptions: - hw0 = 1(共識 #6:神攝手 1 = 學校版);model 字串 CAMSCH 照任務指定(韌體原本沒有型號欄位)。 - D4:I2C 0x4C 用 SDA = IO3、SCL = IO1(沿 PS4 Wire.setPins 慣例),與 EV3/SPIKE 串口模式二選一編譯;ESP32 從機不能時脈延展,onReceive 預載 32 B;頁面標「硬體已確認,上機待測」。mBlock 用同一組腳 Serial.begin(38400, SERIAL_8N1, 3, 1)。 - EV3 六個模式全部鎖住照盤點(模式 3/5 的 −1 已在 #65 修成符號延伸);EV3 定案最後的 golden 備註把 cam_school 列進「模式 5 改 ID」是筆誤(定案表本身寫「—」;模式 5 仍是 [色相, 飽和]),所以 ev3IdMode = null。 - SPIKE 模式 9 鎖住,只有 byte 8~9(v[4])從 0 改成面積 W×H;模式 6 改 [X, Y, 面積];模式 8 = [0x4C | 1<<8, 2, 韌體版, 更新序號];模式 1~4 維持 0。 - SPIKE 模式 0 的「面積」是 map(像素面積 0~5000 → 0~100),跟值表 09 的 W×H 不同,鎖住不改(照盤點)。 - mVision:N = 10(idx 0~9),色相 −1 送 255;每 20 ms 一包(B-6);不做 0x22(hosts.matrix = false)。 - 0A 有找到色塊 = W > 0(盤點:W 0 = 沒找到);F3 b1 同這個值。 - 值 05~08 的「沒找到 = 0」照盤點 §0;色塊 Y 下 = 0、上 = 75 照盤點(map(bestY,120,0,0,75))。 - 沒有寫入命令(韌體無法從程式改目標顏色/補光燈)。 ## 神攝手 WRO 版(HUE12)(舊版,停止支援) / Vision Sensor (WRO Edition, HUE12) (legacy, no longer supported) (id cam_wro, I2C 0x4C, hw0 2, model HUE12) hosts: ev3, spike, i2c, mblock, mvision, microbit values: 10~1B spotColor: 色點 1~12 顏色碼 / spot 1~12 colour code; range 0~255; 10~1B = S1~S12 顏色碼:0~239 彩色(色相 0~255 等比縮成 0~239)、240~245 白(飽和度 < 30,越低越大)、246~250 黑(明度 < 30,越暗越大)、255 = 色點沒開 / 10~1B = colour code of spots S1~S12: 0~239 colour (hue 0~255 scaled to 0~239), 240~245 white (saturation < 30, lower = larger), 246~250 black (value < 30, darker = larger), 255 = spot not enabled; EV3 mode0[0]; SPIKE mode0 b0; mVision slot0 20~2B spotVivid: 色點 1~12 鮮豔度 / spot 1~12 vividness; range 0~255; 20~2B = S1~S12 鮮豔度(飽和度)0~255:黑 = 1、白/彩色 = 實際飽和度;色點沒開 = 0 / 20~2B = vividness (saturation) of spots S1~S12, 0~255: black = 1, white/colour = actual saturation; 0 when the spot is not enabled; EV3 mode0[0]; SPIKE mode0 b1; mVision slot6 status F3: bit0 ready: 恆 1;b1 = 0(WRO 版沒有「有找到色塊」) / always 1; b1 = 0 (the WRO edition has no 'blob found') assumptions: - hw0 = 2(共識 #6:神攝手 2 = WRO 版);model = HUE12(樂高模式名)。 - I2C 0x4C 與學校版同一位址(主機用 F0 高 byte 1/2 分辨);D4:SDA = IO3、SCL = IO1,與 EV3/SPIKE 串口模式二選一編譯;ESP32 從機 onReceive 預載 32 B;上機待測。mBlock 用 Serial.begin(38400, SERIAL_8N1, 3, 1)。 - 值表只有 10~1B、20~2B(mBlock 定案);兩群各 12 個,I2C 一次連續讀 12 個值(24 B)剛好一群。 - EV3/SPIKE 只有一個模式 HUE12(type 95,動態描述表 DATA32×8),鎖住照盤點 §0-2 排法;沒有 ID 模式(type 95 只宣告 1 個模式,不加)。 - mVision 鎖住照盤點 §4:[0xAA][9][18 B][xor],byte 0~11 顏色碼、12~17 鮮豔度 4 bit;WRO 隊伍的 HUE12_AS_mVisionSensor_v1.0.8.mbr4 在用,不動;B-6:不節流(每圈 loop 送)。 - mVision 的鮮豔度是 S>>4(0~15),值表 20~2B 是完整 0~255;兩者不同是既有設計,不改。 - 顏色碼 255 只代表「色點沒開」,不代表「沒找到」(沒抓到時仍回種子點顏色,盤點 §0-1)。 - 不做 0x22(hosts.matrix = false);沒有寫入命令;F3 只有 b0。 ## IMU 陀螺儀 / IMU Gyro Sensor (id imu, I2C 0x6A, hw0 1, model IMU) hosts: ev3, i2c, mblock, matrix, microbit values: 01 headingGyro3D: 陀螺 3D 航向 / gyro 3D heading; range -32768~32767 °; 四元數算出的航向,度,開機/歸零 = 0,連續累積可超過 360(int16 到 ±32767 繞回,約 91 圈) / heading from the 3D quaternion, degrees, 0 at boot/zero, accumulates past 360 (wraps at ±32767, ~91 turns); EV3 mode0[0]; MATRIX 0x22 cmd4-32768 02 headingFused: 融合航向 / fused heading; range -32768~32767 °; 陀螺 3D 加磁力計慢修正的航向,度,減去相對零點;可超過 360 / 3D gyro heading slowly corrected by the magnetometer, degrees, relative to the zero point; may exceed 360; EV3 mode1[0]; MATRIX 0x22 cmd6-32768 03 headingGyro1D: 陀螺 1D 航向 / gyro 1D heading; range -32768~32767 °; 只繞轉向軸積分的航向,度,開機/歸零 = 0;可超過 360 / heading integrated about the yaw axis only, degrees, 0 at boot/zero; may exceed 360; EV3 mode3[0]; MATRIX 0x22 cmd8-32768 04 headingMag: 磁力航向 / magnetic heading; range -32768~32767 °; 磁力計傾斜補償航向,度,減去相對零點 / tilt-compensated magnetometer heading, degrees, relative to the zero point; EV3 mode3[1] 05 yawRate: 轉向軸角速度 / yaw rate; range -32768~32767 0.1 dps; 繞轉向軸(getYawAxis())的角速度,0.1 度/秒,正負跟航向同向 / angular rate about the yaw axis (getYawAxis()), 0.1 deg/s, same sign as the heading; EV3 mode2[0] 06 pitch: 俯仰角 / pitch angle; range -90~+90 °; 板子絲印 X 軸相對水平面的仰角:X 軸朝上 +90、朝下 −90、水平 0(用重力向量 atan2 算) / elevation of the board's printed X axis above horizontal: +90 pointing up, −90 pointing down, 0 level (from the gravity vector); EV3 mode6[0] 07 pitchRate: 俯仰角速度 / pitch rate; range -32768~32767 0.1 dps; 繞板子絲印 X 軸的角速度,0.1 度/秒(右手定則,從 +X 端看逆時針為正);注意這是 gyro X,不是 06 的微分 / angular rate about the board's printed X axis, 0.1 °/s (right-hand rule, CCW seen from +X is positive); this is gyro X, not the derivative of 06; EV3 mode5[0] 08 magTrust: 磁力信任度 / magnetometer trust; range 0~255; 融合演算法對磁力計的信任度 0~255(= 0~1 × 255) / how much the fusion trusts the magnetometer, 0~255 (= 0~1 × 255) 09 magDisturb: 磁場干擾度 / magnetic disturbance; range 0~255 0.01°; 磁場干擾程度 0~255(度 × 100,上限 255) / magnetic disturbance level 0~255 (degrees × 100, capped at 255) 0A upFace: 朝上的面 / face up; range 0~5; 哪個軸朝上:0 +X、1 +Y、2 +Z、3 −X、4 −Y、5 −Z(實體軸) / which axis points up: 0 +X, 1 +Y, 2 +Z, 3 −X, 4 −Y, 5 −Z (physical axes) 10~12 gyro: 角速度 1~3 軸 / gyro axis 1~3; range -32768~32767 0.1 dps; 10 X、11 Y、12 Z 角速度,0.1 度/秒(實體軸,已套軸向號誌) / 10 X, 11 Y, 12 Z angular rate, 0.1 deg/s (physical axes, sign-corrected) 13~15 accel: 加速度 1~3 軸 / accel axis 1~3; range -32768~32767 mg; 13 X、14 Y、15 Z 加速度,mg(1000 = 1 g) / 13 X, 14 Y, 15 Z acceleration, mg (1000 = 1 g) 16~18 mag: 磁力 1~3 軸 / mag axis 1~3; range -32768~32767 mG; 16 X、17 Y、18 Z 磁場強度,mG(毫高斯) / 16 X, 17 Y, 18 Z magnetic field, mG (milligauss) 0B cmdStatus: 命令狀態 / command status; range 0~0xEF03; (最後命令碼 << 8) | 狀態;狀態 0 完成、1 忙碌、2 失敗、3 拒絕(跟 SPIKE 命令回覆(模式 8 v3)同一套碼);E1~EB 都會回報;EB 以後沒定義的命令:I2C 直接不理、0B 不變(SPIKE 回 3 拒絕) / (last command code << 8) | state; state 0 done, 1 busy, 2 failed, 3 rejected (same codes as the SPIKE command reply (mode 8 v3)); reported for E1~EB; undefined codes after EB: ignored on I2C, 0B unchanged (SPIKE replies 3 rejected) commands: E0 zeroHeading: 四個航向都歸零(zeroHeadings());EV3 另有原廠 WRITE 0x11 陀螺歸零 / zero all four headings (zeroHeadings()); EV3 also accepts the stock gyro-reset WRITE 0x11 E1 accelCalStart: 開始加速度計校準(= v1 的 0x20=0x01);期間 F3 b4 = 1;磁力計校準中 → 忽略(0B 狀態 3 拒絕) / start accelerometer calibration (= v1 0x20=0x01); F3 b4 = 1 meanwhile; ignored during magnetometer calibration (0B state 3 rejected); busy F3 bit4 E2 accelCalEnd: 結束加速度計校準並存 EEPROM(= v1 的 0x20=0x02);通過後重新擷取安裝軸,擺正靜置後才航向歸零(不是馬上歸零);沒在校準中 → 拒絕(0B 狀態 3);驗證沒過 → 0B 狀態 2 失敗 / finish accelerometer calibration and save to EEPROM (= v1 0x20=0x02); on success the mount axis is re-captured and headings are zeroed once the sensor is level and still (not immediately); rejected if not calibrating (0B state 3); failed check → 0B state 2 E3 magCalStart: 開始磁力計校準(= v1 的 0x20=0x03);期間 F3 b5 = 1;磁力計故障時 → 忽略(0B 狀態 3) / start magnetometer calibration (= v1 0x20=0x03); F3 b5 = 1 meanwhile; ignored if the magnetometer has failed (0B state 3); busy F3 bit5 E4 magCalEnd: 結束磁力計校準並存 EEPROM(= v1 的 0x20=0x04);成功後馬上航向歸零;沒在校準中 → 拒絕(0B 狀態 3);驗證沒過 → 0B 狀態 2 失敗 / finish magnetometer calibration and save to EEPROM (= v1 0x20=0x04); headings zeroed right away on success; rejected if not calibrating (0B state 3); failed check → 0B state 2 E5 setHeading: [角度 int16 小端]:四個航向都設成這個角度(RAM);校準中不能做 → 拒絕(0B 狀態 3) / [angle int16 little-endian]: all four headings set to this angle (RAM); rejected while calibrating (0B state 3); params angle int16 ° E6 zeroNorth: 陀螺航向設成目前的磁北方位 0~359,之後只扣整圈(顯示絕對方位);融合重新初始化約 3 秒內完成,逾時 = 失敗;校準中不能做 → 拒絕(0B 狀態 3) / gyro heading set to the current magnetic bearing 0~359, then only whole turns are removed (absolute bearing); fusion re-init within ~3 s, timeout = failed; rejected while calibrating (0B state 3) E7 gyroBiasReset: 靜止約 1.5 秒(連續 3 個靜止窗)重新估計陀螺零點;4 秒內被移動湊不滿 = 失敗;校準中不能做 → 拒絕(0B 狀態 3) / re-estimates the gyro bias over ~1.5 s of stillness (3 still windows); moved and not done within 4 s = failed; rejected while calibrating (0B state 3) E8 recaptureAxis: 重新判定安裝方向(擷取後自動歸零);RAM;校準中不能做 → 拒絕(0B 狀態 3) / re-detects the mounting orientation (headings zeroed after capture); RAM; rejected while calibrating (0B state 3) E9 cancelCalib: 取消進行中的加速度計/磁力計校準,不存檔、還原舊值 / cancels the running accelerometer / magnetometer calibration without saving (old values restored) EA headingCorrection: [uint16 小端] 轉一圈的實際度數 × 10(0.1 度/圈),3500~3700;0 = 回 360.0。存 EEPROM 0x60(停 3 秒才寫,值沒變不寫),改完航向歸零;少參數或範圍外 → 0B 狀態 2(SPIKE 也回 2) / [uint16 little-endian] actual degrees per turn × 10 (0.1°/turn), 3500~3700; 0 = back to 360.0. Saved to EEPROM 0x60 (written after 3 s, skipped if unchanged), headings zeroed afterwards; missing or out of range → 0B state 2 (SPIKE also 2); params 0.1°/turn 0, 3500~3700 EB calibFactoryReset: [A5]:加速度計、磁力計校準與航向修正係數都回出廠值,馬上存 EEPROM;確認碼不對 → 0B 狀態 2;校準中 → 拒絕(3) / [A5]: accelerometer, magnetometer calibration and heading correction back to factory values, saved immediately; wrong magic → 0B state 2; rejected while calibrating (3); params magic 0xA5 status F3: bit0 ready: 恆 1 / always 1 bit1 still: 1 = 感應器靜止中 / 1 = sensor is stationary bit2 axisCaptured: 1 = 已判定安裝方向(首次擷取後自動歸零一次) / 1 = mounting orientation determined (headings zeroed once after first capture) bit3 mountTilted: 1 = 安裝角度偏離太多 / 1 = mounted too far from level bit4 accelCalibrating: E1 之後、E2 之前 = 1 / 1 between E1 and E2 bit5 magCalibrating: E3 之後、E4 之前 = 1 / 1 between E3 and E4 bit6 fusionInit: 1 = 融合航向可用 / 1 = fused heading is valid bit7 magAutoCalDone: 1 = 磁力計自動校準偏移已收斂 / 1 = magnetometer auto-calibration offsets have converged assumptions: - hw0 = 1(共識 #6);EV3 模式 4 = [0x6A | 1<<8, 韌體主×100+次, 0, 0](格式 B 再補 2 個 0),模式 5 改送俯仰角速度(取代 #65 放的 ID)。 - EV3 鎖住模式 0/1/3 照盤點程式碼:0 = 陀螺 3D、1 = 融合航向、3 = [陀螺 1D, 磁力航向](INO:213 註解寫反,以程式為準)。 - 0x22 照 R4 版(出貨版)鎖住:命令 4~9 = 三個航向 +32768 的「低 byte 在前、高 byte 在後」;盤點檔分析的是主韌體(高在前),主韌體 #67 改成跟 R4 版逐 byte 相同。命令 10~12 = 0;0x01、0x0A、0x0F、F1~F4 都觸發航向歸零(刻意,不動)。 - B-13:E1~E4 加速度計/磁力計校準開始/結束補回(v1 的 0x20 = 01/02/03/04),I2C 定案 §3 只列 E0。busyFlag:E1 → b4、E3 → b5。 - 俯仰角範圍定案沒寫(韌體尚無現成值,#67 用 atan2 新算),range 先填「°」不給 min/max,韌體做好後再補。 - 磁力信任度 08 = round(trust×255),磁場干擾度 09 = round(disturbance×100) 上限 255,朝上的面 0A = 軸號 + 3×負向:公式照盤點 I2C v1 0x34~0x36。 - 角速度 10~12 = round(dps×SIGN×10)、加速度 13~15 = mm/s²×1000/9806.65、磁力 16~18 = raw×SIGN×4/15:公式照盤點 I2C v1 0x22~0x24;mBlock 一併有(I2C 定案 §4 共用值表)。 - 主對話 2026-10-22:06 俯仰角範圍 −90~+90、07 = gyro X(照字面),取自 F5 韌體實作。 ## 循行者 16 路 / Line Follower 16-ch (id line16, I2C 0x16, hw0 16, model LINE16) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 linePos: 線位置 / line position; range -16~+16; 線在哪一路:−16(最左)~+16(最右),0 = 正中間;站在車後往前看,負 = 線在左(平常 ±15,±16 只在最外側掉線後 200 ms 內) / which channel the line is under: −16 (far left) to +16 (far right), 0 = centre; seen from behind the robot, negative = left (normally ±15; ±16 only for 200 ms after the line leaves the outermost channel); EV3 mode0[0]; SPIKE mode0 b1-16,mode0 b0-16,mode1 b0-16,mode5 v0,mode9 v4lo-16; MATRIX 0x22 cmd4-16 02 linePosFine: 細位置 / fine position; range -100~+100; 線位置的細分:−100 ~ +100,0 = 正中間,負 = 線在左(與線位置同號) / sub-channel position: −100 to +100, 0 = centre, negative = left (same sign as line position); EV3 mode2[0],mode4[0]; SPIKE mode0 b2-100,mode0 b2-100,mode3 b0-100,mode4 v0-100,mode7 v0,mode9 v5lo-100; MATRIX 0x22 cmd6-100 03 lineWidth: 線寬 / line width; range 0~16 路; 壓到線的路數 0~16,0 = 找不到線 / number of channels on the line, 0~16; 0 = no line; EV3 mode2[1],mode4[1]; SPIKE mode0 b0,mode0 b1,mode2 b0,mode3 b1,mode9 v4hi; MATRIX 0x22 cmd5 04 groupCount: 線段數 / line segments; range 0~8; 看到幾段線:0 丟線、1 一條線、2 以上 = 分岔/十字 / number of separate line segments: 0 = lost, 1 = one line, ≥2 = fork / crossing; SPIKE mode9 v5hi 05 bitmap: 壓線位元圖 / line bitmap; range 0~65535 bit; bit0 = 第 1 路(最左)… bit15 = 第 16 路,1 = 那一路在線上 / bit0 = channel 1 (left) … bit15 = channel 16; 1 = that channel sees the line; EV3 mode3[0]; SPIKE mode4 v1,mode9 v6 06 lastDir: 最後離線方向 / last exit direction; range -16~+16; 丟線前線最後在哪一側:−16 ~ +16(負 = 左),找回線後維持最後一次 / where the line was before it was lost: −16 to +16 (negative = left); keeps the last value 07 threshold: 二值化門檻 / threshold; range 1~99; 判斷「在線上」的光值門檻 1~99,預設 40(2026-11-03 以前出貨的韌體是 50);用 E4 改 / reflect threshold for 'on line', 1~99, default 40 (firmware shipped before 2026-11-03: 50); set with E4 08 calibCount: 校準完成次數 / calibrations done; range 0~255 次; 開機後完成校準的次數(按鈕校準也算) / number of calibrations completed since power-on (button calibrations included) 10~1F light: 第 1~16 路光值 / channel 1~16 reflect; range 0~100; 第 1~16 路校準後光值 0~100(第 1 路最左);編號 10~1F / calibrated reflect of channel 1~16, 0~100 (channel 1 = left); ids 10~1F; EV3 mode1[0],mode2[2],mode4[2]; SPIKE mode0 b4,mode0 b4,mode3 b2,mode6 v0,mode8 v0,mode9 v0; MATRIX 0x22 cmd7 commands: E0 blackLine: 追黑線(預設);存 RAM,重開機回預設 / follow a black line (default); RAM only, back to the default after reset E1 whiteLine: 追白線(F3 b1 = 1);存 RAM,重開機回預設 / follow a white line (F3 b1 = 1); RAM only, back to the default after reset E2 calibBlack: 把目前讀值記為黑(感應器壓在黑線上),約 50 ms;寫入 EEPROM / store the current reading as black (sensor over the black line), ~50 ms; saved to EEPROM; busy F3 bit2 E3 calibWhite: 把目前讀值記為白(感應器壓在白底上),約 50 ms;寫入 EEPROM / store the current reading as white (sensor over the white surface), ~50 ms; saved to EEPROM; busy F3 bit2 E4 setThreshold: 二值化門檻 1~99(RAM,重開機回預設 40);SPIKE 參數超出範圍回失敗(狀態 2) / threshold 1~99 (RAM only, back to 40 after reboot); on SPIKE an out-of-range value returns failed (state 2); params threshold 1~99 E7 calibAuto: 5 秒內把感應器在黑線與白底上來回掃,取極值當黑白參考(共識 B-12,= v1 的 0x20=0x01);期間 F3 b2 = 1 / sweep the sensor across black line and white surface for 5 s; min/max become the references; F3 b2 = 1 meanwhile; busy F3 bit2 E9 reverse: [0 正常/1 左右反向]:感應器反裝時用,通道順序與線位置左右對調;校準值照實體通道存,切換不用重校;存 RAM,重開機回 0(舊 mBlock 沒有);SPIKE 參數超出範圍回失敗(狀態 2) / [0 normal / 1 mirrored]: for a sensor mounted backwards — channel order and line position are mirrored; calibration stays per physical channel; RAM only, 0 after reset (not in legacy mBlock); on SPIKE an out-of-range value returns failed (state 2); params mirrored 0~1 status F3: bit0 ready: 恆 1 / always 1 bit1 whiteMode: 1 = 正在追白線 / 1 = following a white line bit2 calibrating: E2/E3/E7 執行中;此時拒收新的校準命令 / E2/E3/E7 in progress; new calibration commands are ignored bit3 lost: 線段數 = 0 / segment count = 0 bit4 fork: 線段數 ≥ 2 / segment count ≥ 2 bit5 reversed: E9 = 1(感應器反裝,左右對調) / E9 = 1 (sensor mounted backwards, left/right mirrored) assumptions: - B-11:細位置 02 與線位置 01 同號(負 = 左);韌體 F16:1290 註解寫反,程式碼同號(IR:11 為準)。 - B-12:E7 五秒動態校準補回(v1 的 0x20=0x01),定案表沒列。 - EV3:模式 0~2 鎖住;模式 3 原本不送 → 16 bit 位元圖;模式 4 原本不送 → 同模式 2;模式 5 ID 格式 B(共用函式)。 - SPIKE:0/5/7/9 鎖住,1~4、6 維持不動;教育版模式 0 的 16 路光值是 2-bit(玩具版 1-bit),跟 8 路的 4-bit 不同;byte 8~15 補 0(#65 已改,使用者保留);模式 9 排法照盤點(四路 4-bit 一個 int16,v6 = 位元圖);模式 8 v[0] 改 ID|hw[0]<<8。 - 線段數 04 範圍:定案沒寫,16 路最多 8 段(交錯壓線),採 0~8。 - mBlock 舊版:MBC_MBLOCK_LEGACY=1 時逐 byte 同 2026-10-21 統一後韌體(0x01 位置、0x02 線寬、n<<4|03 反向兩路壓一 byte、0x07 細位置 0~200),0x0B 回 1(B-1)。 - Flash:C031 硬體鎖 28 KB,I2C 版餘 848 B;不夠時照 B-17 順序瘦身,JSON 不受影響。 ## 循行者 8 路 / Line Follower 8-ch (id line8, I2C 0x16, hw0 8, model LINE8) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 linePos: 線位置 / line position; range -8~+8; 線在哪一路:−8(最左)~+8(最右),0 = 正中間;站在車後往前看,負 = 線在左 / which channel the line is under: −8 (far left) to +8 (far right), 0 = centre; seen from behind the robot, negative = left; EV3 mode0[0]; SPIKE mode0 b1-8,mode0 b0-8,mode1 b0-8,mode5 v0,mode9 v4lo-8; MATRIX 0x22 cmd4-8 02 linePosFine: 細位置 / fine position; range -100~+100; 線位置的細分:−100 ~ +100,0 = 正中間,負 = 線在左(與線位置同號) / sub-channel position: −100 to +100, 0 = centre, negative = left (same sign as line position); EV3 mode2[0]; SPIKE mode0 b2-100,mode3 b0-100,mode4 v0-100,mode7 v0,mode9 v5lo-100; MATRIX 0x22 cmd6-100 03 lineWidth: 線寬 / line width; range 0~8 路; 壓到線的路數 0~8,0 = 找不到線 / number of channels on the line, 0~8; 0 = no line; EV3 mode2[1]; SPIKE mode0 b0,mode0 b1,mode2 b0,mode5 v0,mode7 v0,mode9 v4hi; MATRIX 0x22 cmd5 04 groupCount: 線段數 / line segments; range 0~4; 看到幾段線:0 丟線、1 一條線、2 以上 = 分岔/十字 / number of separate line segments: 0 = lost, 1 = one line, ≥2 = fork / crossing; SPIKE mode9 v5hi 05 bitmap: 壓線位元圖 / line bitmap; range 0~255 bit; bit0 = 第 1 路(最左)… bit7 = 第 8 路,1 = 那一路在線上 / bit0 = channel 1 (left) … bit7 = channel 8; 1 = that channel sees the line; EV3 mode3[0]; SPIKE mode4 v1,mode9 v6lo 06 lastDir: 最後離線方向 / last exit direction; range -8~+8; 丟線前線最後在哪一側:−8 ~ +8(負 = 左),找回線後維持最後一次 / where the line was before it was lost: −8 to +8 (negative = left); keeps the last value 07 threshold: 二值化門檻 / threshold; range 1~99; 判斷「在線上」的光值門檻 1~99,預設 50;用 E4 改 / reflect threshold for 'on line', 1~99, default 50; set with E4 08 calibCount: 校準完成次數 / calibrations done; range 0~255 次; 開機後完成校準的次數(按鈕校準也算) / number of calibrations completed since power-on (button calibrations included) 10~17 light: 第 1~8 路光值 / channel 1~8 reflect; range 0~100; 第 1~8 路校準後光值 0~100(第 1 路最左);編號 10~17 / calibrated reflect of channel 1~8, 0~100 (channel 1 = left); ids 10~17; EV3 mode1[0]; SPIKE mode0 b4,mode9 v0; MATRIX 0x22 cmd7 commands: E0 blackLine: 追黑線(預設);存 RAM,重開機回預設 / follow a black line (default); RAM only, back to the default after reset E1 whiteLine: 追白線(F3 b1 = 1);存 RAM,重開機回預設 / follow a white line (F3 b1 = 1); RAM only, back to the default after reset E2 calibBlack: 把目前讀值記為黑(感應器壓在黑線上),約 50 ms;寫入 EEPROM / store the current reading as black (sensor over the black line), ~50 ms; saved to EEPROM; busy F3 bit2 E3 calibWhite: 把目前讀值記為白(感應器壓在白底上),約 50 ms;寫入 EEPROM / store the current reading as white (sensor over the white surface), ~50 ms; saved to EEPROM; busy F3 bit2 E4 setThreshold: 二值化門檻 1~99(RAM,重開機回預設 50);SPIKE 參數超出範圍回失敗(狀態 2) / threshold 1~99 (RAM only, back to 50 after reboot); on SPIKE an out-of-range value returns failed (state 2); params threshold 1~99 E7 calibAuto: 5 秒內把感應器在黑線與白底上來回掃,取極值當黑白參考(共識 B-12,= v1 的 0x20=0x01);期間 F3 b2 = 1 / sweep the sensor across black line and white surface for 5 s; min/max become the references; F3 b2 = 1 meanwhile; busy F3 bit2 E9 reverse: [0 正常/1 左右反向]:感應器反裝時用,通道順序與線位置左右對調;校準值照實體通道存,切換不用重校;存 RAM,重開機回 0(舊 mBlock 沒有);SPIKE 參數超出範圍回失敗(狀態 2) / [0 normal / 1 mirrored]: for a sensor mounted backwards — channel order and line position are mirrored; calibration stays per physical channel; RAM only, 0 after reset (not in legacy mBlock); on SPIKE an out-of-range value returns failed (state 2); params mirrored 0~1 status F3: bit0 ready: 恆 1 / always 1 bit1 whiteMode: 1 = 正在追白線 / 1 = following a white line bit2 calibrating: E2/E3/E7 執行中;此時拒收新的校準命令 / E2/E3/E7 in progress; new calibration commands are ignored bit3 lost: 線段數 = 0 / segment count = 0 bit4 fork: 線段數 ≥ 2 / segment count ≥ 2 bit5 reversed: E9 = 1(感應器反裝,左右對調) / E9 = 1 (sensor mounted backwards, left/right mirrored) assumptions: - B-11:細位置 02 與線位置 01 同號(負 = 左);v1 韌體註解寫反,程式碼同號。 - B-12:E7 五秒動態校準補回(v1 的 0x20=0x01),定案表沒列。 - SPIKE 教育版模式 0 的 byte 8~15 補 0(#65 已改,使用者保留)。 - EV3 模式 4 與模式 2 相同內容;模式 3 改壓線位元圖(#67)。 - mBlock 舊版:MBC_MBLOCK_LEGACY=1 時逐 byte 同 2026-10-21 統一後韌體,0x0B 回 1。 ## 掌控者 PS2 / PS2 Gamepad Receiver (id ps2, I2C 0x42, hw0 1, model PS2) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 buttons16: 十六鍵 / 16 buttons; range 0~65535 bit; 16 個按鍵合成一個數(PSX 排列,1 = 按下):bit0 SELECT、1 L3、2 R3、3 START、4 上、5 右、6 下、7 左、8 L2、9 R2、10 L1、11 R1、12 ▲、13 ●、14 ✕、15 ■;未連線 = 0 / all 16 buttons in one word (PSX order, 1 = pressed): bit0 SELECT, 1 L3, 2 R3, 3 START, 4 Up, 5 Right, 6 Down, 7 Left, 8 L2, 9 R2, 10 L1, 11 R1, 12 Triangle, 13 Circle, 14 Cross, 15 Square; 0 when not connected; SPIKE mode0 b6,mode5 v0,mode6 v2,mode9 v6 02 dpad: 方向鍵 / d-pad; range 0~15 bit; 上 1、右 2、下 4、左 8(同時按相加),0~15;未連線 = 0 / Up 1, Right 2, Down 4, Left 8 (added when pressed together), 0~15; 0 when not connected; EV3 mode0[0],mode1[0],mode3[0],mode4[0]; SPIKE mode0 b1,mode0 b0,mode1 b0,mode6 v0lo,mode9 v0; MATRIX 0x22 cmd4 03 shape: 形狀鍵 / shape buttons; range 0~15 bit; ▲ 1、● 2、✕ 4、■ 8(同時按相加),0~15;未連線 = 0;0x22 的 R 高 4 bit / Triangle 1, Circle 2, Cross 4, Square 8 (added when pressed together), 0~15; 0 when not connected; high nibble of 0x22 'R'; EV3 mode1[2],mode3[0],mode4[2]; SPIKE mode0 b1,mode0 b0,mode1 b0,mode6 v0hi,mode9 v0 04 shoulder: 肩鍵 / shoulder buttons; range 0~15 bit; L2 1、R2 2、L1 4、R1 8(同時按相加),0~15;未連線 = 0 / L2 1, R2 2, L1 4, R1 8 (added when pressed together), 0~15; 0 when not connected; EV3 mode1[4]; SPIKE mode0 b0,mode2 b0,mode6 v1lo,mode9 v1,mode0 b6,mode0 b1; MATRIX 0x22 cmd5 05 func: 功能鍵 / function buttons; range 0~15 bit; SELECT 1、L3 2、R3 4、START 8(同時按相加),0~15;未連線 = 0;0x22 的 G 高 4 bit / SELECT 1, L3 2, R3 4, START 8 (added when pressed together), 0~15; 0 when not connected; high nibble of 0x22 'G'; EV3 mode1[6]; SPIKE mode0 b0,mode2 b0,mode6 v1hi,mode9 v1,mode0 b6,mode0 b1 06 connected: 已連線 / connected; range 0~1; 1 = 手把已連線(psx.read() 成功),0 = 沒有;未連線時所有按鍵 0、搖桿回中 / 1 = gamepad connected (psx.read() succeeds), 0 = not; while disconnected all buttons read 0 and sticks are centred; EV3 mode3[0]; SPIKE mode3 b0; MATRIX 0x22 cmd10 07 battery: 電量 / battery; range 0 %; 0~100;PS2 手把沒有電量 → 恆 0(PS4 才有) / 0~100; PS2 pads report no battery → always 0 (PS4 only); SPIKE mode3 b1 08 l2Analog: L2 類比 / L2 analog; range 0~255; L2 壓力 0~255(DualShock 2 類比模式才有壓力值;手把沒有壓力值時按下 = 255、放開 = 0);未連線 = 0 / L2 pressure 0~255 (only DualShock 2 in analog mode reports pressure; otherwise pressed = 255, released = 0); 0 when not connected 09 r2Analog: R2 類比 / R2 analog; range 0~255; R2 壓力 0~255(同 08);未連線 = 0 / R2 pressure 0~255 (same rule as 08); 0 when not connected 0A sysKeys: 系統鍵 / system keys; range 0 bit; b0 PS 鍵、b1 擷取鍵;PS2 手把沒有 → 恆 0(PS4 才有) / b0 PS button, b1 capture button; PS2 pads have none → always 0 (PS4 only) 0B padType: 手把類型 / gamepad type; range 0~2; 0 沒有手把、1 PS2 數位模式、2 PS2 類比模式(3 PS4、4 PS5 只有 PS4 接收器會出現) / 0 none, 1 PS2 digital mode, 2 PS2 analog mode (3 PS4 / 4 PS5 only appear on the PS4 receiver) 10~13 stick: 搖桿 LX/LY/RX/RY / stick LX / LY / RX / RY; range -100~+100; 10 LX、11 LY、12 RX、13 RY:−100 ~ +100,0 = 中間,右/上為正(原始 0~255 死區 ±7 吸成中心);未連線 = 0。EV3/SPIKE/MATRIX 送的是 0~99(50 = 中間)或 1~9(5 = 中間),見各平台欄 / 10 LX, 11 LY, 12 RX, 13 RY: −100 to +100, 0 = centre, right / up positive (raw 0~255 with ±7 dead zone); 0 when not connected. EV3 / SPIKE / MATRIX carry 0~99 (50 = centre) or 1~9 (5 = centre), see each platform; EV3 mode1[1],mode2[0],mode4[1]; SPIKE mode0 b2,mode0 b2,mode4 v0,mode7 v2,mode9 v2; MATRIX 0x22 cmd6 commands: E5 vibrate: [強度 0~255],0 = 停;PS2 接收器收到後回 ACK 但忽略(250614 已關手把震動),PS4 才有作用 / [strength 0~255], 0 = stop; the PS2 receiver ACKs and ignores it (pad rumble disabled since 250614), effective on PS4 only; params strength 0~255 E6 setLed: [R][G][B] 各 0~255;PS2 手把沒有燈條,接收器收到後回 ACK 但忽略,PS4 才有作用 / [R][G][B] 0~255 each; PS2 pads have no light bar, the receiver ACKs and ignores it, effective on PS4 only; params red 0~255, green 0~255, blue 0~255 status F3: bit0 ready: 恆 1 / always 1 bit1 connected: = 06 已連線 / same as value 06 assumptions: - hw[0] = 1(PS2)、電量 07 恆 0、系統鍵 0A 恆 0、手把類型 0B 只會出現 0/1/2(I2C 定案 §2、§4)。 - 08/09 L2/R2 類比照定案寫 0~255:DS2 類比模式有壓力值;沒有壓力值時按下 = 255、放開 = 0(沿用 v1 0x14 的做法,盤點 .ino:598-603)。 - E5 震動、E6 燈條照 I2C 定案 §3 列在 PS2/PS4 共用命令表;PS2 收到回 ACK 後忽略(跟 v1 0x10/0x23 一樣)。 - 搖桿 10~13 在 I2C/mBlock 是 ±100(由 raw (v−128)×100/128、Y 上為正);EV3/0x22 維持 0~99(50 中間)、SPIKE 維持 1~9(5 中間)照盤點,不改鎖住模式。 - EV3:模式 0、1、2、4 鎖住(照盤點);模式 3 改 方向|形狀<<4|已連線<<8(原本沒有 bit8);模式 5 改成 ID 格式 B(原本 = 按鍵/搖桿合併版)。 - SPIKE:0/5/7/9 鎖住,1、2、4、6 維持不動;模式 3 改 [已連線, 電量(0), 0](原本 = 4 組按鍵);模式 8 改 v[0] = ID|hw[0]<<8(原本 = 搖桿)。模式 9 v[6] button16 = PSX 排列(D3)。 - SPIKE 模式 5 只容得下 11 鍵(L2、R2、L3、R3、START 讀不到),鎖住不改。 ## 掌控者 PS4/PS5 接收器 / Gamepad Receiver PS4/PS5 (id ps4, I2C 0x42, hw0 2, model PS4) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 buttons16: 十六鍵 / 16 buttons; range 0~65535 bit; 全部按鍵一個 16 bit(PSX 排列):bit0 SELECT(SHARE)、1 L3、2 R3、3 START(OPTIONS)、4 上、5 右、6 下、7 左、8 L2、9 R2、10 L1、11 R1、12 ▲、13 ●、14 ✕、15 ■;1 = 按下;未連線 = 0 / all buttons in one 16-bit word (PSX layout): bit0 SELECT(SHARE), 1 L3, 2 R3, 3 START(OPTIONS), 4 up, 5 right, 6 down, 7 left, 8 L2, 9 R2, 10 L1, 11 R1, 12 triangle, 13 circle, 14 cross, 15 square; 1 = pressed; 0 when not connected; SPIKE mode5 v0,mode0 b6,mode6 v2,mode9 v6 02 dpad: 方向鍵 / D-pad; range 0~15 bit; 上 1、右 2、下 4、左 8,同時按相加(0~15) / up 1, right 2, down 4, left 8, added when pressed together (0~15); EV3 mode0[0],mode1[0],mode3[0],mode4[0]; SPIKE mode0 b1,mode0 b0,mode1 b0,mode6 v0lo,mode7 v0lo,mode9 v0lo; MATRIX 0x22 cmd4 03 shapeKeys: 形狀鍵 / shape buttons; range 0~15 bit; ▲ 1、● 2、✕ 4、■ 8,同時按相加(0~15) / triangle 1, circle 2, cross 4, square 8, added when pressed together (0~15); EV3 mode1[2],mode3[0],mode4[2]; SPIKE mode0 b1,mode0 b0,mode1 b0,mode6 v0hi,mode7 v0hi,mode9 v0lo 04 shoulderKeys: 肩鍵 / shoulder buttons; range 0~15 bit; L2 1、R2 2、L1 4、R1 8,同時按相加(0~15) / L2 1, R2 2, L1 4, R1 8, added when pressed together (0~15); EV3 mode1[4]; SPIKE mode0 b0,mode2 b0,mode6 v1lo,mode7 v1lo,mode9 v1lo,mode0 b6,mode0 b1; MATRIX 0x22 cmd5 05 funcKeys: 功能鍵 / function buttons; range 0~15 bit; SELECT(SHARE) 1、L3 2、R3 4、START(OPTIONS) 8,同時按相加(0~15) / SELECT(SHARE) 1, L3 2, R3 4, START(OPTIONS) 8, added when pressed together (0~15); EV3 mode1[6]; SPIKE mode0 b0,mode0 b1,mode2 b0,mode6 v1hi,mode7 v1hi,mode9 v1lo,mode0 b6 06 connected: 已連線 / connected; range 0~1; 1 = 手把已連線且 300 ms 內有資料,0 = 未連線(斷線時按鍵 0、搖桿中間) / 1 = gamepad connected and data seen within 300 ms, 0 = not connected (buttons 0, sticks centred while disconnected); EV3 mode3[0]; SPIKE mode3 b0; MATRIX 0x22 cmd10 07 battery: 電量 / battery; range 0~100 %; 手把電量 0~100(PS2 接收器恆 0) / gamepad battery 0~100 (always 0 on the PS2 receiver); SPIKE mode3 b1 08 l2Analog: L2 類比 / L2 analog; range 0~255; L2 扳機壓多深 0~255(未連線 0) / L2 trigger depth 0~255 (0 when not connected) 09 r2Analog: R2 類比 / R2 analog; range 0~255; R2 扳機壓多深 0~255(未連線 0) / R2 trigger depth 0~255 (0 when not connected) 0A sysKeys: 系統鍵 / system buttons; range 0~3 bit; b0 PS 鍵、b1 擷取(PS5 靜音)鍵;未連線 0(PS2 恆 0) / b0 PS button, b1 capture (PS5 mute) button; 0 when not connected (always 0 on PS2) 0B padType: 手把類型 / gamepad type; range 0~4; 0 無、1 PS2 數位、2 PS2 類比、3 PS4、4 PS5(或其他) / 0 none, 1 PS2 digital, 2 PS2 analog, 3 PS4, 4 PS5 (or other) 10~13 stick: 搖桿 1~4 軸 / stick axis 1~4; range -100~+100; 10 LX、11 LY、12 RX、13 RY:−100 ~ +100,0 = 中間,右/上為正;未連線 0 / 10 LX, 11 LY, 12 RX, 13 RY: −100 to +100, 0 = centre, right/up positive; 0 when not connected; EV3 mode1[1],mode2[0],mode4[1]; SPIKE mode0 b2,mode0 b2,mode4 v0,mode7 v2,mode9 v2; MATRIX 0x22 cmd6 commands: E5 rumble: [強度 0~255],0 = 停;每次 200 ms(PS2 收到忽略) / [strength 0~255], 0 = stop; 200 ms per call (ignored by PS2); params strength 0~255 E6 lightbar: [R][G][B] 各 0~255,要剛好 3 byte;未連線先記住,連上再套用;預設藍 (0,0,255)(PS2 收到忽略) / [R][G][B] each 0~255, exactly 3 bytes; remembered until connected; default blue (0,0,255) (ignored by PS2); params R 0~255, G 0~255, B 0~255 status F3: bit0 ready: 恆 1 / always 1 bit1 connected: = 值 06(linkActive) / same as value 06 (linkActive) assumptions: - 值表、命令、旗標與 PS2 完全相同(mBlock 定案「兩款相同」+I2C 定案 §3/§4);只有 hw0 = 2、model = PS4、E5/E6 有作用。 - D3:SPIKE 模式 0 教育版 byte 6~7、模式 6 v[2]、模式 9 v[6] 的 button16 都是 PSX 排列(#65 已把 PS4 改成 PSX,盤點檔寫的 Bluepad32 排列已過時)。 - 0x22 命令 4 同時裝方向鍵(低 nibble)與形狀鍵(高 nibble)、命令 5 裝肩鍵(低)與功能鍵(高);JSON 只能把一個命令掛在一個值上,所以掛在 02/04,03/05 的 ch22 = null(內容寫在 02/04 的 note)。SPIKE 模式 0/1/2/9 的 nibble 也用同樣方式在 note 說明。 - 搖桿:I2C/mBlock 送 ±100;EV3/0x22送 0~99(50 = 中間)、SPIKE 送 1~9(5 = 中間),不是線性 offset,主機端各自換算(網站範例已是這樣)。 - EV3 模式 3 = 方向鍵 | 形狀鍵<<4 | 已連線<<8(#67 新增 bit8);模式 4 內容不變([方向鍵, LX, 形狀鍵, LY]);模式 5 改送裝置 ID 格式 B [0x42 | 2<<8, 韌體版]。 - SPIKE 模式 3 改 [已連線, 電量, 0](3×int8)、模式 8 改 [0x42 | 2<<8, 協議版 2, 韌體版, 更新序號];其餘空模式 1、2、4、6 維持現狀。 - ESP32 從機不能時脈延展:I2C v2 在 onReceive 就預載從該編號起 32 B;0x22照 MATRIX 定案 §5 #2 預載最新一包,待上機。 - I2C 0A 系統鍵 b1 = 擷取鍵(v1 0x15 放在 b3,v2 改 b1,照 I2C 定案 §4)。 ## 測距者 2 路 / Laser Ranger 2-ch (id tof2, I2C 0x29, hw0 2, model LASER2) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 leftCm: 左距離 cm / left distance (cm); range 0~120 cm; 左邊那顆的距離 0~120 cm(站在車後往前看,左 = 第 0 顆),120 = 前面沒東西/那顆失效 / distance from the left sensor, 0~120 cm (left = sensor 0 seen from behind the robot); 120 = nothing in range / sensor failed; EV3 mode1[0],mode2[0],mode4[0]; SPIKE mode0 b0,mode0 b0,mode1 b0,mode2 b0,mode3 b0,mode4 v0lo,mode5 v0,mode8 v0lo,mode9 v0lo; MATRIX 0x22 cmd4 02 rightCm: 右距離 cm / right distance (cm); range 0~120 cm; 右邊那顆的距離 0~120 cm(右 = 第 1 顆),120 = 前面沒東西/那顆失效 / distance from the right sensor, 0~120 cm (right = sensor 1); 120 = nothing in range / sensor failed; EV3 mode1[1],mode2[1],mode4[1]; SPIKE mode0 b1,mode0 b1,mode3 b1,mode4 v0hi,mode7 v2,mode8 v0hi,mode9 v0hi; MATRIX 0x22 cmd5 03 nearCm: 較近距離 cm / nearer distance (cm); range 0~120 cm; 左右兩顆取較近的 0~120 cm / the smaller of left and right, 0~120 cm; MATRIX 0x22 cmd6 04 leftMm: 左距離 mm / left distance (mm); range 0~1200 mm; 左邊那顆的距離 0~1200 mm,1200 = 前面沒東西/那顆失效 / left sensor distance 0~1200 mm; 1200 = nothing in range / sensor failed; EV3 mode5[0]; SPIKE mode6 v0 05 rightMm: 右距離 mm / right distance (mm); range 0~1200 mm; 右邊那顆的距離 0~1200 mm,1200 = 前面沒東西/那顆失效 / right sensor distance 0~1200 mm; 1200 = nothing in range / sensor failed; EV3 mode5[1]; SPIKE mode6 v1 06 initOk: 初始化位元圖 / init bitmap; range 0~3 bit; bit0 = 左、bit1 = 右,1 = 那顆開機初始化成功(失敗不重試);3 = 兩顆都好 / bit0 = left, bit1 = right; 1 = that sensor initialised at power-on (no retry); 3 = both OK; SPIKE mode9 v1lo 07 fault: 故障位元圖 / fault bitmap; range 0~3 bit; bit0 = 左、bit1 = 右,1 = 那顆目前失效(I2C 讀失敗或 200 ms 沒更新);失效那顆距離回 120/1200 / bit0 = left, bit1 = right; 1 = that sensor is currently failing (I2C error or no update for 200 ms); its distance reads 120 / 1200; SPIKE mode9 v1hi 08 avgMm: 左右平均 mm / average distance (mm); range 0~1200 mm; (左 mm + 右 mm) / 2,0~1200;跟 EV3 模式 3、SPIKE 模式 6 第 3 個值一致(共識 #8 補上) / (left mm + right mm) / 2, 0~1200; same number as EV3 mode 3 and the 3rd value of SPIKE mode 6; EV3 mode0[0],mode3[0]; SPIKE mode0 b7,mode6 v2 status F3: bit0 ready: 2 顆都初始化完、快照開始更新後恆 1 / 1 once both sensors are initialised and snapshots are running bit1 fault: 初始化失敗、I2C 讀失敗或 200 ms 沒更新,任一顆就是 1(= 07 ≠ 0 或 06 ≠ 3) / 1 if any sensor failed to initialise, has an I2C error or no update for 200 ms (07 ≠ 0 or 06 ≠ 3) assumptions: - 共識 #8:08 左右平均 mm 補進 I2C/mBlock 值表(定案 §5 已列)。 - 0x22 命令 4~12 不動(4 左、5 右、6 最近、7~11 = 0、12 = 最近);schema 不收 11/12,所以 12 只寫在 03 的 note。 - EV3:模式 0、2、4 鎖住(照盤點);模式 1 改 [左,右]×4(index 0/1 各代表左右)、模式 3 改平均 mm、模式 5 改 [左 mm, 右 mm];模式 1 描述表宣告 int8 −100~100,cm×100/120 在範圍內。 - SPIKE:0/5/7/9 鎖住,另加模式 3 鎖住(網站 sensors/tof2/index.md read(3) = 左/右 cm,共識 #11);模式 6 改 [左 mm, 右 mm, 平均 mm];模式 1、2、4、8 維持不動;模式 8 v[0] 改 ID|hw[0]<<8(統一後共用函式)。 - 「左」= 站在車後往前看的左(第 0 顆,XSHUT PA6);韌體只有 L/R 巨集名,盤點檔標為推測。 - 沒有寫入命令;F8 換位址/EF 重開機用共用的。 ## 測距者 8 路 / Laser Ranger 8-ch (id tof8, I2C 0x29, hw0 8, model LASER8) hosts: ev3, spike, i2c, mblock, matrix, microbit values: 01 nearCm: 最近距離 cm / nearest distance (cm); range 0~120 cm; 8 顆裡最小的距離 0~120 cm(失效那顆以 120 參與),120 = 四周沒東西 / smallest of the 8 distances, 0~120 cm (a failed sensor counts as 120); 120 = nothing around; EV3 mode2[1]; SPIKE mode2 b0,mode3 b1,mode4 v0hi,mode7 v2,mode9 v4hi 02 nearDir: 最近方向 / nearest direction; range -8~+8; 最近目標在哪個方向:−7(正左)~ +7(正右),0 = 正前方,負 = 左;±8 = 四周沒東西(沿用上次偏向側) / direction of the nearest object: −7 (left) to +7 (right), 0 = straight ahead, negative = left; ±8 = nothing around (keeps the last side); EV3 mode2[0],mode5[1]; SPIKE mode1 b0-8,mode3 b0-8,mode4 v0lo-8,mode5 v0,mode6 v2,mode9 v4lo-8 03 farCm: 最空曠距離 cm / farthest distance (cm); range 0~120 cm; 8 顆裡最大的距離 0~120 cm(壞掉那顆永遠 120,會被當成最空曠) / largest of the 8 distances, 0~120 cm (a failed sensor always reads 120 and looks 'farthest'); EV3 mode2[3]; SPIKE mode9 v5hi 04 farDir: 最空曠方向 / farthest direction; range -7~+7; 最遠(最空曠)在哪個方向:−7 ~ +7,0 = 正前方,負 = 左;8 顆全 120 時 = 0 / direction of the most open side: −7 to +7, 0 = straight ahead, negative = left; 0 when all 8 read 120; EV3 mode2[2]; SPIKE mode9 v5lo-8 05 frontCm: 正前方 cm / front distance (cm); range 0~120 cm; 第 4、5 顆(兩顆平行朝前)平均 0~120 cm;EV3 模式 3、SPIKE 模式 6 給的是同一個值的 mm;0x22 的 C 是 min(第 4, 第 5 顆) 不是平均(見 10) / average of sensors 4 and 5 (both facing forward), 0~120 cm; EV3 mode 3 and SPIKE mode 6 carry the same thing in mm; 0x22 'C' is min(4, 5), not the average (see 10); EV3 mode0[0] 06 nearMm: 最近距離 mm / nearest distance (mm); range 0~1200 mm; 8 顆 mm 的最小值 0~1200(失效那顆以 1200 參與),1200 = 四周沒東西 / smallest of the 8 mm readings, 0~1200 (failed sensor counts as 1200); 1200 = nothing around; EV3 mode5[0]; SPIKE mode6 v0 07 initOk: 初始化位元圖 / init bitmap; range 0~255 bit; bit0 = 第 1 顆(最左)… bit7 = 第 8 顆,1 = 那顆開機初始化成功(8 顆約 2~4 秒,失敗不重試);255 = 全部好 / bit0 = sensor 1 (left) … bit7 = sensor 8; 1 = initialised at power-on (8 sensors take ~2~4 s, no retry); 255 = all OK; SPIKE mode9 v6lo 08 fault: 故障位元圖 / fault bitmap; range 0~255 bit; bit0 = 第 1 顆 … bit7 = 第 8 顆,1 = 那顆目前失效(I2C 讀失敗或 200 ms 沒更新);失效那顆距離回 120/1200 / bit0 = sensor 1 … bit7 = sensor 8; 1 = currently failing (I2C error or no update for 200 ms); its distance reads 120 / 1200; SPIKE mode9 v6hi 09 frontMm: 正前方距離 mm / front distance (mm); range 0~1200 mm; 第 4、5 顆(正前方兩顆)平均,0~1200 mm;1200 = 前面沒東西。cm 版是 05 / average of sensors 4 and 5 (the two facing forward), 0~1200 mm; 1200 = nothing ahead. cm version is 05; EV3 mode3[0]; SPIKE mode6 v1 10~17 distCm: 第 1~8 顆距離 cm / sensor 1~8 distance (cm); range 0~120 cm; 第 1~8 顆各自的距離 0~120 cm(第 1 顆正左、第 4、5 顆正前、第 8 顆正右,每顆隔 30°);120 = 那個方向沒東西/那顆失效;編號 10~17 / distance of each sensor 1~8, 0~120 cm (1 = far left, 4 and 5 = front, 8 = far right, 30° apart); 120 = nothing that way / sensor failed; ids 10~17; EV3 mode1[0],mode4[0]; SPIKE mode0 b0,mode0 b0,mode3 b2,mode4 v1,mode8 v0,mode9 v0; MATRIX 0x22 cmd4 18~1F distMm: 第 1~8 顆距離 mm / sensor 1~8 distance (mm); range 0~1200 mm; 第 1~8 顆各自的距離 0~1200 mm,1200 = 那個方向沒東西/那顆失效;編號 18~1F / distance of each sensor 1~8, 0~1200 mm; 1200 = nothing that way / sensor failed; ids 18~1F status F3: bit0 ready: 8 顆都初始化完(開機約 2~4 秒)、快照開始更新後恆 1 / 1 once all 8 sensors are initialised (~2~4 s after power-on) and snapshots are running bit1 fault: 初始化失敗、I2C 讀失敗或 200 ms 沒更新,任一顆就是 1(= 08 ≠ 0 或 07 ≠ 255) / 1 if any sensor failed to initialise, has an I2C error or no update for 200 ms (08 ≠ 0 or 07 ≠ 255) assumptions: - 正前方 mm(EV3 模式 3、SPIKE 模式 6 v[1])在定案 §5 沒有獨立 I2C 編號 → 掛在 05 正前方 cm 底下,用 scale:mm 標示,不自己加編號。 - 0x22(使用者 2026-10-21 最終定案):只用一個位址,R~K 由左到右 7 個 cm:第 1、2、3 顆、min(第 4, 第 5)、第 6、7、8 顆;11、12 不放資料;最近距離/方向由主機自己比較。此排法只用在 0x22,EV3/SPIKE不動。 - SPIKE:0/5/7/9 鎖住,1、2、3、4、8 維持不動;模式 6 改 [最近 mm, 正前方 mm, 最近方向 −8~+8](原本 = 第 2~7 顆兩兩合併);模式 8 v[0] 改 ID|hw[0]<<8。 - 最空曠方向 04 範圍 −7~+7(maxDirection 永遠不會是 0/16,盤點 INO:1086-1088);最近方向 02 ±8 = 沒目標、沿用上次偏向側,開機預設 −8。 - 沒有寫入命令;F8 換位址/EF 重開機用共用的。 - 主對話 2026-10-21:補 09 正前方 mm(定案 §5 只有 05 正前方 cm,但 EV3 模式 3、SPIKE 模式 6 都送 mm,I2C/mBlock 應有同一個值)。