当前位置: 首页 > news >正文

零知IDE——STM32F407VET6驱动SHT40温湿度传感器与ST7789实现智能环境监测系统

  ✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!

✔访问零知实验室,获取更多实战项目和教程资源吧!

www.lingzhilab.com

(1)项目概述

        本项目基于零知增强板和SHT40温湿度传感器,系统通过高精度的SHT40传感器实时采集环境温度和湿度数据,并在240×240分辨率的TFT显示屏上以四种不同的可视化界面进行展示。用户可以通过物理按键在不同显示模式间切换,系统还集成了VPD(蒸气压亏缺)计算功能,为农业智能家居等应用场景提供专业的环境参数监测。

(2)项目难点及解决方案

       问题描述:I2C通信的稳定性直接影响传感器数据的准确性

解决方案:设置合理的I2C通信时钟频率,添加数据CRC校验机制确保数据完整性

一、硬件系统设计

1.1 硬件清单

器件型号数量
主控板零知增强板(STM32F407VET6)1
温湿度传感器SHT401
TFT显示屏ST77891
按键轻触开关1
连接线杜邦线若干

1.2 接线方案

根据代码中定义的引脚,接线如下:

零知增强板引脚连接器件功能
10TFT_CS显示屏片选
6TFT_MOSI显示屏数据输入
5TFT_SCK显示屏时钟
9TFT_RST显示屏复位
8TFT_DC显示屏数据/命令选择
3BUTTON_PIN按键输入(下拉)
3.3VSHT4X VCC传感器电源
GNDSHT4X GND传感器地
20/SDASHT4X SDA传感器数据
21/SCLSHT4X SCL传感器时钟

        SHT40温湿度传感器可以采取线对板2.0引脚间距线束直插零知增强板扩展板

1.3 具体接线图

        注意:零知SHT40温湿度传感器采用LDO模块适配增强板板载电源输入1.5V-5.5V宽电压,满足芯片1.08V-3.6V供电电压

1.4 连接实物图

零知SHT40温湿度传感器详解

        将LDO稳压器布置在距离传感器较远的位置,减少热量对温度测量的影响;在每个IC电源引脚附近布置去耦电容,提高系统稳定性

        1)电源管理设计,采用SUL6018S5-ADJ LDO稳压器为系统提供稳定的1.8V电源:支持1.2V-5.5V输入范围,适应多种电源环境

        2)信号电平匹配,使用TXS0102双向电平转换器:解决1.8V和3.3/5V设备间的通信兼容性问题、支持I2C总线的双向电平转换

二、代码架构讲解

        代码使用零知DE框架编写,主要分为以下几个部分

2.1 全局对象与变量定义

#include <Adafruit_GFX.h>        // 图形库核心
#include <Adafruit_ST7789.h>     // ST7789显示屏驱动
#include <Adafruit_SHT4x.h>      // SHT4X传感器驱动
#include <Fonts/FreeSansBold18pt7b.h>  // 大号字体
#include <Fonts/FreeSansBold12pt7b.h>  // 中号字体  
#include <Fonts/FreeSans9pt7b.h>       // 小号字体// ST7789显示引脚定义
#define TFT_CS   10    // 片选信号
#define TFT_MOSI 6     // SPI数据输入
#define TFT_SCK  5     // SPI时钟
#define TFT_RST  9     // 复位信号
#define TFT_DC   8     // 数据/命令选择// 按键引脚定义
#define BUTTON_PIN 3   // 界面切换按键// 创建显示对象
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);// 创建传感器对象
Adafruit_SHT4x sht4 = Adafruit_SHT4x();// 全局变量
volatile int currentScreen = 0;          // 当前显示界面索引
volatile bool screenChanged = false;     // 界面切换标志
unsigned long lastButtonPress = 0;       // 上次按键时间
const unsigned long BUTTON_COOLDOWN = 300; // 按键防抖时间(ms)// 颜色定义
#define BACKGROUND_COLOR ST77XX_BLACK    // 背景色
#define PRIMARY_COLOR ST77XX_GREEN       // 主色调
#define TEMP_COLOR ST77XX_CYAN           // 温度颜色
#define HUMIDITY_COLOR ST77XX_BLUE       // 湿度颜色
#define VPD_COLOR ST77XX_YELLOW          // VPD颜色
#define WARNING_COLOR ST77XX_RED         // 警告颜色

        TFT_CS:显示屏片选,低电平有效、BUTTON_PIN:配置为输入上拉模式,下降沿触发中断

