嵌入式温湿度监测实战:SHT30/SHT20驱动模块设计与优化

从零实现STM32模拟IIC驱动SHT30与OLED的温湿度监测方案 本文详细介绍了基于STM32的模拟IIC驱动方案,实现SHT30温湿度传感器与OLED显示屏的高效集成。通过精确控制IIC时序、优化传感器数据读取和显示刷新策略,构建了稳定的本地化环境监测系统,适用于智能家居、农业大棚等场景。重点解析了模拟IIC实现细节、SHT30驱动开发和OLED显示优化等核心技术。 阅读详情

1. 从零开始:为什么我们需要一个“好”的SHT30驱动?

如果你正在做一个智能家居项目,比如一个能自动开关加湿器的温湿度控制器,或者一个需要记录环境数据的农业监测设备,那么SHT30或SHT20这类数字温湿度传感器大概率是你的首选。它们精度不错、体积小巧、接口简单,价格也亲民。但当你兴冲冲地买来模块,准备用单片机读取数据时,可能会发现事情没那么简单。

很多朋友的第一反应是:网上找个例程,复制粘贴一下I2C的读写代码,能读出来数据不就行了?我刚开始也是这么想的,但实际做项目时,问题就来了。比如,你的主程序正在处理复杂的网络通信或用户界面,传感器数据读取如果采用简单的“阻塞式”轮询,整个系统就可能被卡住,反应迟钝。再比如,传感器数据是字符串格式“Temp = 25.600 Hum = 60.500\r\n”,你需要稳定地从串口字节流里把这一帧帧数据完整地“抠”出来,还要能应对数据错位、丢包的情况。更别提你可能还需要动态调整传感器的采样率。

这时候,一个设计良好的驱动模块的价值就体现出来了。它不仅仅是“能工作”的代码,更是稳定、可靠、易集成的保障。一个好的驱动应该像黑匣子,你只需要告诉它“数据来了”和“你想干什么”,它就能在后台默默处理好一切,通过回调函数把干净的数据交给你,不打扰主程序的运行。这正是原始文章中那个驱动模块的设计思路:指令器(Cmder) 和接收机(Recver) 分离,完全被动工作,与硬件平台解耦。接下来,我们就一起动手,从硬件连接到软件架构,一步步设计和优化一个属于你自己的、更强大的SHT30/SHT20驱动模块。

2. 硬件连接与通信协议:避开第一个坑

在写代码之前,我们先得把硬件搞清楚。这里有个关键点:原始文章里提到的模块,其实是一个SHT30传感器+串口转换板的组合体。这意味着,传感器本身(I2C接口)已经由转接板处理好了,我们单片机直接面对的是一个TTL串口。这一点非常重要,直接决定了我们的驱动是面向串口通信,而不是直接操作I2C。

2.1 硬件接线与参数确认

首先,准备你的硬件。你需要一个STM32、ESP32或者其他任何带串口(UART)的单片机,一个SHT30的串口模块(通常标有TX、RX、VCC、GND)。接线非常简单:

  • 模块的 VCC 接单片机 3.3V(绝大多数SHT30模块是3.3V电平,务必确认,接5V可能损坏!)
  • 模块的 GND 接单片机 GND
  • 模块的 TX 接单片机的 RX(接收引脚)
  • 模块的 RX 接单片机的 TX(发送引脚)。如果你只需要读取数据,不发送配置指令,RX可以不接。

接好线,上电。这时模块可能已经开始通过串口往外发送数据了。用串口调试助手(如XCOM、Putty)连接到单片机对应的串口,设置参数为:波特率115200,8位数据位,1位停止位,无校验位。你应该能看到屏幕上每隔一段时间就打印出一行类似 Temp = 25.600 Hum = 60.500 的数据。恭喜,硬件通道打通了!

2.2 理解数据帧与指令格式

看到数据只是第一步,我们要让单片机也能看懂。仔细分析这行数据,它就是一个标准的文本帧:

  • 帧头:固定字符串 "Temp = "。这是一个非常清晰的起始标志。
  • 数据体:温度值(如25.600)、分隔字符串 " Hum = "、湿度值(如60.500)。
  • 帧尾:回车换行符 "\r\n"。这是经典的串口文本行结束标志。

