这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » ESP32-S31Functioncoreboard-1测评]收官:多传感器集成

共1条 1/1 1 跳转至页

ESP32-S31Functioncoreboard-1测评]收官:多传感器集成系统

菜鸟
2026-10-05 19:44:31     打赏

这是本次测评的最后一篇。前两篇分别做了开箱环境搭建、以及硬件资源梳理和代码框架,这篇把采集端真正跑起来,并记录调试过程中遇到的几个问题。

IMG_20261005_181638.jpg

一、系统构成

1.1 传感器选型

模块测量对象接口地址/引脚
BH1750光照度I2C0x23
BMP280气压 / 温度 / 海拔I2C0x76
DHT22温度 / 湿度单总线GPIO4
MQ-2可燃气体ADCGPIO42
ST7789 屏本地显示SPIGPIO35~40

选型时特意让四路覆盖三种接口类型:I2C 是数字传感器最常见的接法,可以一条总线挂多个;单总线只有一根数据线,时序全靠软件配合;MQ-2 输出模拟量,走 ADC,能顺带验证一下 S31 的模拟前端。

1.2 接线

J2 排针上 3V3 只有两个、5V 只有两个,DHT22 和屏就把 3V3 用完了。所以把面包板当配电盘用:

板子 3V3 ──→ 上轨 +
板子 G   ──→ 上轨 −
          (跳线把上下两轨连起来)

面包板的上下两条电源轨是独立的,不加这两根跳线的话下半边没电,这是接的时候容易忽略的地方。

信号线没走面包板,直接用杜邦线连板子。少两个接触点,出问题好查。

需要注意的是线材数量。板子到面包板一共要连 7 条(3V3、G、5V、47、48、42、4),公对公的跳线很快就不够用了。后来的做法是:模块尽量直接插在面包板上,模块侧的连接就全是面包板内部的事;另外把 MQ-2 的 VCC 和 GND 改成从板子直连,腾出两根公对母给 BH1750 用。

1.3 MQ-2 的分压

MQ-2 加热丝要求 5V,AO 输出最高接近供电电压,直接进 ADC 会超量程,所以用两个电阻分压:

MQ-2 AO ──[R1]──┬── GPIO42
               │
             [R2]
               │
              GND

R1/R2 取 10k 和 20k,分压比 2/3,5V 进来是 3.33V。

IMG_20261005_180456.jpg


面包板上插这两个电阻有个讲究:电阻要横跨不同的列,但要共用中间那一列。因为面包板的孔是按列连通的(一列五个孔上下相通,列与列之间不通),R1 的右脚和 R2 的左脚落在同一列就自动接上了,不需要额外跳线。

两个容易出错的地方:电阻不能两只脚插同一列,那样会被列内连通短路掉;也不能跨中间那条凹槽,凹槽把面包板分成上下两组独立的孔,跨过去是不通的。

二、软件

代码按模块拆开:

文件内容
board_config.h所有引脚定义
i2c_bus.c/hI2C 初始化与地址扫描
bh1750 / bmp280 / dht22 / mq2各传感器驱动
st7789_disp.c/h显示屏,含 5x7 点阵字模
main.c采集调度、显示刷新

引脚集中在 board_config.h 里,改接线的时候只动这一个文件。

主循环里每个传感器独立采集、独立失败:

if (s_status.dht22_ok) {
   /* 读失败就打警告,继续跑 */
} else {
   ESP_LOGI(TAG, "[DHT22 ] n/a");
}

没接的模块打 n/a 而不是反复重试,启动时探测一次就记住状态。这样调试时能接一个测一个,出问题范围小。

三、调试记录

四路跑通一共踩了五个问题,按遇到的顺序记下来。

3.1 BMP280 气压正常,温度不对

气压读出来 1014.60 hPa,和当地天气对得上,但温度显示 0.27℃,而同一房间的 DHT22 是 26 度。

气压对、温度错,这个组合本身就说明了问题在哪。BMP280 的温度补偿和气压补偿是两个函数,气压补偿用的是温度补偿算出来的 t_fine,不经过温度的最终换算。所以错误只能在温度那一步:

T = (*t_fine_out) / 5120.0;    /* T 是摄氏度,比如 26.53 */
return (int32_t)T;             /* 这里截断成了 26 */

而调用方按 0.01℃ 解释返回值:

out->temperature_c = (float)temp_centi / 100.0f;    /* 26 / 100 = 0.26 */

返回值和调用方的单位约定不一致,改成 return (int32_t)(T * 100.0) 就对了。

改之前串口打印 T=0.27 C,改之后是 T=28.03 C,和 DHT22 的 27 度能对上。