2.2 温度显示界面显示

void showTemperatureScreen() {sensors_event_t humidity, temp;sht4.getEvent(&humidity, &temp);// 绘制标题tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(TEMP_COLOR);tft.setCursor(50, 30);tft.print("Temperature");// 绘制温度圆环 (0-50°C范围)int centerX = 120, centerY = 110;int outerRadius = 70, innerRadius = 50;// 绘制背景圆环drawRing(centerX, centerY, innerRadius, outerRadius, 0, 360, ST77XX_DARKGREY);// 计算填充角度并绘制温度圆环float tempPercent = constrain(temp.temperature, 0, 50) / 50.0;int endAngle = 360 * tempPercent;drawRing(centerX, centerY, innerRadius, outerRadius, 0, endAngle, TEMP_COLOR);// 显示温度数值tft.setFont(&FreeSansBold18pt7b);tft.setTextColor(TEMP_COLOR);char tempStr[8];dtostrf(temp.temperature, 5, 1, tempStr);  // 浮点数转字符串// 清除中心区域并显示数值tft.fillCircle(centerX, centerY, innerRadius - 5, BACKGROUND_COLOR);tft.setCursor(centerX - 50, centerY + 10);tft.print(tempStr);tft.setFont(&FreeSans9pt7b);tft.setCursor(centerX + 30, centerY + 15);tft.print("C");
}

2.3 图形绘制辅助函数

