#include <freertos/message_buffer.h>
#include "DHTesp.h"
#define DHT_PIN 15
#define LDR_PIN 5
#define BUFFER_SIZE 512 // 缓冲区大小
#define PH {0X55, 0XAA, 0X89} // 包头固定字符串
const char HEAD[3]=PH;
typedef struct{ // 数据包结构体
char head[3]; // 数据表其实标志(包头,包花)
uint8_t data_type; // 数据包类型
uint8_t data_length; // 数据包包体长度
char reserve[3]; // 无实际用途,用于数据对齐
}Package_Head;
typedef struct{ // DHP22 数据结构体
Package_Head head; // 包头
float temperature; // 温度
float humidity; // 湿度
}DHT22_Package;
typedef struct{ // LDR 数据结构体
Package_Head head; // 包头
float lux; // 光照度
}LDR_Package;
MessageBufferHandle_t xMessageBuffer = NULL; // 消息缓冲区句柄
// 温湿度传感器数据获取线程
void dht22_task(void* param_t){
DHTesp dhtSensor;
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
size_t psize = sizeof(DHT22_Package); // 数据包大小
Package_Head head = {PH, 1, psize- sizeof(Package_Head)};
DHT22_Package pck = {head, 0, 0};
size_t size;
while(1){
TempAndHumidity data = dhtSensor.getTempAndHumidity();
// 灌装数据
pck.temperature = data.temperature;
pck.humidity = data.humidity;
size = xMessageBufferSend(xMessageBuffer, // 消息缓冲句柄
(void*)&pck, // 传输的消息体首地址指针
psize, // 本次传输的数据大小
portMAX_DELAY); // 传输等待超时时间
if(size != psize){
printf("[DHTP] 数据发送失败,可能造成数据不完整的混乱\n");
}else{
// printf("[DHTP] 数据发送成功,大小 : %d\n",size);
}
vTaskDelay(random(1000,3000));
}
}
// 光照度传感器数据获取线程
void ldr_task(void* param_t){
const float GAMMA = 0.7;
const float RL10 = 50;
size_t psize = sizeof(LDR_Package); // 数据包大小
Package_Head head = {PH, 2, psize- sizeof(Package_Head)};
LDR_Package pck = {head, 0};
size_t size;
while(1){
int analogValue = analogRead(LDR_PIN); // 读取引脚的模拟量
// 一下是一顿猛如虎的操作,具体做了些什么请参照LDR的文档,8191是精度,表示13位精度
float voltage = analogValue / 8191. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
pck.lux = lux;
size = xMessageBufferSend(xMessageBuffer, // 消息缓冲句柄
(void*)&pck, // 传输的消息体首地址指针
psize, // 本次传输的数据大小
portMAX_DELAY); // 传输等待超时时间
if(size != psize){
printf("[LDRP] 数据发送失败,可能造成数据不完整的混乱\n");
}else{
// printf("[DHTP] 数据发送成功,大小 : %d\n",size);
}
vTaskDelay(random(1000,3000));
}
}
// 消息处理器
void processor(char *data, size_t size){
/* 正确的消息处理方式如下:
* 1. 首先判断包头是否正确,如果不正确则直接扔掉数据包
* 2. 判断长度是否正确,如果不正确则扔掉数据包
* 3. 取出数据
*/
if(data[0] == HEAD[0] && data[1] == HEAD[1] && data[2] == HEAD[2]){
Package_Head *head= (Package_Head *)data;
if(head->data_length == size-sizeof(Package_Head)){
// printf("[PROC] 数据包到达,类型 :%02X , 长度 : %d\n", data[3], head->data_length);
switch(data[3]){
case 0x01: // DHT22类型数据
{
DHT22_Package *pak = (DHT22_Package *)data;
printf("[PROC] DHT22数据到达,Temperature : %.2f°C , Humidity : %.2f%%\n",
pak->temperature, pak->humidity);
break;
}
case 0x02: // LDR类型数据
{
LDR_Package *pak = (LDR_Package *)data;
printf("[PROC] LDR数据到达,光照 : %.2f\n",
pak->lux);
break;
}
default:
{
printf("[PROC] 未知数据包 : %02X\n",data[3]);
}
}
}else{
printf("[PROC] 数据长度检测失败 : %d\n", data[4]);
}
}else{
printf("[PROC] 包头检测失败 : %02X , %02X , %02X\n", data[0], data[1], data[2]);
}
}
/**
* @brief 数据处理器线程
* 该函数优先级建议比数据存入线程高,保证数据先处理(视具体情况而定)
* 当发现缓冲区中有数据时,先处理缓冲区数据,确保所有数据处理完成之后再进行下一次等待
**/
void processor_task(void* param_t){
size_t msize; // 消息的长度
size_t size; // 接收的长度
while(1){
msize = xMessageBufferNextLengthBytes(xMessageBuffer); // 获得下一条消息的长度
while(msize>0){
char *data = (char *)pvPortMalloc(msize); // 开辟空间准备接收消息
size = xMessageBufferReceive(xMessageBuffer, // 消息缓冲区句柄
(void *)data, // 接收数据的首地址
msize, // 最大接收数据长度
portMAX_DELAY); // 等待时间
if(size == msize){
// 正确收到了消息
processor(data, size);
}else{
printf("[PROC] 消息接收错误,应接收 : %d , 实际接收 : %d\n", msize, size);
}
vPortFree(data); // 释放空间
msize = xMessageBufferNextLengthBytes(xMessageBuffer); // 获得下一条消息的长度
}
vTaskDelay(1000);
}
}
void setup() {
Serial.begin(115200);
Serial.println("Hello, ESP32-S3!");
xMessageBuffer = xMessageBufferCreate(BUFFER_SIZE); // 初始化消息缓冲区
if (xMessageBuffer == NULL)
{
printf("创建缓冲区失败,内存不足!\n");
}
else
{
// 创建线程
xTaskCreate(dht22_task, "DHT22", 1024 * 4, NULL, 1, NULL);
xTaskCreate(ldr_task, "LDR", 1024 * 4, NULL, 1, NULL);
xTaskCreate(processor_task, "PROC", 1024 * 4, NULL, 1, NULL);
}
}
void loop() {
delay(10);
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:11
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:20
esp:21
esp:35
esp:36
esp:37
esp:38
esp:39
esp:40
esp:41
esp:42
esp:45
esp:46
esp:47
esp:48
esp:3V3.1
esp:3V3.2
esp:RST
esp:5V
esp:GND.1
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:GND.4
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
ldr1:VCC
ldr1:GND
ldr1:DO
ldr1:AO