3.2 MQ-2 通道配不起来

屏上 MQ-2 那行一直显示 N/A,但模块的电源灯是亮的,说明供电没问题。看启动日志:

E (802) adc_oneshot: adc_oneshot_config_channel(199): invalid attenuation
E (808) mq2: config channel failed: ESP_ERR_INVALID_ARG
W (813) gateway: MQ-2 not available

查 adc_oneshot_config_channel 的实现,第 199 行有这么个检查:

ESP_RETURN_ON_FALSE(config->atten < SOC_ADC_ATTEN_NUM, ...);

S31 的 SOC_ADC_ATTEN_NUM 是 1,也就是 atten 只能传 0。而 adc_atten_t 枚举里 DB_0=0、DB_2_5=1、DB_6=2、DB_12=3,我填的是 DB_12,直接返回错误。

改成 ADC_ATTEN_DB_0 就好了。

这里我自己走了个弯路。之前查代码时看到 adc_oneshot_ll_set_atten() 的函数体是 (void)atten,参数被硬件忽略,就以为填什么值都无所谓。实际上运行时确实忽略,但配置阶段会做范围校验,填错值连通道都配不上。查了一半就下结论,代价是多花了一轮排查。

3.3 改了代码没反应

修完温度问题重新编译,设备跑起来温度还是 0.27。当时以为是修复没生效,看启动日志才发现:

I (206) boot: compile time Sep 24 2026 12:50:24
I (373) app_init: Compile time: Sep 24 2026 12:47:34

编译时间是 9 月 24 号,而当时是 10 月 5 号。烧进去的是十天前的固件。

原因是习惯在 VSCode 里点烧录按钮,IDE 扩展用的构建目录和命令行不是同一个。后来改用命令行烧录就正常了。

日志里的编译时间戳可以直接用来确认烧的是不是最新那版,比怀疑代码快。

3.4 显示屏

驱动用的是 esp_lcd 框架,ST7789 的驱动在 IDF 本体里就有,不需要额外拉组件。

遇到的第一个问题是字符横向拉伸,看着像乱码。原因是我画字符时用了二维数组当缓冲区:

uint16_t buf[FONT_H * 4][FONT_W * 4];   /* [28][20],每行 20 个元素 */
esp_lcd_panel_draw_bitmap(..., (uint16_t *) buf);   /* 按 cw=10 的宽度去读 */

draw_bitmap 要的是连续的 cw × chh 个像素,二维数组每行有 20 个,多出来的 10 个被当成同一行的像素读了,整幅字就错位。

改成按实际宽度排布的一维数组:

uint16_t buf[FONT_H * 4 * FONT_W * 4];
buf[(r * scale + sy) * cw + (c * scale + sx)] = color;   /* stride 用 cw */

这个错误编译期查不出来,两边类型都是 uint16_t*,只能看实际效果。

第二个问题是画面转了 90 度。ST7789 芯片原生的帧缓冲是 240×320,而 3.2 寸模块的物理长边是 320,需要用 swap_xy 把坐标轴换过来。换完之后还有镜像,再调 mirror 的两个参数。

调这个的时候我把三个开关做成了宏,写在 board_config.h 里:

#define BOARD_LCD_SWAP_XY       1
#define BOARD_LCD_MIRROR_X      0
#define BOARD_LCD_MIRROR_Y      1

对着现象改比较快:整体转 90 度就改 swap,左右反了改 mx,上下反了改 my,这三个是独立的。

IMG_20261005_185322.jpg


3.5 BH1750 损伤

焊接排针时不小心焊掉了一颗电容,旁边那颗电容的两个焊盘还被锡连在了一起。

先量 VCC 和 GND,蜂鸣档不响,说明不是直接短路。然后串了一个 100Ω 电阻限流再上电——BH1750 工作电流只有 0.12mA,串 100Ω 压降 0.012V 不影响工作,但万一内部短路电流也只有 33mA,烧不了板子。

结果扫描正常,读到的数据也对。看来掉一颗去耦电容不影响使用。

IMG_20261005_182040.jpg

四、实测数据

屏幕截图 2026-10-05 181152.png


[DHT22 ] T=27.2 C  RH=59.7 %
[BH1750] lux=15.8
[BMP280] T=30.03 C  P=1015.45 hPa  alt=-18.30 m
[MQ-2  ] raw=2080 ratio=0.0159

BMP280 的温度比 DHT22 高大约 2 度。刚上电时差 3.1 度,过十几分钟热平衡之后收敛到 2 度左右,是芯片自发热和位置差异造成的。

MQ-2 在预热期间读数会持续往上爬,涨到 2084 左右才平稳。加热丝温度升高,SnO2 敏感层内阻下降,分压点电压跟着上升,读数变大。