// 绘制圆环函数
void drawRing(int x, int y, int innerRadius, int outerRadius, int startAngle, int endAngle, uint16_t color) {for (int r = innerRadius; r <= outerRadius; r++) {drawArc(x, y, r, startAngle, endAngle, color);}
}// 绘制圆弧函数
void drawArc(int x, int y, int radius, int startAngle, int endAngle, uint16_t color) {for (int i = startAngle; i <= endAngle; i++) {float angle = i * PI / 180;  // 角度转弧度int xp = x + radius * cos(angle);int yp = y + radius * sin(angle);tft.drawPixel(xp, yp, color);}
}

        通过 tft.drawPixe(xp, yp, color),在计算出的每个 (xp, yp) 位置画一个像素点;循环遍历 startAngle 到 endAngle 的所有角度

2.4 项目完整代码实现

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <Adafruit_SHT4x.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans9pt7b.h>// ST7789显示引脚定义
#define TFT_CS   10
#define TFT_MOSI 6
#define TFT_SCK  5
#define TFT_RST  9
#define TFT_DC   8// 按键引脚定义
#define BUTTON_PIN 3// 创建显示对象
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);// 创建传感器对象
Adafruit_SHT4x sht4 = Adafruit_SHT4x();// 全局变量
volatile int currentScreen = 0;
volatile bool screenChanged = false;
unsigned long lastButtonPress = 0;
const unsigned long BUTTON_COOLDOWN = 300; // 按键冷却时间(ms)// 颜色定义
#define BACKGROUND_COLOR ST77XX_BLACK
#define PRIMARY_COLOR ST77XX_GREEN
#define SECONDARY_COLOR ST77XX_WHITE
#define TEMP_COLOR ST77XX_CYAN
#define HUMIDITY_COLOR ST77XX_BLUE
#define VPD_COLOR ST77XX_YELLOW
#define WARNING_COLOR ST77XX_RED
#define ST77XX_DARKGREY 0xAD55// 已知序列号对应的型号-测试用(每个设备的序列号不一致)
#define SHT41_SERIAL 0x1513FB18
#define SHT40_SERIAL 0xF6C5E9F// 中断服务函数
void buttonISR() {if (millis() - lastButtonPress > BUTTON_COOLDOWN) {currentScreen = (currentScreen + 1) % 4;screenChanged = true;lastButtonPress = millis();}
}void setup() {Serial.begin(115200);// 初始化按键中断pinMode(BUTTON_PIN, INPUT_PULLUP);attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);// 初始化显示屏tft.init(240, 240);tft.setRotation(1);tft.fillScreen(BACKGROUND_COLOR);// 显示启动画面showSplashScreen();delay(2000);// 初始化传感器if (!sht4.begin()) {showError("SHT4x not found!");while (1) delay(1000);}Serial.println("Found SHT4x sensor");Serial.print("Serial number 0x");Serial.println(sht4.readSerial(), HEX);// 设置传感器精度sht4.setPrecision(SHT4X_HIGH_PRECISION);sht4.setHeater(SHT4X_NO_HEATER);// 显示初始化信息showInitInfo();delay(3000);// 清屏准备主界面tft.fillScreen(BACKGROUND_COLOR);
}void loop() {// 读取传感器数据sensors_event_t humidity, temp;sht4.getEvent(&humidity, &temp);// 串口打印数据(简单格式)Serial.print("Temp:");Serial.print(temp.temperature, 2);Serial.print("℃ Humi:");Serial.print(humidity.relative_humidity, 2);Serial.println(" %RH");// 检查是否需要切换界面if (screenChanged) {tft.fillScreen(BACKGROUND_COLOR);screenChanged = false;}// 根据当前界面显示相应内容switch (currentScreen) {case 0:showTemperatureScreen();break;case 1:showHumidityScreen();break;case 2:showVPDScreen();break;case 3:showInfoScreen();break;}delay(500);
}void showSplashScreen() {tft.fillScreen(BACKGROUND_COLOR);// 标题tft.setFont(&FreeSansBold18pt7b);tft.setTextColor(PRIMARY_COLOR);tft.setCursor(40, 80);tft.print("SHT4x");tft.setFont(&FreeSansBold12pt7b);tft.setCursor(50, 120);tft.print("Sensor");tft.setCursor(60, 150);tft.print("Monitor");
}void showInitInfo() {tft.fillScreen(BACKGROUND_COLOR);tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(PRIMARY_COLOR);tft.setCursor(20, 40);tft.print("Initialization");tft.drawLine(20, 50, 220, 50, PRIMARY_COLOR);// 读取并显示序列号uint32_t serial = sht4.readSerial();String sensorModel = "Unknown";if (serial == SHT41_SERIAL) {sensorModel = "SHT41";} else if (serial == SHT40_SERIAL) {sensorModel = "SHT40";}tft.setFont(&FreeSans9pt7b);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 80);tft.print("Model: ");tft.setTextColor(PRIMARY_COLOR);tft.print(sensorModel);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 105);tft.print("Serial: 0x");tft.setTextColor(PRIMARY_COLOR);tft.print(serial, HEX);// 显示精度设置tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 130);tft.print("Precision: ");tft.setTextColor(PRIMARY_COLOR);switch (sht4.getPrecision()) {case SHT4X_HIGH_PRECISION: tft.print("High");break;case SHT4X_MED_PRECISION: tft.print("Medium");break;case SHT4X_LOW_PRECISION: tft.print("Low");break;}// 显示加热器设置tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 155);tft.print("Heater: ");tft.setTextColor(PRIMARY_COLOR);switch (sht4.getHeater()) {case SHT4X_NO_HEATER: tft.print("Off");break;case SHT4X_HIGH_HEATER_1S: tft.print("High 1s");break;case SHT4X_HIGH_HEATER_100MS: tft.print("High 0.1s");break;case SHT4X_MED_HEATER_1S: tft.print("Medium 1s");break;case SHT4X_MED_HEATER_100MS: tft.print("Medium 0.1s");break;case SHT4X_LOW_HEATER_1S: tft.print("Low 1s");break;case SHT4X_LOW_HEATER_100MS: tft.print("Low 0.1s");break;}tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 200);tft.print("Press button to start");
}void showTemperatureScreen() {sensors_event_t humidity, temp;sht4.getEvent(&humidity, &temp);// 绘制标题tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(TEMP_COLOR);tft.setCursor(50, 30);tft.print("Temperature");// 绘制温度圆环 (0-50°C范围)int centerX = 120;int centerY = 110;int outerRadius = 70;int innerRadius = 50;int ringWidth = outerRadius - innerRadius;// 绘制背景圆环drawRing(centerX, centerY, innerRadius, outerRadius, 0, 360, ST77XX_DARKGREY);// 绘制温度填充圆环float tempPercent = constrain(temp.temperature, 0, 50) / 50.0;int endAngle = 360 * tempPercent;drawRing(centerX, centerY, innerRadius, outerRadius, 0, endAngle, TEMP_COLOR);// 绘制中心数值tft.setFont(&FreeSansBold18pt7b);tft.setTextColor(TEMP_COLOR);char tempStr[8];dtostrf(temp.temperature, 5, 1, tempStr);// 清除中心区域tft.fillCircle(centerX, centerY, innerRadius - 5, BACKGROUND_COLOR);// 显示温度值tft.setCursor(centerX - 50, centerY + 10);tft.print(tempStr);tft.setFont(&FreeSans9pt7b);tft.setCursor(centerX + 30, centerY + 15);tft.print("C");// 显示底部状态tft.setFont(&FreeSans9pt7b);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(60, 220);tft.print("Screen: 1/4");
}void showHumidityScreen() {sensors_event_t humidity, temp;sht4.getEvent(&humidity, &temp);// 绘制标题tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(HUMIDITY_COLOR);tft.setCursor(65, 30);tft.print("Humidity");// 绘制湿度圆环 (0-100%范围)int centerX = 120;int centerY = 110;int outerRadius = 70;int innerRadius = 50;// 绘制背景圆环drawRing(centerX, centerY, innerRadius, outerRadius, 0, 360, ST77XX_DARKGREY);// 绘制湿度填充圆环float humidityPercent = constrain(humidity.relative_humidity, 0, 100) / 100.0;int endAngle = 360 * humidityPercent;drawRing(centerX, centerY, innerRadius, outerRadius, 0, endAngle, HUMIDITY_COLOR);// 绘制中心数值tft.setFont(&FreeSansBold18pt7b);tft.setTextColor(HUMIDITY_COLOR);char humidityStr[8];dtostrf(humidity.relative_humidity, 5, 1, humidityStr);// 清除中心区域tft.fillCircle(centerX, centerY, innerRadius - 5, BACKGROUND_COLOR);// 显示湿度值tft.setCursor(centerX - 50, centerY + 10);tft.print(humidityStr);tft.setFont(&FreeSans9pt7b);tft.setCursor(centerX + 25, centerY + 10);tft.print("%");// 显示底部状态tft.setFont(&FreeSans9pt7b);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(60, 220);tft.print("Screen: 2/4");
}void showVPDScreen() {sensors_event_t humidity, temp;int innerRadius = 50;sht4.getEvent(&humidity, &temp);// 计算VPDfloat svp = 0.6108 * exp(17.27 * temp.temperature / (temp.temperature + 237.3));float avp = humidity.relative_humidity / 100 * svp;float vpd = svp - avp;// 绘制标题tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(VPD_COLOR);tft.setCursor(95, 30);tft.print("VPD");// 绘制VPD仪表int centerX = 120;int centerY = 110;int radius = 60;// 绘制仪表背景tft.drawCircle(centerX, centerY, radius, ST77XX_DARKGREY);tft.drawCircle(centerX, centerY, radius + 1, ST77XX_DARKGREY);// 根据VPD值选择颜色 (正常范围: 0.8-1.2 kPa)uint16_t vpdColor;if (vpd >= 0.8 && vpd <= 1.2) {vpdColor = VPD_COLOR;} else {vpdColor = WARNING_COLOR;}// 绘制VPD值弧线float vpdMapped = constrain(vpd, 0, 2.0) / 2.0; // 映射到0-2kPa范围int vpdAngle = 270 * vpdMapped; // 270度弧线for (int i = 0; i <= vpdAngle; i += 5) {float angle = i * PI / 180;int x1 = centerX + (radius - 10) * cos(angle);int y1 = centerY + (radius - 10) * sin(angle);int x2 = centerX + radius * cos(angle);int y2 = centerY + radius * sin(angle);tft.drawLine(x1, y1, x2, y2, vpdColor);}// 清除中心区域tft.fillCircle(centerX, centerY, innerRadius - 5, BACKGROUND_COLOR);// 显示VPD数值tft.setFont(&FreeSansBold18pt7b);tft.setTextColor(vpdColor);char vpdStr[8];dtostrf(vpd, 4, 2, vpdStr);tft.setCursor(centerX - 40, centerY + 10);tft.print(vpdStr);tft.setFont(&FreeSans9pt7b);tft.setCursor(centerX + 5, centerY + 30);tft.print("kPa");// 清除状态显示tft.fillRect(30, 180, 210, 20, BACKGROUND_COLOR);// 显示VPD状态tft.setFont(&FreeSans9pt7b);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(30, 195);if (vpd < 0.8) {tft.print("Low VPD - Risk of mold");} else if (vpd > 1.2) {tft.print("High VPD - Plant stress");} else {tft.print("Optimal VPD range");}// 显示底部状态tft.setCursor(60, 220);tft.print("Screen: 3/4");
}void showInfoScreen() {sensors_event_t humidity, temp;sht4.getEvent(&humidity, &temp);// 计算VPDfloat svp = 0.6108 * exp(17.27 * temp.temperature / (temp.temperature + 237.3));float avp = humidity.relative_humidity / 100 * svp;float vpd = svp - avp;// 读取序列号并确定型号uint32_t serial = sht4.readSerial();String sensorModel = "Unknown";if (serial == SHT41_SERIAL) {sensorModel = "SHT41";} else if (serial == SHT40_SERIAL) {sensorModel = "SHT40";}// 绘制标题tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(PRIMARY_COLOR);tft.setCursor(50, 30);tft.print("Sensor Info");tft.drawLine(20, 45, 220, 45, PRIMARY_COLOR);tft.setFont(&FreeSans9pt7b);// 显示传感器型号tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 70);tft.print("Model:");tft.setTextColor(PRIMARY_COLOR);tft.setCursor(100, 70);tft.print(sensorModel);// 显示序列号tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 95);tft.print("Serial:");tft.setTextColor(PRIMARY_COLOR);tft.setCursor(100, 95);tft.print("0x");tft.print(serial, HEX);// 显示当前读数tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 120);tft.print("Temperature:");tft.fillRect(140, 100, 40, 30, BACKGROUND_COLOR);   //局部刷新tft.setTextColor(TEMP_COLOR);tft.setCursor(140, 120);tft.print(temp.temperature, 1);tft.print(" C");tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 145);tft.print("Humidity:");tft.fillRect(140, 125, 40, 30, BACKGROUND_COLOR);tft.setTextColor(HUMIDITY_COLOR);tft.setCursor(140, 145);tft.print(humidity.relative_humidity, 1);tft.print(" %");tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 170);tft.print("VPD:");tft.fillRect(140, 150, 40, 30, BACKGROUND_COLOR);tft.setTextColor(VPD_COLOR);tft.setCursor(140, 170);tft.print(vpd, 2);tft.print(" kPa");// 显示精度信息tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 195);tft.print("Precision:");tft.setTextColor(PRIMARY_COLOR);switch (sht4.getPrecision()) {case SHT4X_HIGH_PRECISION: tft.setCursor(140, 195);tft.print("High");break;case SHT4X_MED_PRECISION: tft.setCursor(140, 195);tft.print("Medium");break;case SHT4X_LOW_PRECISION: tft.setCursor(140, 195);tft.print("Low");break;}// 显示底部状态tft.setTextColor(SECONDARY_COLOR);tft.setCursor(60, 220);tft.print("Screen: 4/4");
}void drawRing(int x, int y, int innerRadius, int outerRadius, int startAngle, int endAngle, uint16_t color) {for (int r = innerRadius; r <= outerRadius; r++) {drawArc(x, y, r, startAngle, endAngle, color);}
}void drawArc(int x, int y, int radius, int startAngle, int endAngle, uint16_t color) {for (int i = startAngle; i <= endAngle; i++) {float angle = i * PI / 180;int xp = x + radius * cos(angle);int yp = y + radius * sin(angle);tft.drawPixel(xp, yp, color);}
}void showError(const char* message) {tft.fillScreen(BACKGROUND_COLOR);tft.setFont(&FreeSansBold12pt7b);tft.setTextColor(WARNING_COLOR);tft.setCursor(40, 100);tft.print("ERROR");tft.setFont(&FreeSans9pt7b);tft.setTextColor(SECONDARY_COLOR);tft.setCursor(20, 140);tft.print(message);
}

