#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <OneWire.h>
#define SCL 16
#define SDA 17
#define ONE_WIRE_BUS 11
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
static TaskHandle_t xGatewayTask = NULL; // 网关线程
typedef struct{
uint8_t type; // 数据类型 1
uint16_t year; // 年
uint8_t month; // 月
uint8_t day; // 日
uint8_t hour; // 时
uint8_t minute; // 分
uint8_t second; // 秒
uint8_t week; // 星期
}Data_Time;
typedef struct{
uint8_t type; // 数据类型 2
float temperature; //温度
}Data_Temperature;
// 温度传感器获取
void temperature_task(void* param_t){
OneWire oneWire(ONE_WIRE_BUS); // 初始化一个OneWire对象来控制1-Wire总线
DallasTemperature sensors(&oneWire); // 初始化一个DallasTemperature对象来使用DS18B20
sensors.begin();
while(1){
sensors.requestTemperatures();
Data_Temperature *temp = (Data_Temperature *)pvPortMalloc(sizeof(Data_Temperature));
temp->type=2;
temp->temperature = sensors.getTempCByIndex(0);
// 发送数据,使用指针作为附件
if(xTaskNotify(xGatewayTask, (uint32_t)temp, eSetValueWithoutOverwrite)!=pdPASS){
// 不进行数据覆盖,但如果发送失败,则需要就地释放空间,否则运行时间长了会导致溢出
vPortFree(temp);
}
vTaskDelay(random(200,1000));
}
}
// 时钟获取线程
void clock_task(void *param_t){
RTC_DS1307 rtc; // 定义时钟
if (rtc.begin()) {
while(1){
DateTime now = rtc.now();
Data_Time *time = (Data_Time *)pvPortMalloc(sizeof(Data_Time));
time->type=1;
time->year = now.year();
time->month = now.month();
time->day = now.day();
time->hour = now.hour();
time->minute = now.minute();
time->second = now.second();
time->week = now.dayOfTheWeek();
// 发送数据,使用指针作为附件
if(xTaskNotify(xGatewayTask, (uint32_t)time, eSetValueWithoutOverwrite)!=pdPASS){
// 释放空间
vPortFree(time);
}
vTaskDelay(random(200,1000)); // 每间隔一段时间上报一次时间
}
}
vTaskDelete(NULL); // 自我终结
}
// 物联网网关
void gateway_task(void *param_t){
uint32_t annex; // 附件数据
void *dp= NULL; // 接收邮件附件用的指针
LiquidCrystal_I2C lcd(0x27, 20, 4);
lcd.init();
lcd.backlight();
char line[4][21]; //数据
while(1){
if(xTaskNotifyWait(0x00, 0x00, &annex, 0) == pdTRUE){
dp = (void*)annex;
char *type = (char *)dp;
if(*type==1){
// 时间数据
Data_Time *time = (Data_Time *)dp;
int second = time->second;
int minute = time->minute;
int hour = time->hour;
int day = time->day;
int month = time->month;
int year = time->year;
int week = time->week;
sprintf(line[0], " %04d - %02d - %02d", year, month, day);
sprintf(line[1], " %s",daysOfTheWeek[time->week]);
sprintf(line[2], " %02d : %02d : %02d", hour, minute, second);
for(int i=0; i<3; i++){
lcd.setCursor(0, i);
lcd.print(line[i]);
}
}else if(*type==2){
// 温度数据
Data_Temperature *temp = (Data_Temperature *)dp;
sprintf(line[3], " Temperature : %.2f", temp->temperature);
lcd.setCursor(0, 3);
lcd.print(line[3]);
}
vPortFree(dp); // 一定要释放附件空间
}
vTaskDelay(200);
}
}
void setup() {
Serial.begin(115200);
// Serial.println("Hello, ESP32-S3!");
Wire.begin(SDA, SCL); // 初始化I2C总线
xTaskCreate(gateway_task, "GATEWAY", 10240, NULL, 1, &xGatewayTask);
xTaskCreate(clock_task, "CLOCK", 10240, NULL, 1, NULL);
xTaskCreate(temperature_task, "TEMP", 10240, NULL, 1, NULL);
vTaskDelete(NULL); // 自宫
}
void loop() {
delay(3000);
}
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
rtc1:GND
rtc1:5V
rtc1:SDA
rtc1:SCL
rtc1:SQW
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
temp1:GND
temp1:DQ
temp1:VCC