1. 项目背景与硬件选型
第一次接触物联网开发时,我被各种专业术语和复杂的协议搞得晕头转向。直到用STM32配合涂鸦Wi-Fi模组完成了一个温湿度监测项目,才发现原来智能硬件开发可以这么简单。这个系统最吸引人的地方在于,你只需要基础的嵌入式开发知识,就能让设备快速接入云端,实现手机远程监控。
选择STM32F103C8T6作为主控是因为它的性价比超高,一块核心板不到20元,却拥有72MHz主频和丰富的外设接口。而涂鸦WB3S模组则是我的首选,这个指甲盖大小的模块内置了Wi-Fi和蓝牙双模,最关键的是它已经预装了涂鸦的通信协议栈,省去了自己折腾TCP/IP协议栈的麻烦。
硬件连接非常简单:
- STM32的USART1(PA9/PA10)连接WB3S的TXD/RXD
- I2C1(PB6/PB7)连接SHT30温湿度传感器
- 3.3V电源同时给主控和模组供电
实际搭建时有个小技巧:一定要在WB3S的电源引脚并联一个100μF的电容。我在实验室测试时一切正常,但设备拿到现场就频繁重启,后来发现是Wi-Fi信号弱导致模组瞬时电流过大,加了电容后问题迎刃而解。
2. 开发环境搭建与CubeMX配置
安装STM32CubeMX时建议选择6.3.0版本,这个版本对HAL库的稳定性做了很多优化。新建工程时有个容易踩的坑:如果用的是国产兼容芯片,记得在"Help -> Manage embedded software packages"里安装对应的芯片支持包。
时钟配置是很多新手头疼的问题。对于温湿度监测这种低频采集场景,我习惯把主频设为64MHz,既保证性能又降低功耗。具体步骤:
- 在Clock Configuration选项卡选择HSE作为时钟源
- 在PLL Source Mux选择HSE
- 设置PLLM为4,PLLN为64,PLLP为2
- 最后将系统时钟源切到PLLCLK
串口配置需要特别注意:
// USART1用于与WB3S通信 huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16;I2C配置有个隐藏技巧:把Timing参数设为0x2000090E,这个值在标准库中找不到,但实测发现它能完美匹配SHT30的时序要求。记得开启I2C中断,这样在读取传感器数据时不会阻塞主程序。
3. SHT30传感器驱动开发
SHT30的硬件连接看似简单,但有几个细节容易出错:
- 上拉电阻必须接,推荐使用4.7kΩ
- 传感器供电电压不能超过3.6V
- PCB布局时要远离发热元件
驱动开发中最关键的是处理I2C的超时问题。我封装了一个安全读取函数:
uint8_t SHT3x_ReadReg(uint8_t reg, uint8_t *buf, uint16_t len) { HAL_StatusTypeDef ret; uint32_t tickstart = HAL_GetTick(); do { ret = HAL_I2C_Master_Transmit(&hi2c1, SHT3x_ADDR_WRITE, ®, 1, 10); if(ret != HAL_OK && (HAL_GetTick() - tickstart) > 100) return 1; } while(ret != HAL_OK); tickstart = HAL_GetTick(); do { ret = HAL_I2C_Master_Receive(&hi2c1, SHT3x_ADDR_READ, buf, len, 10); if(ret != HAL_OK && (HAL_GetTick() - tickstart) > 100) return 1; } while(ret != HAL_OK); return 0; }温湿度数据转换也有讲究,原始数据是16位无符号整数,需要按手册公式转换:
// 温度转换公式:T = -45 + 175 * rawValue / 65535 temperature = -45.0f + 175.0f * (float)rawTemp / 65535.0f; // 湿度转换公式:RH = 100 * rawValue / 65535 humidity = 100.0f * (float)rawHum / 65535.0f;实测发现,在连续读取模式下,每次读取后最好延时20ms再读取下一次,否则数据容易漂移。如果环境变化剧烈,可以开启加热器模式,但要注意这会增加5mA左右的电流消耗。
4. 涂鸦云平台对接实战
在涂鸦IoT平台创建产品时,品类选择"环境监测器"比选"开关"更合适,因为系统会自动预置温湿度DP点。创建完产品后,务必记录下PID和UUID,这两个参数相当于设备的身份证。
MCU SDK移植时最容易出错的是串口数据处理。涂鸦的协议是透传模式,需要在串口中断中这样处理:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { uart_receive_input(rx_buffer[rx_index++]); if(rx_index >= sizeof(rx_buffer)) rx_index = 0; HAL_UART_Receive_IT(&huart1, &rx_buffer[rx_index], 1); } }数据上报需要遵循特定的JSON格式,我写了个封装函数:
void report_sensor_data(float temp, float humi) { char buffer[128]; snprintf(buffer, sizeof(buffer), "{\"1\":%.1f,\"2\":%.1f}", temp, humi); wifi_uart_write_frame(SENSOR_REPORT_CMD, buffer, strlen(buffer)); }配网功能实现有个小技巧:长按开发板上的用户按键3秒进入配网模式,此时WB3S的LED会快闪。在涂鸦智能APP中添加设备时,选择"Wi-Fi快连"模式比AP模式成功率更高,特别是在2.4GHz和5GHz双频路由器环境下。
5. 低功耗优化与稳定性提升
项目上线后发现了几个需要优化的问题:
- Wi-Fi信号弱时数据上报失败
- 电池供电时续航时间短
- 传感器数据偶尔跳变
针对这些问题,我做了以下改进:
- 增加数据重传机制,失败后最多重试3次
- 采用间断工作模式:每5分钟唤醒一次,采集数据后立即休眠
- 在SHT30数据读取后增加CRC校验
休眠模式的实现代码:
void enter_stop_mode(void) { HAL_UART_DeInit(&huart1); HAL_I2C_DeInit(&hi2c2); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); MX_USART1_UART_Init(); MX_I2C2_Init(); }电源管理方面,实测发现:
- 运行模式电流:32mA(Wi-Fi连接时)
- 休眠模式电流:120μA(RTC保持运行)
- 如果关闭所有外设,电流可降至15μA
为了提升数据可靠性,我增加了本地存储功能,使用STM32的Flash模拟EEPROM存储最近10条记录,网络恢复后自动补传。具体实现时要注意Flash的写寿命,同一个页不要频繁擦写。
6. 项目进阶与功能扩展
基础功能稳定后,可以尝试这些增强功能:
- OTA远程升级:在平台上传固件后,设备会自动下载更新
- 报警功能:当温湿度超过阈值时推送APP通知
- 历史数据统计:使用涂鸦的数据API生成曲线图
OTA实现的关键代码:
void check_ota_update(void) { if(mcu_get_ota_flag()) { HAL_NVIC_SystemReset(); } }报警功能需要先在平台创建布尔型DP点,然后在代码中添加判断:
if(temperature > 30.0f || humidity > 80.0f) { char alert[32]; snprintf(alert, sizeof(alert), "{\"3\":true}"); wifi_uart_write_frame(ALARM_REPORT_CMD, alert, strlen(alert)); }如果想进一步降低功耗,可以考虑用LoRa模组替代Wi-Fi,但需要自己搭建网关。另一个方向是加入BLE Mesh,实现设备间组网,这在没有Wi-Fi覆盖的仓库场景特别有用。