2.5 关键算法解析

        1)VPD计算算法:VPD(Vapor Pressure Deficit)是农业环境中重要的生理参数,计算公式基于Magnus公式:

// 饱和蒸气压计算 (Tetens公式)
float svp = 0.6108 * exp(17.27 * T / (T + 237.3));
// 实际蒸气压
float avp = RH / 100 * svp;
// 蒸气压亏缺
float vpd = svp - avp;

参数意义:T:温度(℃)、RH:相对湿度(%)

        2)中断服务函数:volatile关键字确保多线程环境下变量的可见性;时间戳防抖算法有效消除机械按键抖动

void setup() {Serial.begin(115200);// 初始化按键中断pinMode(BUTTON_PIN, INPUT_PULLUP);attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);/*省略其他部分代码*/
}void buttonISR() {// 防抖处理:确保两次按键间隔大于冷却时间if (millis() - lastButtonPress > BUTTON_COOLDOWN) {currentScreen = (currentScreen + 1) % 4;  // 循环切换0-3四个界面screenChanged = true;                     // 设置界面更新标志lastButtonPress = millis();               // 更新按键时间戳}
}

        attachInterrupt()处理按键的中断触发,设置冷却时间以防止按键抖动导致的多次触发,currentScreen变量确保界面索引切换

中断函数语法:attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

pin: 中断引脚号、ISR: 中断服务程序名、mode:中断模式

中断模式(mode)有以下几种形式:LOW: 当引脚为低电平时触发中断服务程序、CHANGE: 当引脚电平发生变化时触发中断服务程序、RISING: 当引脚电平由低电平变为高电平时触发中断服务程序
        FALLING: 当引脚电平由高电平变为低电平时触发中断服务程序,代码中采取这种方式进入中断

系统流程图:

三、项目结果演示

3.1 操作流程

        1)硬件连接与系统启动:确认所有接线按照接线图正确连接、检查电源电压稳定在3.3V或5V。上电后观察启动画面显示,检查传感器初始化信息

        2)功能验证测试:确认序列号读取正确(每个传感器序列号不同)、按键切换四个显示界面、观察温湿度数据更新

        3)测试异常状态提示功能:错误界面展示"SHT40通信失败"

        4)串口调试数据打印测试:通过零知IDE串口实时输出监测的温湿度数据

        eg: Found SHT4x sensor
                Serial number 0xF6C5E9F
                Temp:27.43℃ Humi:73.33 %RH
                Temp:27.45℃ Humi:74.06 %RH

3.2 界面展示说明

        >界面1 温度显示,中央圆形进度条显示当前温度(0-50℃范围)、显示当前环境精确温度数据

        >界面2 湿度显示,圆形进度条显示相对湿度(0-100%范围)、实时湿度百分比显示

        >界面3 VPD显示,弧形仪表显示VPD值(0-2kPa范围)、状态编码:正常(黄色)| 异常(红色)、底部状态提示文字

