xiao-i2c-sensors
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseI2C sensors on the XIAO ESP32S3
XIAO ESP32S3上的I2C传感器
Bus pins are fixed by the board: SDA = D4 = GPIO5, SCL = D5 = GPIO6.
— the no-argument form picks the wrong pins.
Wire.begin(D4, D5)Read the skill for the compile/upload workflow, and
for watching the output.
xiao-esp32s3xiao-serial-monitor开发板的总线引脚是固定的:SDA = D4 = GPIO5,SCL = D5 = GPIO6。
—— 无参数形式会选择错误的引脚。
Wire.begin(D4, D5)编译/上传流程请参考技能,查看输出请参考技能。
xiao-esp32s3xiao-serial-monitorAlways scan before writing driver code
编写驱动代码前务必先扫描总线
Module silkscreens lie and address straps vary between clones. One scan
settles both, and everything downstream depends on being right about it:
powershell
arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3 -u -p <PORT> assets\sketches\i2c_scani2c_scan 0x23 BH1750 (ADDR=L)
0x29 BNO055 (ADDR=H)
0x76 BME280/BMP280 (SDO=L)
0x76 chip id = 0x60 -> BME280
0x29 chip id = 0xA0 -> BNO055模块丝印可能有误,不同克隆版的地址跳线也可能不同。一次扫描即可解决这两个问题,后续所有操作都依赖正确的地址:
powershell
arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3 -u -p <PORT> assets\sketches\i2c_scani2c_scan 0x23 BH1750 (ADDR=L)
0x29 BNO055 (ADDR=H)
0x76 BME280/BMP280 (SDO=L)
0x76 chip id = 0x60 -> BME280
0x29 chip id = 0xA0 -> BNO055Sketches
代码示例
| Sketch | What it does |
|---|---|
| scan + chip-ID identification |
| BH1750 unit test, 5 automated checks |
| BME280 unit test, 8 automated checks |
| BNO055 unit test, 10 automated checks |
| all three streaming together, 1 Hz |
Copy the one you need into the user's workspace (folder name must match the
name) rather than writing a driver from scratch. All five were run on
real hardware; the unit tests all pass at 5/5, 8/8, 10/10.
.inoLibraries:
powershell
arduino-cli lib install "BH1750"
arduino-cli lib install "Adafruit BME280 Library"
arduino-cli lib install "Adafruit BNO055"sensors_alllux 48.3 | 25.86C 1006.31hPa 42.7%RH | H 359.9 R 7.9 P -5.2 | cal 1300cal| 代码示例 | 功能 |
|---|---|
| 总线扫描 + 芯片ID识别 |
| BH1750单元测试,包含5项自动化检查 |
| BME280单元测试,包含8项自动化检查 |
| BNO055单元测试,包含10项自动化检查 |
| 同时流式传输三个传感器的数据,频率1Hz |
无需从零编写驱动,只需将所需的代码示例复制到用户工作区(文件夹名称必须与文件名一致)。这五个示例均在真实硬件上运行过,单元测试分别达到5/5、8/8、10/10的通过率。
.ino所需库:
powershell
arduino-cli lib install "BH1750"
arduino-cli lib install "Adafruit BME280 Library"
arduino-cli lib install "Adafruit BNO055"sensors_alllux 48.3 | 25.86C 1006.31hPa 42.7%RH | H 359.9 R 7.9 P -5.2 | cal 1300calHanding the stream to the user
将数据流交付给用户
A sensor stream is something the user watches, not something you screenshot
once. Verify it yourself with a bounded read, then tell them how to open it
themselves — the skill covers both halves:
xiao-serial-monitorpowershell
.\scripts\mon.ps1 -Seconds 15 # your check; returns
mon # theirs; runs until Ctrl+CNever launch the interactive monitor from a tool call — it never returns and
the session hangs. Close instead with a handoff that names the command, how to
run it, and how to stop it:
센서 값이 1초마다 흐르고 있습니다. 직접 보시려면:! D:\path\to\mon.ps1Claude Code에서를 붙이면 이 세션에서 바로 실행됩니다. Ctrl+C로 종료. 프로필 단축키를 넣으셨다면 새 터미널에서!만 쳐도 됩니다.mon
This matters more for sensors than for most things: the interesting part is
what happens when the user covers the light sensor, breathes on the humidity
sensor, or rotates the IMU. None of that shows up in a capture you took while
the board sat still on a desk.
传感器数据流需要用户实时查看,而不是仅截取一次截图。你可以先通过有限时长读取来验证,然后告诉用户如何自行打开数据流——技能涵盖了这两部分:
xiao-serial-monitorpowershell
.\scripts\mon.ps1 -Seconds 15 # 你的验证操作;执行后返回
mon # 用户的操作;运行直到按下Ctrl+C切勿通过工具调用启动交互式监视器——它不会返回,会话会挂起。应改为告知用户命令名称、运行方式和停止方式:
传感器数据正在每秒流式传输。如需查看,请执行:! D:\path\to\mon.ps1在Claude Code中添加即可在当前会话中直接运行。按下Ctrl+C可终止。 若已设置配置文件快捷方式,在新终端中输入!即可运行。mon
这一点对传感器而言尤为重要:有趣的部分是用户遮挡光传感器、对着湿度传感器呼气或旋转IMU时的变化。这些内容在开发板静置时的截图中是无法体现的。
How these unit tests are built
单元测试的构建规则
Two rules make the difference between a test that proves something and a test
that just prints numbers:
Bounds-check, don't eyeball. Every reading is asserted against the
datasheet range, because the failure that actually happens is a dead bus
returning , , or a pegged rail — not a part that is 2 % out of
calibration. The strongest single check in the set is the BNO055's gravity
magnitude: however the board is lying, must come out near 9.8 m/s², so
one assertion covers all three accelerometer axes and their scaling at once.
0NaN|g|Never assert something that needs a human hand. An early version of the
BH1750 test asserted that consecutive readings differ, reasoning that a frozen
bus repeats itself. Under steady room light a healthy sensor returns exactly
46.7 lx every time, so the test failed on working hardware whenever nobody
happened to be waving at it. Checks that need physical stimulus — covering the
light sensor, breathing on the humidity sensor, moving the IMU to calibrate —
belong in a printed "manual check" section that is not scored. Keep the
automated count honest and it stays worth reading.
以下两条规则区分了真正能验证功能的测试和仅打印数值的测试:
进行边界检查,而非目视判断。 每次读数都需根据数据手册的范围进行断言,因为实际出现的故障通常是总线失效返回、或固定值——而不是器件校准误差超出2%。这套测试中最有效的检查是BNO055的重力幅值:无论开发板如何放置,必须接近9.8 m/s²,因此一个断言即可同时覆盖三个加速度计轴及其缩放比例。
0NaN|g|切勿断言需要人工操作的内容。 BH1750测试的早期版本断言连续读数必须不同,理由是冻结的总线会重复返回相同值。但在稳定的室内光线条件下,正常的传感器每次都会返回精确的46.7 lx,因此当无人晃动传感器时,正常硬件上的测试会失败。需要物理刺激的检查——比如遮挡光传感器、对着湿度传感器呼气、移动IMU进行校准——应放在未计分的“手动检查”打印部分。保持自动化计数的准确性,才能让测试结果有参考价值。
Pitfalls
常见陷阱
These each cost a debugging session once.
-
A BNO055 at 0x29 will not talk to the default driver. The Adafruit library constructor defaults to 0x28; a module with ADDR/COM3 strapped high sits at 0x29 andfails while the scan shows the device plainly. Pass it explicitly:
begin()Adafruit_BNO055 bno(55, 0x29, &Wire); -
silently zeroes the BNO055. Many clone modules have no 32 kHz crystal fitted, and selecting an absent clock source parks the chip in idle with every output stuck at
setExtCrystalUse(true)— temperature, gravity, euler angles, all of it. The trap is that it still looks healthy: the power-on self test reports0.00and0x0Fstayssystem_error. Leave it on the internal oscillator unless you have confirmed the crystal exists.0Guard against it by checking the mode rather than the self test:cppuint8_t sysStat, selfTest, sysErr; bno.getSystemStatus(&sysStat, &selfTest, &sysErr); // 5 = sensor fusion algorithm running. Anything else and the // orientation numbers are not real, whatever self_test says. -
0x76 does not mean BME280. BMP280 shares the address and has no humidity channel, so a humidity read returns garbage rather than an error. Read chip-ID register:
0xD0= BME280,0x60= BMP280,0x58= BME680,0x61= BMP180. Decide the driver from that, not the module's label.0x55 -
BH1750 needs ~120 ms afterbefore the first conversion. Reading immediately returns a stale or zero value that looks like a wiring fault. The tests wait 200 ms.
begin() -
One missing module should not silence the others. Ineach sensor is probed independently and a missing one is reported once at startup, then skipped. A single loose wire otherwise takes the whole stream down and sends you looking for a software bug.
sensors_all -
Keep serial output ASCII. The Windows console reads the port as the ANSI codepage, so Korean or accented text incomes back as mojibake in captured logs. Put the explanation in comments, keep the printed strings English.
Serial.print
这些陷阱都曾花费过调试时间:
-
地址0x29的BNO055无法与默认驱动通信。 Adafruit库的构造函数默认地址为0x28;若模块的ADDR/COM3引脚接高电平,器件地址为0x29,此时会失败,但扫描结果会显示该器件存在。需显式传入地址:
begin()Adafruit_BNO055 bno(55, 0x29, &Wire); -
会使BNO055静默返回0。 许多克隆模块未安装32 kHz晶体,选择不存在的时钟源会使芯片进入空闲状态,所有输出(温度、重力、欧拉角等)都固定为
setExtCrystalUse(true)。陷阱在于芯片看起来仍正常:上电自检报告0.00,0x0F始终为system_error。除非确认晶体存在,否则应使用内部振荡器。0可通过检查模式而非自检结果来避免此问题:cppuint8_t sysStat, selfTest, sysErr; bno.getSystemStatus(&sysStat, &selfTest, &sysErr); // 5 = 传感器融合算法正在运行。任何其他值都意味着姿态数据无效,无论自检结果如何。 -
地址0x76并不代表是BME280。 BMP280共享该地址且无湿度通道,因此读取湿度会返回垃圾数据而非错误。读取芯片ID寄存器:
0xD0= BME280,0x60= BMP280,0x58= BME680,0x61= BMP180。应根据该值选择驱动,而非模块标签。0x55 -
BH1750在后需要约120 ms才能完成首次转换。 立即读取会返回过时或0值,看起来像是接线故障。测试中会等待200 ms。
begin() -
单个模块缺失不应导致其他模块无输出。 在中,每个传感器都会被独立探测,缺失的模块会在启动时报告一次,之后被跳过。否则,一根松动的线会导致整个数据流中断,让你误以为是软件bug。
sensors_all -
串口输出请使用ASCII编码。 Windows控制台以ANSI代码页读取端口,因此中的韩文或带重音的文本会在捕获的日志中显示为乱码。说明文字可放在注释中,打印字符串请使用英文。
Serial.print
Adding another I2C sensor
添加其他I2C传感器
Scan first and confirm the address; identify the part from its ID register
where one exists; bounds-check every reading against the datasheet; and keep
any check that needs a human hand out of the automated score. That is the
whole method — the five sketches here are just instances of it.
首先扫描并确认地址;若有ID寄存器,通过其识别器件;根据数据手册对每次读数进行边界检查;将需要人工操作的检查排除在自动化计分之外。这就是完整的方法——此处的五个代码示例只是该方法的具体实现。