这种格式对程序员非常友好,因为它避免了处理二进制数据时的大小端、对齐等麻烦。我们的接收机核心任务,就是从连续的字节流中,准确识别出以 "Temp = " 开头、以 "\r\n" 结尾的完整数据帧。

那么,如何控制模块呢?根据资料,模块需要先发送一个进入配置模式的指令(通常是 0xFF, 0xAA, 0x09, 0x00, 0x00),然后再发送一次包含具体参数的指令来设置,比如采样率。采样率参数就放在指令数组的第四个字节。原始驱动里用枚举 SHT30SampleRate 定义了从10Hz到0.1Hz共7个档位,对应数值0到6。指令器(Cmder)的工作,就是封装好这些指令数组,并通过你提供的发送函数发出去。

3. 驱动模块架构设计:解耦与被动式响应的艺术

直接对着串口写死读取代码是最快的,但也是最脆弱的。当你的项目需要同时处理按键、屏幕刷新、网络发包时,这种写法会让代码变得难以维护。我们来借鉴并深化原始文章的设计,打造一个更健壮的架构。

3.1 核心思想:模块分离与事件驱动

整个驱动分为两个独立部分:

  • SHT30Cmder(指令器):只管“发”。它内部不知道数据通过串口、蓝牙还是Wi-Fi发送,它只依赖一个你注册的“发送通道”函数。想设置采样率?调用 SHT30Cmder_setSampleRate(SHT30SR_1Hz),它生成指令数组,调用你的发送函数,任务完成。
  • SHT30Recver(接收机):只管“收”和“解析”。它像一个专注的“哨兵”,你每收到一个字节,就喂给它(SHT30Recver_Feed(byte))。它在内部拼装字节流,冷静地寻找帧头和帧尾。只有当确认捕获到一个完整、正确的数据帧时,它才通过你事先注册的回调函数,把解析好的温湿度值(一个结构体)通知给你的应用程序。

这种设计的最大好处是解耦。你的主循环(或中断服务程序)只需要做两件事:1. 从串口读取字节;2. 把字节喂给 SHT30Recver_Feed。你不需要关心解析细节。同时,指令器也让配置操作变得安全且统一。

3.2 关键数据结构与接口

让我们看看核心的头文件 SHT30Driver.h 里定义了些什么,这能帮助我们理解模块的能力边界。

typedef struct SHT30STRUCT_DATA{
    float temp; // °C
    float humi; // percent
} SHT30Data;

typedef void (* SHT30FUNC_DATA)(SHT30Data data);

SHT30Data 结构体是驱动与应用程序之间的数据契约,温度(℃)和湿度(%)都以浮点数传递,方便直接使用。SHT30FUNC_DATA 是一个函数指针类型,这就是回调函数的原型。当接收机解析成功,就会调用这个函数,并把数据作为参数传入。

void SHT30Recver_Init(SHT30FUNC_DATA onRecvData);
void SHT30Recver_Feed(uint8_t nextByte);
void SHT30Cmder_Init(void (* outChannel)(uint8_t *buf, uint16_t len));
void SHT30Cmder_setSampleRate(SHT30SampleRate value);

这几个接口是模块的灵魂。Init 函数完成初始化和回调函数绑定。Feed 是驱动运行的“发动机”。setSampleRate 则展示了指令器的用法。整个设计非常简洁,没有复杂的依赖,几乎可以移植到任何嵌入式平台。

4. 接收机(Recver)实现详解:打造可靠的字节流处理器

接收机是驱动里最复杂也最精彩的部分。它本质上是一个状态机,或者叫“协议解析器”。原始文章的实现依赖了一个叫 RxMac 的通用接收状态机模块,这体现了很好的软件复用思想。我们来剖析一下它的工作原理,并思考如何优化。

4.1 状态机是如何工作的?

想象一下,你正在听一个断断续续的电台广播,广播里每隔一段时间说一句“当前温度是XX度,湿度是YY%”。你怎么判断一句话什么时候开始,什么时候结束?你会等待“当前温度是”这个关键词(帧头),然后开始认真听后面的数字,直到听到句号(帧尾),就知道一句话说完了。