3.3 视频演示

SHT40温湿度传感器环境监测系统

系统在实际环境中的温度变化时的实时响应、不同湿度条件下的显示效果,以及VPD异常状态下的警告提示

四、SHT4X温湿度传感器工作原理

        SHT4X是Sensirion公司的新一代数字温湿度传感器,基于CMOSens®技术,将完整的传感器系统集成在单个芯片上

4.1 温湿度测量原理

        SHT4X采用带隙温度传感器原理:

        利用半导体PN结的正向电压与温度的线性关系、内置两个不同电流偏置的晶体管,测量其基极-发射极电压差、通过ΔVBE电压与绝对温度成正比的关系计算温度值

        湿度测量基于电容式聚合物传感器:传感器由两个电极和吸湿性聚合物介质组成、聚合物吸收水分子后介电常数发生变化、导致电极间电容值与相对湿度成比例变化

4.2 I2C通信协议详解

        SHT4X使用标准的I2C通信协议,设备地址为0x44(7位地址)

通信时序

        a. 启动条件 → 设备地址(写) → 命令字节 → 停止条件
        b. 启动条件 → 设备地址(读) → 数据字节1 → ACK → 数据字节2 → NACK → 停止条件

重要命令集

        0xFD → 高精度温度湿度测量、0x89 → 读取32位唯一序列号、0x94 → 软件复位传感器

