








I2C 数字温湿度传感器,精度 ±0.3°C / ±2%RH。通过 I2C 接口(SCL/PB6, SDA/PB7)连接 STM32,每 100ms 采集一次环境温湿度。草莓生长适宜温度 18-25°C,适宜湿度 60-80%。实时数据通过串口 JSON 上传至浏览器。
模拟量 TDS 传感器,通过 STM32 ADC(PA0)采样后经温度补偿算法换算为 ppm 值。草莓苗期适宜 400-700 ppm,花果期需 800-1200 ppm。系统根据实时 TDS 值与阶段标准对比,自动生成施肥建议。
USB 转 TTL 串口芯片,连接 STM32 的 PA9(TX)/PA10(RX),115200 bps 速率传输 JSON 数据。配合浏览器 Web Serial API,无需安装驱动即可在 Chrome 中直接读取串口数据,实现真正的"零安装"体验。
SWD 接口(SWCLK/SWDIO/GND/3.3V)连接 STM32,Keil MDK 一键编译+下载。支持断点调试、变量查看。4 根杜邦线连接即可,无需额外配置。固件源码位于 E:\keli5\greentest\2-1stm32\。
SSD1306 驱动,128×64 分辨率,I2C 接口(地址 0x3C)。本地实时显示温度 / 湿度 / TDS 数值,方便不连接电脑时也能查看传感器数据。10Hz 刷新频率。
MB-102 面包板 + 跳线 + 杜邦线 + 飞线,用于搭建传感器与 STM32 的电路连接原型。无需焊接,方便快速迭代和实验调整。
| STM32引脚 | 连接外设 | 类型 | 说明 |
|---|---|---|---|
| PB6 | SHT31 SCL | I2C1_SCL | 温湿度传感器时钟线 |
| PB7 | SHT31 SDA | I2C1_SDA | 温湿度传感器数据线 |
| PA0 | TDS 探头 AO | ADC1_IN0 | 电导率模拟采样,12位分辨率 |
| PB0 | OLED SCL | GPIO (软I2C) | 软件模拟 I2C 时钟 |
| PB1 | OLED SDA | GPIO (软I2C) | 软件模拟 I2C 数据 |
| PA9 | CH340 RX | USART1_TX | 串口发送 JSON 数据 (115200bps) |
| PA10 | CH340 TX | USART1_RX | 串口接收 (备用) |
| PA13 | ST-LINK SWDIO | SWD | 程序下载/调试数据线 |
| PA14 | ST-LINK SWCLK | SWD | 程序下载/调试时钟线 |
主循环用 SysTick 中断产生 1ms 基准,HAL_GetTick() 提供毫秒级时间戳。主循环间隔 100ms = 10Hz 采集频率。
标准 I2C 协议,地址 0x44。发送 0x2C06 命令触发单次测量,等待 15ms 后读取 6 字节温湿度原始数据,按公式换算为 °C 和 %RH。
PA0 引脚 ADC1_IN0,12位分辨率(0-4095)。连续采样 10 次取平均值,温度补偿公式换算为 ppm 值。TDS = ADC_avg × 系数 ÷ (1 + 0.02 × (temp - 25))。
SSD1306 驱动芯片,PB0(SCL)/PB1(SDA) 软件模拟 I2C。128×64 分辨率,三行显示:温度 / 湿度 / TDS,10Hz 刷新率。
u8 SHT31_Read(float *temp, float *humi) {
u8 buf[6]; u16 raw_t, raw_h;
I2C_Start(); // 启动信号
I2C_SendByte(0x44 << 1); // SHT31 地址 0x44, 写模式
I2C_SendByte(0x2C); I2C_SendByte(0x06); // 高精度测量命令
I2C_Stop();
delay_ms(15); // 等待测量完成
I2C_Start();
I2C_SendByte(0x44 << 1 | 1); // 读模式
for (int i = 0; i < 5; i++) {
buf[i] = I2C_ReadByte(1); // ACK
}
buf[5] = I2C_ReadByte(0); // NACK + Stop
// SHT31 公式: temp = -45 + 175 × raw_t / (2^16-1)
raw_t = (buf[0] << 8) | buf[1];
raw_h = (buf[3] << 8) | buf[4];
*temp = -45.0 + 175.0 * raw_t / 65535.0;
*humi = 100.0 * raw_h / 65535.0;
return 0;
}
u16 TDS_Read(float temp) {
u32 adc_sum = 0;
for (int i = 0; i < 10; i++) { // 10次采样取平均
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动ADC
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));// 等转换完成
adc_sum += ADC_GetConversionValue(ADC1); // 读12bit值
}
float adc_avg = adc_sum / 10.0;
// 电压换算: V = adc × 3.3V / 4096
float voltage = adc_avg * 3.3 / 4096.0;
// TDS 计算(含温度补偿): TDS = V × coeff / (1 + 0.02×(temp-25))
float compensation = 1.0 + 0.02 * (temp - 25.0);
u16 tds = (u16)(voltage * 500.0 / compensation); // 系数500
return tds;
}
int main(void) {
System_Init(); // 时钟72MHz
I2C_Init(); ADC_Init(); UART1_Init(115200);
OLED_Init(); // SSD1306
float temp, humi; u16 tds;
char json[128];
while (1) {
SHT31_Read(&temp, &humi); // I2C 读温湿度
tds = TDS_Read(temp); // ADC 读电导率
// OLED 本地显示 (三行)
OLED_Clear();
OLED_Printf(0, 0, "Temp: %.1f C", temp);
OLED_Printf(0, 2, "Humi: %.1f %%", humi);
OLED_Printf(0, 4, "TDS : %d ppm", tds);
// 串口 JSON 输出 → 浏览器 Web Serial API 读取
sprintf(json, "{\"temp\":%.1f,\"humi\":%.1f,\"tds\":%d}\r\n",
temp, humi, tds);
UART1_SendString(json);
delay_ms(100); // 10Hz 采集频率
}
}
async function connectSerial() {
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 115200 });
const reader = port.readable.getReader();
let buffer = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += new TextDecoder().decode(value);
// 按行分割 JSON
const lines = buffer.split('\n');
buffer = lines.pop(); // 保留不完整行
for (const line of lines) {
if (line.startsWith('{"temp"')) {
sensor = JSON.parse(line.trim()); // 解析传感器数据
updateSensorDisplay(); // 更新页面
}
}
}
}
TDS 电导率连续采样 10 次取平均值,消除电源纹波和随机噪声干扰。
TDS 值随温度漂移,采用标准补偿公式 TDS = V × K / (1 + 0.02×(T-25)) 消除温度影响。
Web Serial API 检测到串口断开后,3 秒间隔自动重连,无需人工干预。
STM32 启动时自动扫描所有 COM 口,过滤发送全零数据的无效端口,精确匹配 CH340 数据端口。
仅解析以 {"temp" 开头的合法 JSON 行,忽略噪声数据和乱码,确保数据完整性。
浏览器不支持 Web Serial API 时,自动显示手动输入面板,输入温湿度/TDS 即可继续使用。
浏览器原生串口通信,零驱动、零安装。替代传统 pyserial + EXE 方案,彻底解决华为电脑兼容性问题。
SHT31 数字温湿度 (I2C) + TDS 模拟电导率 (ADC),100ms 周期同步采集,10Hz 刷新率。
四任务并行分析:生长阶段判断 + 植株测量(以果实为天然标尺) + 果实颗粒度三级识别 + 营养故事生成。
4 阶段预设参考数据,根据 AI 检测结果自动切换对照组,实现真正意义上的"对比实验"。
SheetJS 纯前端生成,传感器历史 + AI分析记录 + 汇总信息三个Sheet,蓝表头+斑马纹。
千问 API Key 仅存于服务端 .env,前端通过 POST /api/analyze 代理调用,密钥永不暴露。
| IDE | Keil MDK v5 (uVision V5.06) |
| 编译器 | ARMCC V5.06 update 5 (build 528) |
| 主控芯片 | STM32F103C8T6 (Cortex-M3, 64KB Flash, 20KB SRAM) |
| 时钟 | HSE 8MHz → PLL 9x → 72MHz |
| 标准库 | STM32F10x Standard Peripheral Library V3.5.0 |
| C语言标准 | C99 (--c99) |
| MicroLIB | 已启用 (精简 math 库) |
| 工程定义 | STM32F10X_MD, USE_STDPERIPH_DRIVER |
| 启动文件 | startup_stm32f10x_md.s (中等密度) |
| 编程器 | ST-LINK/V2 (SWD接口) |
| 开发语言 | Python 3.10+ (服务端), JavaScript ES6+ (前端), C99 (固件) |
| 核心依赖 | Flask, Requests, Web Serial API, SheetJS, openpyxl |
| AI 模型 | 千问 Qwen-VL-Plus 多模态视觉语言模型 |
| 传感器采样率 | STM32 端 10Hz (100ms/次), 浏览器端 1Hz 显示刷新 |
| 串口速率 | 115200 bps, 8N1, JSON 行协议 |
| 部署架构 | Ubuntu 22.04 + systemd + nginx HTTPS 反向代理 |