RxMac 模块就是做了这件事。在 SHT30Recver.c 的 _onFlushed 函数中,它被配置为识别两种“标志”:

  • 强帧头:_flag_header = {'T','e','m','p',' ','=',' '}。必须按顺序完整匹配,才认为一帧开始。
  • 强帧尾:_flag_ender = {'\r','\n'}。必须按顺序完整匹配,才认为一帧结束。

RxMac 内部维护着一个缓冲区和一个状态。每次你 Feed 一个字节,它就在缓冲区追加,并检查状态。只有同时满足了“找到帧头”和“找到帧尾”两个条件,它才会认为捕获到了一帧完整的数据,然后调用 _onFlushed 回调函数,把缓冲区里的数据交给我们处理。

4.2 数据解析与鲁棒性优化

在 _onFlushed 函数里,我们拿到了原始字节数据(比如 "Temp = 25.600 Hum = 60.500\r\n")。接下来要做的,就是安全地提取出两个浮点数。

原始代码做了以下几件事,非常经典:

  1. 查找湿度分隔符:p = strstr((const char *)buf, " Hum = ");。这找到了湿度值开始的位置。
  2. 验证数字格式:通过一个自定义的 _FloatFormatRight 函数,分别检查温度字符串(buf[7] 到 p 之前)和湿度字符串(p[9] 到帧尾之前)是否只包含数字、负号和小数点。这一步至关重要,它能有效过滤因串口干扰产生的乱码,防止 atof 函数解析错误导致程序崩溃。
  3. 转换并回调:使用 atof 将字符串转为浮点数,填入 SHT30Data 结构体,最后调用用户注册的回调函数 _onRecvData(data)。

这里我们可以做一个优化:原始代码的查找是直接使用 strstr,这在标准C库环境下没问题,但在某些极简的嵌入式C库中可能不支持。我们可以实现一个轻量级的字节匹配函数来替代,增强可移植性。同时,可以增加对数据范围的初步判断(比如温度是否在-40~125℃的合理范围内),在回调函数之前再做一层数据校验,让驱动更健壮。

5. 指令器(Cmder)与采样率控制:让传感器听你的

虽然传感器上电就有默认输出,但能主动控制它才是嵌入式开发的乐趣。SHT30模块允许我们调整数据输出频率,也就是采样率,从每秒10次到每10秒1次(0.1Hz)。这在低功耗场景下非常有用。

5.1 指令发送机制

指令器的实现非常简洁。在 SHT30Cmder.c 中,核心就是一个函数指针 _out,它在你调用 SHT30Cmder_Init 时被赋值,指向你提供的发送函数(比如一个封装好的串口发送函数)。

当调用 SHT30Cmder_setSampleRate(SHT30SR_1Hz) 时,函数内部会构造一个5字节的指令数组:{0xFF, 0xAA, 0x09, rate_code, 0x00}。其中 rate_code 就是枚举值对应的数字(例如 SHT30SR_1Hz 对应 3)。然后,直接调用 _out(buf, sizeof(buf)) 把指令发出去。

这里有一个非常重要的实践细节:根据模块手册,修改配置需要连续发送两次相同指令。第一次是让模块从“工作模式”进入“配置模式”,第二次才是真正执行设置。原始驱动代码里这个细节没有体现,需要你在应用层代码中实现。例如:

// 进入配置模式
SHT30Cmder_setSampleRate(SHT30SR_1Hz);
// 稍作延时,等待模块响应
HAL_Delay(50);
// 再次发送,实际设置采样率为1Hz
SHT30Cmder_setSampleRate(SHT30SR_1Hz);

这个细节很容易被忽略,导致配置失败。一个更完善的驱动设计,可以把“双发”逻辑封装在指令器内部,提供一个像 SHT30Cmder_ConfigSampleRate() 这样的函数,对用户更友好。

5.2 指令器的扩展性

目前指令器只实现了设置采样率。如果模块还有其他指令,比如设置温湿度报警阈值、查询固件版本等,我们可以很方便地扩展。只需要在头文件中增加新的枚举和函数声明,在 .c 文件中添加对应的指令数组构造函数即可。这种模块化设计使得功能扩展变得清晰而安全。

6. 实战集成与调试技巧:把驱动用起来

设计得再好,跑不起来也是白搭。下面我们以STM32的HAL库和FreeRTOS为例,看看如何把这个驱动集成到真实项目中,并分享几个我踩过的坑。

6.1 在裸机环境(无操作系统)中使用

在没有操作系统的单片机程序中,我们通常在串口接收中断服务函数里调用 SHT30Recver_Feed。

// 1. 在main.c中定义回调函数和发送函数
SHT30Data mySensorData;
void My_DataCallback(SHT30Data data) {
    mySensorData = data; // 保存到全局变量
    // 或者直接处理,比如刷新显示屏
    printf("Temp: %.2fC, Hum: %.2f%%\r\n", data.temp, data.humi);
}

void My_UART_Send(uint8_t *buf, uint16_t len) {
    HAL_UART_Transmit(&huart1, buf, len, 1000); // 假设使用UART1
}

// 2. 在main函数初始化
int main(void) {
    // ... HAL初始化,串口初始化等
    SHT30Recver_Init(My_DataCallback);
    SHT30Cmder_Init(My_UART_Send);
    // 如果需要,在这里发送配置指令(注意要发两次)
    // SHT30Cmder_setSampleRate(SHT30SR_1Hz);
    // HAL_Delay(50);
    // SHT30Cmder_setSampleRate(SHT30SR_1Hz);

    while (1) {
        // 主循环处理其他任务,数据会在中断中自动更新
        if (some_condition) {
            printf("Current Temp: %.2f\r\n", mySensorData.temp);
        }
        HAL_Delay(100);
    }
}

// 3. 在串口中断回调函数中喂数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        uint8_t rxByte = your_rx_buffer; // 获取收到的字节
        SHT30Recver_Feed(rxByte); // 喂给接收机
        HAL_UART_Receive_IT(&huart1, &rxByte, 1); // 重新开启接收中断
    }
}

这样,数据接收和解析完全在后台由中断驱动,主循环可以专注业务逻辑,系统响应非常及时。

6.2 在FreeRTOS环境中的使用

在RTOS中,我们可以创建一个专用的串口接收任务,或者使用队列(Queue)来传递字节。

// 创建一个任务用于处理串口接收
void UART_Receive_Task(void *argument) {
    uint8_t rxByte;
    for (;;) {
        // 假设xQueueReceive从串口驱动任务那里获取字节
        if (xQueueReceive(uart_rx_queue, &rxByte, portMAX_DELAY) == pdTRUE) {
            SHT30Recver_Feed(rxByte);
        }
    }
}

// 回调函数在RTOS中可能涉及临界区保护
void My_DataCallback(SHT30Data data) {
    // 将数据发送到其他任务的消息队列中,避免在回调函数中做耗时操作
    xQueueSend(sensor_data_queue, &data, 0);
}

在RTOS中,要特别注意回调函数的执行上下文。如果回调函数中需要操作共享资源(如全局变量、外设),可能需要使用信号量(Semaphore)或任务通知(Task Notification)来进行同步,防止数据竞争。

6.3 常见调试问题与解决

  1. 收不到数据/数据乱码:

    • 检查接线:TX/RX是否接反?VCC电压是否是3.3V?
    • 检查波特率:确保单片机串口初始化的波特率是 115200。我曾因为误设为9600而调试了半天。
    • 检查地线:确保单片机、模块、USB转串口工具(如果用了)三者共地。
    • 逻辑分析仪是神器:用逻辑分析仪抓一下串口线上的波形,能最直观地看到数据是否正确。
  2. 回调函数不被调用:

    • 检查帧头帧尾:用printf打印出接收到的原始字节,看看格式是否完全是 "Temp = ... Hum = ...\r\n"。注意SHT20和SHT30的字符串略有不同(Humi vs Hum),原始文章末尾的更新历史提到了这一点,驱动代码需要对应修改。
    • 检查RxMac配置:确认 _flag_header 和 _flag_ender 数组定义是否正确。
    • 检查缓冲区大小:_macBuf 数组(默认36字节)是否足够容纳一帧数据。
  3. 设置采样率无效:

    • 确认发送了两次指令:这是最容易出错的地方。
    • 检查发送函数:确保你注册给 SHT30Cmder_Init 的发送函数确实能正确地把字节发送到模块的RX引脚。
    • 指令间隔:两次发送之间需要有一点延时,比如50ms,让模块有时间处理模式切换。

7. 驱动优化与进阶思考

原始的驱动已经提供了一个非常优秀的框架,但在实际的大型或长期运行项目中,我们还可以从以下几个角度进行优化和增强。

7.1 增加超时与错误恢复机制

目前的接收机依赖于正确的帧尾 \r\n。如果传输过程中丢失了帧尾字符,这一帧数据就会一直留在缓冲区,直到下一帧的帧头到来将其覆盖,这可能导致数据更新延迟。我们可以引入一个超时机制。在 SHT30Recver_Feed 中记录每次喂数据的时间戳,如果超过一定时间(比如200ms)仍未收到帧尾,就调用 SHT30Recver_CleanupBuffer() 清空缓冲区,重置状态机,从错误中快速恢复。

7.2 支持多实例与线程安全

当前驱动使用静态全局变量,意味着一个程序里只能有一个SHT30传感器。如果项目需要同时监测两个房间的温湿度呢?我们可以将驱动结构体化,将 _onRecvData, _mac, _out 等变量封装到一个 SHT30_HandleTypeDef 结构体中。所有接口函数第一个参数改为这个句柄。这样就能创建多个独立的驱动实例,分别管理不同的传感器。同时,对于RTOS应用,在操作实例内部状态时,可以考虑加入互斥锁(mutex)来保证线程安全。

7.3 低功耗优化策略

对于电池供电的设备,功耗是关键。SHT30传感器本身在低速采样模式下功耗极低。我们的驱动可以与之配合,实现“采集-休眠”的循环。例如,设置采样率为0.1Hz(每10秒一次)。在回调函数中,拿到数据后,通过指令器将模块设置为“单次测量”模式(如果支持),或者直接关闭模块供电,然后让单片机进入深度睡眠。10秒后,单片机定时器唤醒,重新上电并初始化传感器,读取一次数据,如此循环。这样能极大延长设备续航。

7.4 数据滤波与校准

传感器数据可能会有微小波动或存在固定偏差。驱动层可以集成简单的软件滤波算法。例如,在回调函数中,我们不是直接上报原始数据,而是维护一个小的滑动窗口(比如最近5次读数),上报其平均值或中位数,能使读数更稳定。此外,如果已知传感器的误差曲线,可以在驱动层最后一步加上一个校准函数,对读取的原始值进行线性补偿,float calibrated_temp = raw_temp * 1.02 + 0.5;,提高数据的绝对精度。

经过这些设计和优化,我们的SHT30/SHT20驱动模块就从一个简单的数据读取工具,进化成了一个稳定、可靠、功能丰富且易于集成的嵌入式软件组件。它能够安静地在你的项目后台运行,准确可靠地提供环境数据,让你可以更专注于上层应用逻辑的开发。

STM32驱动SHT30与OLED的温湿度监测系统(IIC模拟时序实战) 本文详细介绍了基于STM32驱动SHT30温湿度传感器与OLED显示屏的监测系统开发过程,重点解析了IIC模拟时序的实现方法。通过硬件选型、I2C协议解析、传感器驱动开发和OLED显示实现等步骤,构建了一个低成本、高精度的环境监测方案,适合嵌入式开发初学者实践。 阅读详情

相关推荐

ESP32硬件IIC驱动SHT30:从零构建温湿度监测组件

本文详细介绍了如何使用ESP32通过硬件IIC驱动SHT30温湿度传感器,从零构建温湿度监测组件。内容包括ESP32与SHT30的硬件连接、I2C配置、数据读取与CRC校验,以及组件化开发和调试技巧,适合物联网开发新手快速上手。

weixin_30591551的博客 180

第 49 天:I2C 读取温湿度传感器(如 SHT30)

SHT30 是 Sensirion 推出的一款高精度数字温湿度传感器,具备稳定的性能表现与极低功耗,广泛应用于工业控制、智能家居、环境监测等领域。通过 I2C 接口与主控通信,SHT30 提供了极为简洁的数据读取命令与 CRC 校验机制,适合在嵌入式系统中快速集成部署。本文基于 ESP32 平台,完整展示通过 I2C 驱动 SHT30 获取温湿度数据的全过程,涵盖设备初始化、命令交互、数据读取与校验解析,配套标准 C++ 封装结构与调试建议,适用于对传感器通信实战有深入需求的工程开发者。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 2191

基于STM32与SHT40的嵌入式温湿度计设计

温湿度传感器是环境监测系统的核心感知单元,其精度、功耗与接口兼容性直接影响终端设备性能。SHT40作为新一代数字式温湿度传感器,凭借±0.2℃温度精度、I²C标准接口及微安级待机电流,成为资源受限嵌入式平台的理想选型。结合STM32F103系列MCU丰富的外设集成能力(如硬件I²C、RTC、ADC与PWM),可高效构建低功耗、高可靠性的便携式环境仪表。该技术路径广泛适用于智能楼宇、农业物联网、实验室监控等场景,尤其适合教学实践与小批量工程化开发。本文围绕SHT40与STM32协同设计展开,涵盖硬件接口规范、

weixin_36328210的博客 242

嵌入式传感器选型实战:SHT30在环境监测系统中的优势与陷阱

本文深入解析SHT30温湿度传感器在环境监测系统中的优势与潜在问题。通过对比DHT系列传感器,详细介绍了SHT30的高精度、低功耗和I2C接口特性,并提供硬件设计、软件驱动及系统集成中的实用技巧,帮助开发者规避实际部署中的常见陷阱,提升系统可靠性。

vv45678的博客 719

基于STM32的温湿度监测课程设计:从SHT30驱动到低功耗实战

嵌入式系统开发中,传感器数据采集是核心基础技术,涉及总线通信、时序控制与数据校验等原理。通过I2C等接口读取温湿度传感器,结合CRC校验与滤波算法,可提升数据可靠性,其技术价值在于实现环境参数的精准监控。典型应用场景包括智能家居、农业大棚与工业仓储。在STM32平台上,合理配置外设、优化电源与总线分配,能有效解决读数跳变与通信超时问题。本文围绕基于STM32的温湿度监测课程设计,详解SHT30驱动、OLED显示与报警逻辑,助你快速构建稳定原型。

weixin_29159127的博客 260

STM32 SHT20温湿度监测系统开发与设计

微控制器是现代电子系统中的核心组件,STM32微控制器系列由STMicroelectronics推出,具有高性能、低功耗的特性,广泛应用于工业控制、消费电子产品、医疗设备、物联网等领域。该系列微控制器基于ARM Cortex-M处理器,搭载了丰富的外设接口和高级功能,使其成为开发复杂应用的优选平台。在本章中,我们将从STM32微控制器的架构和特点开始,逐步深入探讨其系列成员间的差异、应用场景以及为何它们在工程师中广受欢迎。

weixin_35879493的博客 482

温湿度传感器SHT30驱动(STM32F103):高效、可靠的嵌入式解决方案

在物联网和嵌入式系统领域,温湿度传感器是不可或缺的关键组件。为了满足开发者对高效、可靠的温湿度数据采集需求,我们推出了基于STM32F103微控制器的SHT30温湿度传感器驱动程序。该驱动程序通过IIC协议与SHT30传感器进行通信,适用于72MHz主频的STM32F103系列微控制器。经过严格测试,代码可以直接使用,帮助开发者快速集成到自己的项目中。 ## 项目技术分析 ### IIC通信协

gitblog_09703的博客 953

STM32与SHT30温湿度传感器交互项目源码剖析

STM32微控制器以其高性能、低成本和丰富的外设选项,成为了众多嵌入式应用的首选解决方案。当我们将STM32与SHT30传感器结合时,可以构建出能够准确检测和响应温度与湿度变化的智能系统。这种系统广泛应用于环境监测、智能农业、医疗设备等领域。在本章中,我们将探讨STM32与SHT30传感器之间的基本交互原理,了解两者如何通过电气接口相互通信,以及如何通过软件层面的编程实现数据的读取和处理。

weixin_30591519的博客 710

基于STM32与SHT30的温湿度传感器模块设计

基于STM32与SHT30的温湿度传感器模块设计

hoiii187的博客 552

0.96寸OLED与SHT20温湿度传感器结合的IIC驱动实践

OLED(有机发光二极管)技术是一种先进的显示技术,以其自发光、高对比度、低能耗、超薄设计以及可弯曲等优势迅速在显示领域占据了一席之地。OLED屏幕上的每个像素点可以独立发光,这种特性使得屏幕可以实现真正的黑色显示,从而达到极高的对比度。除此之外,由于OLED屏幕的响应速度非常快,非常适合用于显示动态图像。

weixin_42174098的博客 665

SHT30与STM32的HAL库应用

本文详解SHT30温湿度传感器与STM32F103ZET6基于HAL库的开发,涵盖I²C通信、CRC校验、低功耗模式及硬件配置要点,适用于工业监测与物联网场景。

smartcontract5的博客 1046

STM32模拟IIC驱动SHT30温湿度传感器实战指南

本文详细介绍了如何在STM32平台上通过模拟IIC协议驱动SHT30温湿度传感器的完整实战方案。内容涵盖GPIO配置、IIC时序模拟、SHT30驱动实现及常见问题调试,提供经过验证的代码示例和优化建议,帮助开发者快速实现高精度环境监测应用。

e4f5g6h7的博客 877

Transformer——从原理、模型架构到内部细节介绍

Transformer模型是一种基于注意力机制的深度学习模型,最早由Google在2017年的论文《AttentionIsAllYouNeed》中提出。自其问世以来就迅速席卷了自然语言处理他(NLP)领域,并在各类主流任务上取得了新的突破,包括机器翻译、语言建模、序列标注和文本分类等。在NLP领域取得巨大成功后,迅速扩展到了计算机视觉(CV)领域,并带来了革命性的变化。这种基于自注意力机制的深度学习模型,不仅在NLP任务中力压群雄,也成为CV领域的新宠。

小拉拉的博客 1万+

SHT30-SHT31温湿度传感器驱动代码:项目推荐

SHT30-SHT31温湿度传感器驱动代码:项目推荐 【下载地址】SHT30-SHT31温湿度传感器驱动代码 这是一个专为SHT30和SHT31温湿度传感器设计的开源驱动代码项目,支持I2C通信协议,提供C、C++、Python等多种编程语言版本。开发者可以轻松地在各种应用场景中读取温度和湿度数据,项目代码简洁高效,易于...

gitblog_06751的博客 398

2025年最新Cesium学习示例:Cesium-Examples

2025年最新Cesium学习示例:Cesium-Examples

2403_88103571的博客 1011

博途 V15.1安装步骤

温馨提醒:安装此软件电脑配置至少应满足以下要求 处理器 CoreTM i5-3320M 3.3 GHz 或相当 内存 至少8G 硬盘 300 GB SSD 显示器 15.6' 宽屏显示 (1920 x 1080) 1.双击打开【Siemens v15.1】文件夹。 2.鼠标右击【STEP 7 BasicProfess...

谢谢关注“小鱼教你模数电”,各平台同号 9万+

ESP32实战:I2C驱动SHT30温湿度传感器的完整开发指南

本文详细介绍了如何使用ESP32通过I2C协议驱动SHT30温湿度传感器,包括硬件连接、I2C通信协议解析、CRC校验实现、数据转换与校准技巧,以及ESP-IDF驱动封装和性能优化方法。SHT30作为高精度温湿度传感器,适用于嵌入式开发中的环境监测项目,提供±0.3°C的温度精度和快速响应。

k9l0m1的博客 530

企业微信会话存档SDK集成与动态库加载实战

本文详细解析了企业微信会话存档SDK的集成与动态库加载实战,重点解决Windows与Linux环境下动态库加载的差异问题。通过实战案例和优化建议,帮助开发者高效完成企业微信API集成,确保合规存档功能稳定运行。

weixin_26934905的博客 465

高效精准:STM32F103与SHT30温湿度传感器驱动代码推荐

高效精准:STM32F103与SHT30温湿度传感器驱动代码推荐 【下载地址】STM32F103--SHT30温湿度传感器驱动代码 本仓库提供了针对STM32F103系列微控制器的SHT30温湿度传感器驱动程序。SHT30是一款高精度、低功耗的数字温湿度传感器,广泛应用于环境监控、智能家居、健康护理等领域。STM32F1...

gitblog_09720的博客 463

全球最大光伏电池缺陷异常检测数据集PVELAD【发布】

下载地址 1:GitHub - binyisu/PVEL-AD 下载地址 2:http://aihebut.com/col.jsp?id=118 下载地址 3:NAVEDownload 竞赛测试系统:Photovoltaic cell anomaly detection | Kaggle 一、简介 PVEL-AD 数据集又叫做EL2021数据集是用于对光伏电池异常缺陷检测方法进行基准测试的数据集,重点是光伏电池工业检测。PVEL-AD包含 36,543 张具有各种内部缺陷和异构背...

苏打水的杯子的博客 2万+

Centos7.6操作系统安装+Bond配置(600GB磁盘版本)

1.安装前准备工作 准备centos7.6操作系统镜像 CentOS-7-x86_64-DVD-1810.iso 服务器安装一般都是在BMC界面操作,所以安装前需要在BMC界面挂载好操作系统镜像 重启服务器后自动进入安装界面。 华为大数据集群安装操作系统配置

小时光 6013

【亲测免费】 轻松集成SHT30传感器:高效、稳定的STM32驱动代码

轻松集成SHT30传感器:高效、稳定的STM32驱动代码 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在物联网和嵌入式系统领域,温湿度传感器是不可或缺的组件。SHT30作为一款高性能的数字温湿度传感器,广泛应用于各种环境监测和数据采集场景。为了帮助开发者更便捷地集成SHT30传感器,我们推出了基于STM32F103的SHT30驱动代码。该驱动代码采用模拟IIC通信方...

gitblog_09793的博客 784

AI智算-K8s如何利用GPFS分布式并行文件存储加速训练or推理

GPFS(General Parallel File System,通用并行文件系统)是由 IBM 开发的高性能分布式文件系统,最初设计于 1990 年代,用于满足高性能计算(HPC)环境对大规模数据存储和访问的需求。GPFS 现已广泛应用于企业级存储、云计算、大数据分析、人工智能和媒体处理等领域。它以其高性能、可扩展性和可靠性著称,能够支持从小型集群到超大规模系统的各种部署场景。

Kason_iWiki 1132

【亲测免费】 快速上手:STM32F103C8T6硬件IIC驱动SHT30温湿度传感器

快速上手:STM32F103C8T6硬件IIC驱动SHT30温湿度传感器 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在物联网和嵌入式系统开发中,温湿度传感器是常见的环境监测设备。SHT30是一款高精度、低功耗的温湿度传感器,广泛应用于智能家居、工业自动化等领域。为了帮助开发者快速实现STM32F103C8T6微控制器与SHT30传感器的通信,我们推出了这个开源项目...

gitblog_09797的博客 803

17 指挥AI写Mamba相关模型代码,快速适配大模型场景

本文为《30天掌控AI编程:从指令到落地,手把手教你指挥AI写代码》系列第十七篇,属于第三阶段多场景实战核心内容。本篇聚焦当下大模型领域热门的**Mamba架构**,针对零基础大模型开发、无深度学习基础的使用者,拆解指挥AI生成Mamba基础模型、微调适配、推理部署代码的核心方法,覆盖Mamba基础模块搭建、简易序列建模、小样本微调、本地推理等高频场景,提供可直接复用的高质量指令模板、完整可运行代码、环境配置与避坑指南,无需精通Transformer、状态空间模型等底层原理,轻松上手Mamba大模型开发。

coreopt的博客 61

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

从零构建:SHT30温湿度传感器的嵌入式系统全栈开发指南

本文详细介绍了从零开始构建基于SHT30温湿度传感器的嵌入式系统全栈开发指南。涵盖硬件架构设计、嵌入式固件开发、云端数据集成及Web可视化实现,特别强调I2C接口的应用与优化,适合物联网和智能硬件开发者快速掌握高精度环境监测方案。

wdx012345的博客 799

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: UE4蓝图实战:从零构建交互式开关门系统
下一篇: MATLAB串口通讯实战:从零搭建实时数据监控系统(附完整代码)
php55
博客等级 码龄15年 51粉丝 1553原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值