数据格式

        16位温度和湿度原始值,通过公式转换为实际温湿度值

CRC检验和

4.3 寄存器配置详解

        SHT4X通过单次命令进行操作,无需寄存器配置,但支持多种测量模式:

命令精度模式测量时间温度精度湿度精度
0xFD高精度10ms±0.2℃±2%RH
0xF6中精度5ms±0.3℃±3%RH
0xE0低精度2ms±0.5℃±4%RH

五、常见问题解答(FAQ)

Q1:显示数据不更新或刷新缓慢?

A1: 可能原因和解决方案:

        检查主循环延迟时间,适当调整刷新频率、确认传感器测量模式设置正确、检查SPI通信速率配置、优化图形绘制算法,减少重复绘制

Q2: VPD计算值不准确如何校准?

A2: 校准步骤:

        使用标准温湿度计进行对比测量、验证传感器本身的测量精度、检查VPD计算公式参数是否正确

Q3: 按键响应不灵敏或误触发?

A3: 优化建议:

        调整按键防抖时间常数BUTTON_COOLDOWN、检查硬件上拉电阻是否正常、优化中断服务函数执行效率

项目资源

        SHT40 库文件: Adafruit_SHT4X Library

        SHT40 数据手册: Datasheet_SHT4x

http://www.dtcms.com/a/583353.html

相关文章:

  • 中国人做的比较好的shopify网站公司网页怎么关闭
  • 大语音模型有什么作用和特点
  • 网站建设公司的市场定位专业的移动网站建设公
  • wordpress 选择插件南昌网络排名优化
  • wordpress 注册 密码专业搜索引擎seo公司
  • mipi dsi图像
  • 网站开发合作意向协议书房产信息网网站
  • 企业管理网站建设wordpress 熊掌
  • 深度学习入门:基于Python的理论与实现(理论研究)
  • 网站开发合同样本兴义网站建设网站建设
  • 网站的常用建设技术有哪些网站建设义乌
  • 360元网站建设链接搜索引擎
  • Visual Studio Installer Projects 打包msi程序
  • 如何自己做网站站长廊坊关键词排名
  • 哪里做网站比较号万江区网站建设公司
  • 金州网站建设做网站字体要求
  • 三维技术 + AI 动画,焕活古镇科技人文新表达,天南文化助力 2025 年世界互联网大会乌镇峰会
  • linux服务-Bonding网卡绑定工具
  • 网站开发 文学网站建设讲解材料
  • 网站常见的域名网站备案企业用个人来备案可以用吗
  • 重组蛋白表达技术|HEK293细胞蛋白表达|高效重组蛋白生产服务
  • 曹县网站建设公司做一个线上app多少钱
  • 官方网站建设的意义芜湖有哪些招聘网站
  • 网站建设 考试题目wordpress怎么上手
  • 网站后缀名厦门做企业网站
  • 做网站月薪网站开发开票内容
  • 南通做百度网站的公司网站电子商务网站建设技术
  • 种子网站开发简单网站建设方案策划
  • asp做网站安全性写一个简单的网页
  • 搜狗网站录入仿网站建设教程视频教程