ESP32使用RMT外设单总线设备驱动(WS2812/DS18B20/DHT11)

2024-06-04 01:12

本文主要是介绍ESP32使用RMT外设单总线设备驱动(WS2812/DS18B20/DHT11),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ESP32使用RMT外设单总线设备驱动(WS2812/DS18B20/DHT11)


  • 📍相关红外遥控 (RMT)介绍:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/rmt.html
  • 🎈相关内容参考:https://docs.espressif.com/projects/espressif-esp-faq/zh_CN/latest/software-framework/peripherals/rmt.html
  • 🔬测试开发板型号:YD-ESP32-S3esp32-devkitc-1
  • 🔧基于Arduino开发平台

✨目前只有 ESP32-S3 这一款芯片的 RMT 带有 DMA。这样 RMT 可以避免 Wi-Fi 或蓝牙等中断的干扰。

  • 📄Arduino ESP32通过Arduino API当前支持以下外围外设情况:
    在这里插入图片描述

📘RMT 概述

RMT 是一个红外发送和接收控制器,可通过软件加解密多种红外协议。RMT 模块可以实现将模块内置 RAM 中的脉冲编码转换为信号输出,或将模块的输入信号转换为脉冲编码存入 RAM 中。此外,RMT 模块可以选择是否对输出信号进行载波调制,也可以选择是否对输入信号进行滤波和去噪处理。

  • RMT 共有八个通道,编码为 0 ~ 7,各通道可独立用于发送或接收信号:
    • 0 ~ 3 通道专门用于发送信号;(针对ESP32S3)
    • 4 ~ 7 通道专门用于接收信号。(针对ESP32S3)
    每个发送通道和接收通道分别有一组功能相同的寄存器。
  • 🌿ESP32共有8个MEM block与读和/或写共享
  • 🌿ESP32-S2共有4个MEM block与读和/或写共享
  • 🌿ESP32-S3有4个读MEM block和4个写MEM block
  • 🌿ESP32-C3有2个读MEM block和2个写MEM block
特性

• 四个通道支持发送.
• 四个通道支持接收.
• 可编程配置多个通道同时发送
• RMT 的八个通道共享 384 x 32-bit 的 RAM
• 发送脉冲支持载波调制
• 接收脉冲支持滤波和载波解调
• 乒乓发送模式
• 乒乓接收模式
• 发射器支持持续发送
• 发送通道 3 支持 DMA 访问。( 针对ESP32S3,其他型号,RMT没有DMA)
• 接收通道 7 支持 DMA 访问 ( 针对ESP32S3,其他型号,RMT没有DMA)

📙ESP 芯片上的 RMT 外设应用场景

可以实现红外遥控,LED 灯带点亮,D-shot 电机控制,以及单总线设备(例如:DS18B20,DHT11/21/22/,AM2301/AM2302)等.

📗驱动ws2812

🌟RMT驱动ws2812潜在隐患
  • 🌿在使用 ESP32 RMT 控制 WS2812 灯带,当与 Wi-Fi 或者蓝牙同时使用时,会出现部分数据帧异常的问题。

这个问题在非 ESP32-S3 的芯片上很难解决,因为 RMT 刷 LED(尤其是很多个 LED 的时候)严重依赖中断,且不支持 DMA,需要软件在中断切换 ping-pong buffer,如果中断没有及时响应,就会出现问题。默认情况下 (即只设置了一个存储块),是两个灯的数据量就要进一次中断来切换 ping-pong buffer

  • 针对Arduino开发平台,RMT DMA方式,目前还不支持。
🔰WS281X差异
  • 🍃WS2811: (2.5us bit time, 400Kbps)
T0H: 0.5us <-- 0 bit
T0L: 2.0us
T1H: 1.2us <-- 1 bit
T1L: 1.3us
RES: 50us
  • 🍃WS2812: (1.25us bit time, 800Kbps)
T0H: 0.35us <-- 0 bit
T0L: 0.8us
T1H: 0.7us <-- 1 bit
T1L: 0.6us
RES: 50us
  • 🍃WS2812b: (1.25us bit time, 800Kbps)
T0H: 0.4us <-- 0 bit
T0L: 0.85us
T1H: 0.8us <-- 1 bit
T1L: 0.45us
RES: 50us
📑驱动WS2812测试代码
  • 🔖测试对象:ESP32-S3-DevKitC-1,板载带一颗WS2812灯珠。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "Arduino.h"#include "esp32-hal.h"// The effect seen in ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED
#if CONFIG_IDF_TARGET_ESP32S2
#define BUILTIN_RGBLED_PIN   18
#elif CONFIG_IDF_TARGET_ESP32S3
#define BUILTIN_RGBLED_PIN   48
#elif CONFIG_IDF_TARGET_ESP32C3
#define BUILTIN_RGBLED_PIN   8
#else
#define BUILTIN_RGBLED_PIN   21   // ESP32 has no builtin RGB LED
#endif#define NR_OF_LEDS   8*4
#define NR_OF_ALL_BITS 24*NR_OF_LEDS//
// Note: This example uses Neopixel LED board, 32 LEDs chained one
//      after another, each RGB LED has its 24 bit value 
//      for color configuration (8b for each color)
//
//      Bits encoded as pulses as follows:
//
//      "0":
//         +-------+              +--
//         |       |              |
//         |       |              |
//         |       |              |
//      ---|       |--------------|
//         +       +              +
//         | 0.4us |   0.85 0us   |
//
//      "1":
//         +-------------+       +--
//         |             |       |
//         |             |       |
//         |             |       |
//         |             |       |
//      ---+             +-------+
//         |    0.8us    | 0.4us |rmt_data_t led_data[NR_OF_ALL_BITS];rmt_obj_t* rmt_send = NULL;void setup() 
{Serial.begin(115200);if ((rmt_send = rmtInit(BUILTIN_RGBLED_PIN, RMT_TX_MODE, RMT_MEM_64)) == NULL){Serial.println("init sender failed\n");}float realTick = rmtSetTick(rmt_send, 100);Serial.printf("real tick set to: %fns\n", realTick);}int color[] =  { 0x55, 0x11, 0x77 };  // RGB value
int led_index = 0;void loop() 
{// Init data with only one led ONint led, col, bit;int i=0;for (led=0; led<NR_OF_LEDS; led++) {for (col=0; col<3; col++ ) {for (bit=0; bit<8; bit++){if ( (color[col] & (1<<(7-bit))) && (led == led_index) ) {led_data[i].level0 = 1;led_data[i].duration0 = 8;led_data[i].level1 = 0;led_data[i].duration1 = 4;} else {led_data[i].level0 = 1;led_data[i].duration0 = 4;led_data[i].level1 = 0;led_data[i].duration1 = 8;}i++;}}}// make the led travel in the pannelif ((++led_index)>=NR_OF_LEDS) {led_index = 0;}// Send the datarmtWrite(rmt_send, led_data, NR_OF_ALL_BITS);delay(100);
}

📗驱动DS18B20测试代码

  • 🥕所需库:https://github.com/junkfix/esp32-ds18b20
  • 📍ESP32S3 ESP-IDF环境是支持的,官方RMT DS18B20例程:https://github.com/espressif/esp-idf/tree/c7bbfaee/examples/peripherals/rmt/onewire
📗驱动DS18B20d代码
  • 🌿依赖库:esp32-ds18b20
    在这里插入图片描述
  • 该库如果使用esp32S3,需要DS18b20地址才能读取到数据,否则数据返回是OWR_BAD_DATA,使用esp32不存在这个问题。
  • 🔖测试对象:ESP32-devkitc-1
//DS18B20数据引脚:ESP32-devkitc-1	-->  D13
#include "OneWireESP32.h"
const uint8_t MaxDevs = 1;float currTemp[MaxDevs];void tempTask(void *pvParameters){//endfor(;;){OneWire32 ds(13, 0, 1, 0); //gpio pin, tx, rx, parasite power// There are 8 RMT channels (0-7) available on ESP32 for tx/rxuint64_t addr[MaxDevs];//uint64_t addr[] = {//	0x183c01f09506f428,//	0xf33c01e07683de28,//};//to find addressesuint8_t devices = ds.search(addr, MaxDevs);for (uint8_t i = 0; i < devices; i += 1) {Serial.printf("%d: 0x%llx,\n", i, addr[i]);//char buf[20]; snprintf( buf, 20, "0x%llx,", addr[i] ); Serial.println(buf);}ds.request();vTaskDelay(750 / portTICK_PERIOD_MS);for(byte i = 0; i < MaxDevs; i++){uint8_t err = ds.getTemp(addr[i], currTemp[i]);if(err){const char *errt[] = {"", "CRC", "BAD","DC","DRV"};Serial.print(i); Serial.print(": "); Serial.println(errt[err]);}else{Serial.print(i); Serial.print(": "); Serial.println(currTemp[i]);}}vTaskDelay(3500 / portTICK_PERIOD_MS);}
} // tempTaskvoid setup() {delay(1000);Serial.begin(115200);xTaskCreatePinnedToCore(tempTask, "tempTask", 4096,  NULL,  1,  NULL, 0);
}void loop() {}
  • 🔖打印效果:
    在这里插入图片描述
  • 📒针对esp32S3代码调整