屏幕截图 2026-10-05 185031.png


4.1 响应测试

光照:拿手机手电筒照 BH1750,读数从 15.8 变化到675.8。遮住之后又降回去。数字和模拟两路都能跟着环境变,这一路是通的。

MQ-2:手边没有标准气体源,对着传感器吹了口气,读数从 2084 降到 2042 左右,幅度几十。

这个方向有点反直觉——如果有可燃气体,应该是 Rs 下降、分压点电压上升、读数变大才对。查了 MQ-2 的资料,它的敏感层工作温度在 300℃ 左右,吹气会带走热量,短时间内降温效应盖过了化学反应,所以看到的是下降。

这个现象也说明器件对气流很敏感,实际部署时要考虑加防风罩。没有标准气体源没法做定量测试,只能记下现象。

关于浓度换算:常规做法是算 Rs/R0,需要准确的 AO 电压和洁净空气里的 R0 标定。S31 的 ADC 目前只有一档衰减,而且曲线拟合校准还没实现(adc_cali_schemes.h 里是注释掉的状态,标着 TODO),电压换算不可靠。所以代码里只输出原始值和归一化比值,用来做相对比较,不换算成物理量。


五、以太网与网页服务

5.1 链路

板载的是 YT8531,RGMII 接口,控制引脚 MDC/MDIO/RST 分别是 GPIO5/6/7。实测结果:

PHY          : YT8531 (RGMII)
Speed        : 1000 Mbps, full duplex
IP / 网关    : 192.168.31.28 / 192.168.31.1
上电→Link Up : 约 2.8 秒
Link Up→IP   : 约 4.8 秒

协商到了千兆全双工,说明 RGMII 的四对数据线时序是对的。同价位的板子不少还是百兆,这一条算是这块板子比较突出的地方。

5.2 PHY 的两个非标准行为

日志里有两行值得记下来:

auto-negotiation re-enabled
RGMII delay set: RX ~2ns (coarse), TX ~2ns (13 x 150ps)

第一行:YT8531 在硬件复位后会自行关闭自动协商——这是它没写在标准流程里的行为,不重新开启的话链路根本起不来。

第二行:RGMII 的收发时钟需要配置内部延迟,不配的话链路能建立但收发的数据是错的。日志里 TX 配的是 13 × 150ps ≈ 1.95ns。

这两点都不是标准 RGMII 流程里会遇到的东西,属于这颗 PHY 的脾气。好在 IDF 的以太网例程里已经封好了。

5.3 网页服务

既然板子有千兆网口,就把数据送到浏览器上看,比只盯着串口直观。

在 gateway 里加了两个模块:net_eth(从之前的链路验证工程移植过来)和 web_server(HTTP 服务端)。后者提供两个路由:

/           返回一个单页
/api/data   返回当前读数的 JSON

页面每 2 秒拉一次数据,四路读数加上底部的网络状态一起刷新:

屏幕截图 2026-10-05 193420.png


前端是自包含的——CSS 和 JS 全部内联,不引用任何 CDN。这样网关在没外网的局域网里也能正常打开,不会因为拉不到外部资源而白屏。

采集任务和 HTTP 任务之间用一份快照结构体交换数据,没有加锁。偶尔可能读到半新半旧的一组值,对网页显示来说无所谓,不值得为它引入互斥锁。

加了这两块之后固件从 292KB 涨到 532KB,app 分区还剩 49%,空间还够。

屏幕截图 2026-10-05 194234.png


六、总结

整个测评做下来,S31 这块板子和预览版的 IDF 用起来有几点感受。

硬件方面,J2 排针引出得比较全,常用的 GPIO 都能接到。受限的地方是两个电源引脚数量少,接多路外设的时候必须做电源分配。片上的 RGB 灯在预览版上驱动不完整(RMT 相关文件缺失),只能当电源指示用。

软件方面,预览版 IDF 的组件完整度参差不齐。以太网、SPI、I2C 和 HTTP 服务端都实测跑通了;WiFi 6 的驱动编译通过,但没有做实际的连接测试;RMT 在 soc 层缺文件,DHT22 这类靠时序的器件得用 GPIO 位操作自己实现;ADC 只有一档衰减且参数被忽略,校准也没有,只能读相对值。这些在正式版应该会补齐。

回头看这篇记录里的五个问题,有三个是真正影响功能的:温度单位、ADC 衰减、固件没更新。它们的共同点是编译都能过,跑起来才暴露。剩下两个是显示和硬件本身的问题。写下来给后来用这块板子的人参考。




关键词: ESP32-S31Functioncoreboar    

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]