//针对esp32S3 RMT驱动代码,兼容ESP32
#include "OneWireESP32.h"
const uint8_t MaxDevs = 1;float currTemp[MaxDevs];void tempTask(void *pvParameters){//ESP32S3 TX:0-3  RX:4-7OneWire32 ds(13, 0, 7, 0); //gpio pin, tx, rx, parasite power// There are 8 RMT channels (0-7) available on ESP32 for tx/rxuint64_t addr[MaxDevs];// uint64_t addr[] = {//   0x43011939241f7b28,	//需要填写DS18B20地址//};//to find addresses
//	uint8_t devices = ds.search(addr, MaxDevs);// for (uint8_t i = 0; i < devices; i += 1) {// 	Serial.printf("%d: 0x%llx,\n", i, addr[i]);// 	//char buf[20]; snprintf( buf, 20, "0x%llx,", addr[i] ); Serial.println(buf);// }//endfor(;;){uint8_t devices = ds.search(addr, MaxDevs);Serial.printf("%d: 0x%llx,\n",devices , addr[0]);ds.request();vTaskDelay(750 / portTICK_PERIOD_MS);for(byte i = 0; i < MaxDevs; i++){uint8_t err = ds.getTemp(addr[i], currTemp[i]);if(err){const char *errt[] = {"", "CRC", "BAD","DC","DRV"};Serial.print(i); Serial.print(": "); Serial.println(errt[err]);}else{Serial.print(i); Serial.print(": "); Serial.println(currTemp[i]);}}vTaskDelay(3000 / portTICK_PERIOD_MS);}
} // tempTaskvoid setup() {delay(1000);Serial.begin(115200);xTaskCreatePinnedToCore(tempTask, "tempTask", 2048,  NULL,  1,  NULL, 0);
}void loop() {}

在这里插入图片描述

📗RMT驱动DHT11

  • 🍁DHT11
    在这里插入图片描述

  • 🌿依赖库:dhtESP32-rmt
    在这里插入图片描述

  • 🔖支持DHT11/21/22/,AM2301/AM2302这些传感器。
🔬函数说明
  • 🌿uint8_t read_dht(float &temperature, float &humidity, uint8_t pin, uint8_t dhttype = DHT22, uint8_t rx= 1);
  • 🎉针对ESP32S3型号,rx通道配置4 - 7。ESP32可以任意配置:0 - 7,其他esp32型号,具体参照对应参考手册,收发通道是否共享。
  • 📝测试代码:
//DHT11数据引脚:ESP32-devkitc-1	-->  D13
//esp32-s3-devkitc-1  -->GPIO13
#include <dhtESP32-rmt.h>float temperature = 0.0;
float humidity = 0.0;/*
void tempTask(void *pvParameters){for(;;){uint8_t error=read_dht(temperature, humidity, 13, DHT22, 1);if(error){Serial.println(error);}else{Serial.println(temperature);Serial.println(humidity);}		vTaskDelay(3000 / portTICK_PERIOD_MS);}
}
/* tempTask */void setup() {delay(1000);Serial.begin(115200);//xTaskCreatePinnedToCore(tempTask, "tempTask", 8192,  NULL,  1,  NULL, 0);
}void loop() {//read_dht(temperature, humidity, pin, type (DHT11, DHT21, DHT22, AM2301, AM2302), RMT channel (0-7) uint8_t error=read_dht(temperature, humidity, 13, DHT11, 0);if(error){Serial.println(error);}else{Serial.println(temperature);Serial.println(humidity);}delay(3000);	
}/*
Error codes
0: OK
1: TOO_SOON
2: DRIVER
3: TIMEOUT
4: NACK
5: BAD_DATA
6: CHECKSUM
7: UNDERFLOW
8: OVERFLOW
*/

在这里插入图片描述

这篇关于ESP32使用RMT外设单总线设备驱动(WS2812/DS18B20/DHT11)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1028640

相关文章

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi