物联网技术是指通过互联网将各种设备、传感 器、控制器等连接在一起,形成一个能够实时互通信息的网络。物联网技术的基本原理是通过传感器采集设备产生的数据,并通过控制器进行处理和控制,最终将数据传输到互联网上,实现设备之间的智能交互。物联网技术的核心特点是实时性、数据共享、智能化和互联性。物联网技术的实时性意味着设备和传感器能够即时收集和传输数据,使得用户可以实时了解设备状态和环境情况。数据共享可 以使不同设备之间共享数据,实现更高效的资源利用和协同工作。智能化指的是物联网设备具备处理和分析数据的能力,可以根据用户需求自动调整设备工作模式。互联性表示物联网技术可以实现设备与设备、设备与人之间的无缝连接和交互,实现更强大的功能和用户体验。物联网技术广泛应用于智能家居、智能交通、智慧城市等领域,为人们的生活带来便利和智能化。
室内照明灯系统硬件如图2.1所示分,为三部分:基于ESP32 S3的服务端、基于ESP32 PICO的传感器端与小爱音箱。其中,ESP32 S3服务端使用的是乐鑫的ESP32 S3 LCD EV开发板。如图2.2所示,主要负责与小爱音箱通信,接收传感器端数据、LCD实时显示传感器数据以及灯光的控制;ESP32 PICO传感器端为单独设计的ESP32板卡,如图2.3所示,主要功能为采集MPU6050数据与SHT30数据应通过BLE传输到服务端;小爱音箱主要是与服务端实现语音交互功能。
图2.1 系统架构图
图2.2ESP32 S3 LCD EV
图2.3 传感器端板块
室内照明灯系统软件为服务端代码与传感器端代码。服务端代码基于Arduino并通过FreeRTOS实现多任务处理,如图2.4所示。传感器端则基于Arduino框架完成传感器数据采集与蓝牙传输,如图2.5所示。
服务端代码:
#include "BLEDevice.h"
#include <Arduino.h>
#include <lvgl.h>
#include <ESP_Panel_Library.h>
#include <ESP_IOExpander_Library.h>
// #include <examples/lv_examples.h>
//#include <demos/lv_demos.h>
#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT
#include <Blinker.h>
#include <Adafruit_NeoPixel.h>
char auth[] = "044be84a71f9";
char ssid[] = "C_WIFI";
char pswd[] = "C88888888";
\
ESP_Panel *panel = NULL;
// 蓝牙相关定义
// Default Temperature is in Celsius
// Comment the next line for Temperature in Fahrenheit
#define temperatureCelsius
// BLE Server name (the other ESP32 name running the server sketch)
#define bleServerName "ESP32_HOME"
/* UUID's of the service, characteristic that we want to read*/
// BLE Service
static BLEUUID bmeServiceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
// BLE Characteristics
#ifdef temperatureCelsius
// Temperature Celsius Characteristic
static BLEUUID temperatureCharacteristicUUID("cba1d466-344c-4be3-ab3f-189f80dd7518");
#else
// Temperature Fahrenheit Characteristic
static BLEUUID temperatureCharacteristicUUID("f78ebbff-c8b7-4107-93de-889a6a06d408");
#endif
// Humidity Characteristic
static BLEUUID humidityCharacteristicUUID("ca73b3ba-39f6-4ab3-91ae-186dc9577d99");
// LEDSTATE Characteristic
static BLEUUID LEDCharacteristicUUID("553FF727-642D-493B-9D41-62AED7808700");
// Flags stating if should begin connecting and if the connection is up
static boolean doConnect = false;
static boolean connected = false;
// Address of the peripheral device. Address will be found during scanning...
static BLEAddress *pServerAddress;
// Characteristicd that we want to read
static BLERemoteCharacteristic *temperatureCharacteristic;
static BLERemoteCharacteristic *humidityCharacteristic;
static BLERemoteCharacteristic *LEDStateCharacteristic; // Led控制存储变量
// Activate notify
const uint8_t notificationOn[] = {0x1, 0x0};
const uint8_t notificationOff[] = {0x0, 0x0};
// Variables to store temperature and humidity
String temperatureChar;
String humidityChar;
String LEDStateChar;
String Humidity = "00000";
String Temper = "00000";
lv_obj_t *title_label;
lv_obj_t *temp_label;
lv_obj_t *humi_label;
String Humidity_text;
String Temper_test;
// Flags to check whether new temperature and humidity readings are available
boolean newTemperature = false;
boolean newHumidity = false;
boolean newLEDState = false;
int flag = 2;
#define LV_BUF_SIZE (ESP_PANEL_LCD_H_RES * 20)
#define RGB_1 "RGBKey"
BlinkerRGB WS2812(RGB_1);
#define PIN 4
#define NUMPIXELS 1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);
uint8_t colorR, colorG, colorB;
uint8_t colorW; // 获取亮度
uint8_t colorT; // 获取色温
uint8_t cold; // 白光输出值
uint8_t warm; // 黄光输出值
bool wsState;
bool COLORM; // 彩灯模式
bool READINGM; // 阅读模式
uint8_t wsMode = BLINKER_CMD_MIOT_DAY;
/*定义信号量*/
SemaphoreHandle_t lvgl_mux = NULL; // LVGL mutex
/*线程入口声明*/
void TaskAPPStart();
void ThreadBlinkerEntry(void *pvParameters); // Binker线程入口
void ThreadLVGLEntry(void *pvParameters); // LVGL线程入口
void ThreadSensorEntry(void *pvParameters); // Sensor线程入口
/*定义线程句柄*/
TaskHandle_t ThreadBlinker; // Blinker线程
TaskHandle_t ThreadLVGL; // LVGL线程
TaskHandle_t ThreadSensor; // Sensor线程
void pixelShow() // RGB控制函数
{
pixels.setBrightness(colorW);
for (int i = 0; i < NUMPIXELS; i++)
{
pixels.setPixelColor(i, colorR, colorG, colorB);
}
pixels.show();
}
void LedControl(float x, int y) // CW控制函数(X:亮度、Y:色温)
{
y = 100 - y;
cold = x / 100 * y; // cold_tmp是PWM冷灯珠的占空比
warm = x / 100 * (100 - y); // warm_tmp是PWM冷灯珠的占空比:
}
void ws2812_callback(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value) // RGB2812回调函数
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
BLINKER_LOG("R value: ", r_value);
BLINKER_LOG("G value: ", g_value);
BLINKER_LOG("B value: ", b_value);
BLINKER_LOG("Rrightness value: ", bright_value);
colorR = r_value;
colorG = g_value;
colorB = b_value;
colorW = bright_value;
pixelShow();
}
uint32_t getColor()
{
uint32_t color = colorR << 16 | colorG << 8 | colorB;
return color;
}
void miotPowerState(const String &state) // 用户自定义电源类操作的回调函数:
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON)
{
digitalWrite(LED_BUILTIN, HIGH);
BlinkerMIOT.powerState("on");
BlinkerMIOT.print();
wsState = true;
if (colorW == 0)
colorW = 255;
}
else if (state == BLINKER_CMD_OFF)
{
digitalWrite(LED_BUILTIN, LOW);
BlinkerMIOT.powerState("off");
BlinkerMIOT.print();
wsState = false;
colorW = 0;
}
pixelShow();
}
void miotColor(int32_t color) // 用户自定义颜色设置的回调函数:
{
BLINKER_LOG("need set color: ", color);
colorR = color >> 16 & 0xFF;
colorG = color >> 8 & 0xFF;
colorB = color & 0xFF;
BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB);
pixelShow();
BlinkerMIOT.color(color);
BlinkerMIOT.print();
}
void miotMode(uint8_t mode) // 用户自定义模式设置的回调函数:
{
BLINKER_LOG("need set mode: ", mode);
if (mode == BLINKER_CMD_MIOT_DAY)
{ // 日光(10,25,41)
// Your mode function
COLORM = 0;
colorR = 10;
colorG = 255;
colorB = 41;
}
else if (mode == BLINKER_CMD_MIOT_NIGHT)
{ // 月光 自定义
// Your mode function
COLORM = 0;
COLORM = 0;
colorR = 0;
colorG = 0;
colorB = 0;
}
else if (mode == BLINKER_CMD_MIOT_COLOR)
{ // 彩光
// Your mode function
COLORM = 1;
}
else if (mode == BLINKER_CMD_MIOT_WARMTH)
{ // 温馨
// Your mode function
COLORM = 0;
colorR = 10;
colorG = 255;
colorB = 41;
}
else if (mode == BLINKER_CMD_MIOT_TV)
{ // 电视模式
// Your mode function
COLORM = 0;
}
else if (mode == BLINKER_CMD_MIOT_READING)
{ // 阅读模式
// Your mode function
COLORM = 0;
colorR = 0;
colorG = 0;
colorB = 0;
}
else if (mode == BLINKER_CMD_MIOT_COMPUTER)
{ // 电脑模式
// Your mode function
COLORM = 0;
colorR = 0;
colorG = 0;
colorB = 0;
LedControl(colorW, colorT);
}
wsMode = mode;
BlinkerMIOT.mode(mode);
BlinkerMIOT.print();
}
void miotBright(const String &bright) // 用户自定义亮度控制的回调函数:
{
BLINKER_LOG("need set brightness: ", bright);
colorW = bright.toInt();
BLINKER_LOG("now set brightness: ", colorW);
pixelShow();
BlinkerMIOT.brightness(colorW);
BlinkerMIOT.print();
}
void miotColoTemp(int32_t colorTemp) // 用户自定义色温控制的回调函数:
{
BLINKER_LOG("need set colorTemperature: ", colorTemp);
;
BLINKER_LOG("需要设置色温: ", colorTemp);
colorT = map(colorTemp, 1000, 10000, 0, 100);
BlinkerMIOT.colorTemp(colorT);
BlinkerMIOT.print();
}
void miotQuery(int32_t queryCode) // 用户自定义设备查询的回调函数:
{
BLINKER_LOG("MIOT Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER:
BLINKER_LOG("MIOT Query All");
BlinkerMIOT.powerState(wsState ? "on" : "off");
BlinkerMIOT.color(0);
BlinkerMIOT.mode(0);
BlinkerMIOT.colorTemp(1000);
BlinkerMIOT.brightness(1);
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
BLINKER_LOG("MIOT Query Power State");
BlinkerMIOT.powerState(wsState ? "on" : "off");
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_COLOR_NUMBER:
BLINKER_LOG("MIOT Query Color");
BlinkerMIOT.color(0);
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_MODE_NUMBER:
BLINKER_LOG("MIOT Query Mode");
BlinkerMIOT.mode(0);
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_COLORTEMP_NUMBER:
BLINKER_LOG("MIOT Query ColorTemperature");
BlinkerMIOT.colorTemp(1000);
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_BRIGHTNESS_NUMBER:
BLINKER_LOG("MIOT Query Brightness");
BlinkerMIOT.brightness(1);
BlinkerMIOT.print();
break;
default:
BlinkerMIOT.powerState(wsState ? "on" : "off");
BlinkerMIOT.color(0);
BlinkerMIOT.mode(0);
BlinkerMIOT.colorTemp(1000);
BlinkerMIOT.brightness(1);
BlinkerMIOT.print();
break;
}
}
void dataRead(const String &data)
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print("millis", BlinkerTime);
}
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
panel->getLcd()->drawBitmap(area->x1, area->y1, area->x2 + 1, area->y2 + 1, color_p);
lv_disp_flush_ready(disp);
}
#endif
#if ESP_PANEL_USE_LCD_TOUCH
/* Read the touchpad */
void my_touchpad_read(lv_indev_drv_t *indev, lv_indev_data_t *data)
{
panel->getLcdTouch()->readData();
bool touched = panel->getLcdTouch()->getTouchState();
if (!touched)
{
data->state = LV_INDEV_STATE_REL;
}
else
{
TouchPoint point = panel->getLcdTouch()->getPoint();
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = point.x;
data->point.y = point.y;
// Serial.printf("Touch point: x %d, y %d\n", point.x, point.y);
}
}
#endif
bool lv_port_lock(uint32_t timeout_ms)
{
const TickType_t timeout_ticks = (timeout_ms == 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE;
}
void lv_port_unlock(void)
{
xSemaphoreGiveRecursive(lvgl_mux);
}
void event_handler(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED)
{
LV_LOG_USER("Clicked");
}
else if (code == LV_EVENT_VALUE_CHANGED)
{
LV_LOG_USER("Toggled");
}
}
void lv_example_btn_1(void)
{
Temper_test = "Temperature: ";
Temper_test += Temper;
Temper_test += "'C";
Humidity_text = "Humidity: ";
Humidity_text += Humidity;
Humidity_text += "%";
lv_obj_t* title = lv_obj_create(lv_scr_act());
lv_obj_set_size(title, 480, 120);
lv_obj_set_style_bg_color(title, lv_color_hex(0x00FF00), LV_STATE_DEFAULT);
title_label = lv_label_create(title);
static char title_str[] = "Indoor Lighting System";
lv_label_set_text(title_label, title_str);
lv_obj_align(title_label, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_text_font(title_label, &lv_font_montserrat_36, LV_STATE_DEFAULT);
//*温度 * /
lv_obj_t* temp = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(temp, lv_color_hex(0x00FF00), LV_STATE_DEFAULT);
lv_obj_set_size(temp, 480, 80);
lv_obj_set_pos(temp, 0, 110);
temp_label = lv_label_create(temp);
// lv_label_set_text(temp_label, Temper_test.c_str());
lv_label_set_text(temp_label, Temper_test.c_str());
lv_obj_align(temp_label, LV_ALIGN_OUT_LEFT_MID, 0, 0);
lv_obj_set_style_text_font(temp_label, &lv_font_montserrat_30, LV_STATE_DEFAULT);
/*湿度*/
lv_obj_t* humi = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(humi, lv_color_hex(0x0000FF), LV_STATE_DEFAULT);
lv_obj_set_size(humi, 480, 80);
lv_obj_set_pos(humi, 0, 180);
humi_label = lv_label_create(humi);
// lv_label_set_text(humi_label, Humidity_text.c_str());
lv_label_set_text(humi_label, Humidity_text.c_str());
lv_obj_align(humi_label, LV_ALIGN_OUT_LEFT_MID, 0, 0);
lv_obj_set_style_text_font(humi_label, &lv_font_montserrat_30, LV_STATE_DEFAULT);
}
///////////////////////////蓝牙相关//////////////////////////////////
// Callback function that gets called, when another device's advertisement has been received
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.getName() == bleServerName)
{ // Check if the name of the advertiser matches
advertisedDevice.getScan()->stop(); // Scan can be stopped, we found what we are looking for
pServerAddress = new BLEAddress(advertisedDevice.getAddress()); // Address of advertiser is the one we need
doConnect = true; // Set indicator, stating that we are ready to connect
Serial.println("Device found. Connecting!");
}
}
};
// When the BLE Server sends a new temperature reading with the notify property
static void temperatureNotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData, size_t length, bool isNotify)
{
// store temperature value
temperatureChar = (char *)pData;
newTemperature = true;
}
// When the BLE Server sends a new humidity reading with the notify property
static void humidityNotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData, size_t length, bool isNotify)
{
// store humidity value
humidityChar = (char *)pData;
newHumidity = true;
// Serial.print(newHumidity);
}
// When the BLE Server sends a new humidity reading with the notify property
static void LEDStateNotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData, size_t length, bool isNotify)
{
// store humidity value
LEDStateChar = (char *)pData;
newLEDState = true;
// Serial.print(newLEDState);
}
// Connect to the BLE Server that has the name, Service, and Characteristics
bool connectToServer(BLEAddress pAddress)
{
BLEClient *pClient = BLEDevice::createClient();
// Connect to the remove BLE Server.
pClient->connect(pAddress);
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService *pRemoteService = pClient->getService(bmeServiceUUID);
if (pRemoteService == nullptr)
{
Serial.print("Failed to find our service UUID: ");
Serial.println(bmeServiceUUID.toString().c_str());
return (false);
}
// Obtain a reference to the characteristics in the service of the remote BLE server.
temperatureCharacteristic = pRemoteService->getCharacteristic(temperatureCharacteristicUUID);
humidityCharacteristic = pRemoteService->getCharacteristic(humidityCharacteristicUUID);
LEDStateCharacteristic = pRemoteService->getCharacteristic(LEDCharacteristicUUID);
if (temperatureCharacteristic == nullptr || humidityCharacteristic == nullptr || LEDStateCharacteristic == nullptr)
{
Serial.print("Failed to find our characteristic UUID");
return false;
}
Serial.println(" - Found our characteristics");
// Assign callback functions for the Characteristics
temperatureCharacteristic->registerForNotify(temperatureNotifyCallback);
humidityCharacteristic->registerForNotify(humidityNotifyCallback);
LEDStateCharacteristic->registerForNotify(LEDStateNotifyCallback);
return true;
}
void Display_init()
{
String LVGL_Arduino = "Hello LVGL! ";
LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println(LVGL_Arduino);
Serial.println("I am ESP32_Display_Panel");
panel = new ESP_Panel();
/* Initialize LVGL core */
lv_init();
/* Initialize LVGL buffers */
static lv_disp_draw_buf_t draw_buf;
/* Using double buffers is more faster than single buffer */
/* Using internal SRAM is more fast than PSRAM (Note: Memory allocated using `malloc` may be located in PSRAM.) */
uint8_t *buf = (uint8_t *)heap_caps_calloc(1, LV_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_INTERNAL);
assert(buf);
lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_BUF_SIZE);
/* Initialize the display device */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
/* Change the following line to your display resolution */
disp_drv.hor_res = ESP_PANEL_LCD_H_RES;
disp_drv.ver_res = ESP_PANEL_LCD_V_RES;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
#if ESP_PANEL_USE_LCD_TOUCH
/* Initialize the input device */
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
#endif
/* There are some extral initialization for ESP32-S3-LCD-EV-Board */
#ifdef ESP_PANEL_BOARD_ESP32_S3_LCD_EV_BOARD
/* Initialize IO expander */
ESP_IOExpander *expander = new ESP_IOExpander_TCA95xx_8bit(ESP_PANEL_LCD_TOUCH_BUS_HOST_ID, ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000, ESP_PANEL_LCD_TOUCH_I2C_IO_SCL, ESP_PANEL_LCD_TOUCH_I2C_IO_SDA);
expander->init();
expander->begin();
/* Add into panel for 3-wire SPI */
panel->addIOExpander(expander);
/* For the newest version sub board, need to set `ESP_PANEL_LCD_RGB_IO_VSYNC` to high before initialize LCD */
pinMode(ESP_PANEL_LCD_RGB_IO_VSYNC, OUTPUT);
digitalWrite(ESP_PANEL_LCD_RGB_IO_VSYNC, HIGH);
#endif
/* Initialize bus and device of panel */
panel->init();
#if ESP_PANEL_LCD_BUS_TYPE != ESP_PANEL_BUS_TYPE_RGB
/* Register a function to notify LVGL when the panel is ready to flush */
/* This is useful for refreshing the screen using DMA transfers */
panel->getLcd()->setCallback(notify_lvgl_flush_ready, &disp_drv);
#endif
/* Start panel */
panel->begin();
}
void Bluetooth_Init()
{
Serial.println("Starting Arduino BLE Client application...");
// Init BLE device
BLEDevice::init("");
delay(1000);
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 30 seconds.
BLEScan *pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(2);
delay(1000);
}
void Blinker_Init()
{
/*Bllier 初始化*/
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
BlinkerMIOT.attachPowerState(miotPowerState);
BlinkerMIOT.attachColor(miotColor);
BlinkerMIOT.attachMode(miotMode);
BlinkerMIOT.attachBrightness(miotBright);
BlinkerMIOT.attachColorTemperature(miotColoTemp);
BlinkerMIOT.attachQuery(miotQuery);
colorR = 255;
colorG = 255;
colorB = 255;
colorW = 0;
colorT = 0;
wsState = true;
pixels.begin();
pixels.setBrightness(colorW);
WS2812.attach(ws2812_callback);
pixelShow();
}
/*======================================= TaskAPPStart ====================================*/
/*
* @brief: 启动创建任务
* @param:none
* @retval:none
*/
void TaskAPPStart()
{
/*创建Blinker线程*/
BaseType_t status;
status = xTaskCreatePinnedToCore(
(TaskFunction_t)ThreadBlinkerEntry, // Weather线程入口
(const char *const)"Thread_Blinker", // 线程名称
(const uint32_t)4096 * 2, // 线程栈
(void *const)NULL, // Weather线程入口参数
(UBaseType_t)6, // 线程优先级 0-24 数值越大优先级越高
(TaskHandle_t *)&ThreadBlinker, // 线程句柄
(const BaseType_t)APP_CPU_NUM); // 指定内核1
if (status == pdPASS)
{
Serial.println("Blinker线程创建成功...");
}
else
{
Serial.println("Blinker线程创建失败...");
}
/*创建Sensor线程*/
status = xTaskCreatePinnedToCore(
(TaskFunction_t)ThreadSensorEntry, // Sensor线程入口
(const char *const)"Thread_Sensor", // 线程名称
(const uint32_t)4096 * 1, // 线程栈
(void *const)NULL, // Sensor线程入口参数
(UBaseType_t)6, // 线程优先级 0-24 数值越大优先级越高
(TaskHandle_t *)&ThreadSensor, // 线程句柄
(const BaseType_t)PRO_CPU_NUM); // 指定内核0
if (status == pdPASS)
{
Serial.println("Sensor线程创建成功...");
}
else
{
Serial.println("Sensor线程创建失败...");
}
/* Create a task to run the LVGL task periodically */
lvgl_mux = xSemaphoreCreateRecursiveMutex();
// xTaskCreate(lvgl_task, "lvgl", 8192, NULL, 1, NULL);
/**
* To avoid errors caused by multiple tasks simultaneously accessing LVGL,
* should acquire a lock before operating on LVGL.
*/
lv_port_lock(0);
lv_example_btn_1();
// lv_demo_music(); // NOK
/*创建LVGL线程*/
status = xTaskCreatePinnedToCore(
(TaskFunction_t)ThreadLVGLEntry, // OLED线程
(const char *const)"Thread_LVGL", // 线程名称
(const uint32_t)4096 * 2, // 线程栈
(void *const)NULL, // OLED线程入口参数
(UBaseType_t)8, // 线程优先级 0-24 数值越大优先级越高
(TaskHandle_t *)&ThreadLVGL, // 线程句柄
(const BaseType_t)PRO_CPU_NUM); // 指定内核1
if (status == pdPASS)
{
Serial.println("LVGL线程创建成功...");
}
else
{
Serial.println("LVGL线程创建失败...");
}
/**
* Try an example. Don't forget to uncomment header.
* See all the examples online: https://docs.lvgl.io/master/examples.html
* source codes: https://github.com/lvgl/lvgl/tree/e7f88efa5853128bf871dde335c0ca8da9eb7731/examples
*/
lv_port_unlock();
delay(1000);
}
/*
* @brief:Blinker线程入口
* @param:none
* @retval:none
*/
void ThreadBlinkerEntry(void *pvParameters)
{
// xSemaphoreTake(sem_Blinker, portMAX_DELAY);
while (1)
{
if (LEDStateChar[0] == 'O' && LEDStateChar[1] == 'N' && flag == 2)
{
Serial.println("OK"); //起床打开灯
colorR = 255;
colorG = 255;
colorB = 255;
colorW = 100;
pixelShow();
delay(100);
wsState = true;
flag = 1;
/* code */
}
else if(LEDStateChar[0] == 'O' && LEDStateChar[1] == 'F' && LEDStateChar[2] == 'F' && flag == 1)
{
Serial.println("NO!"); //躺下关闭灯
colorW = 0;
pixelShow();
delay(100);
wsState = false;
flag = 2;
/* code */
}
else
{
// flag = 2;
}
Blinker.run();
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
/*
* @brief:LVGL线程入口
* @param:none
* @retval:none
*/
void ThreadLVGLEntry(void *pvParameter)
{
// xSemaphoreTake(sem_LVGL, portMAX_DELAY);
while (1)
{
lv_port_lock(0);
Temper_test = "Temperature: ";
Temper_test += Temper;
Temper_test += "'C";
Humidity_text = "Humidity: ";
Humidity_text += Humidity;
Humidity_text += "%";
lv_label_set_text(temp_label, Temper_test.c_str());
lv_label_set_text(humi_label, Humidity_text.c_str());
lv_task_handler();
// lv_timer_handler(); /* let the GUI do its work */
lv_port_unlock();
// Serial.println("updata");
delay(1000);
}
}
/*
* @brief:Sensor线程入口
* @param:none
* @retval:none
*/
void ThreadSensorEntry(void *pvParameters)
{
while (1)
{
// Serial.print("Temperature:");
if (doConnect == true)
{
if (connectToServer(*pServerAddress))
{
Serial.println("We are now connected to the BLE Server.");
// Activate the Notify property of each Characteristic
temperatureCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t *)notificationOn, 2, true);
humidityCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t *)notificationOn, 2, true);
LEDStateCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t *)notificationOn, 2, true);
connected = true;
}
else
{
Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again.");
}
doConnect = false;
}
// if new temperature readings are available, print in the OLED
if (newTemperature && newHumidity && newLEDState)
{
newTemperature = false;
newHumidity = false;
newLEDState = false;
Temper = temperatureChar.substring(0, 6);
// Temperature Celsius
// Serial.print("Temperature:");
// Serial.print(temperatureChar);
// Serial.println("C");
// Serial.print("Temperature:");
// Serial.print(Temper);
// Serial.println("C");
// // display humidity
// Serial.print("Humidity:");
// Serial.print(humidityChar);
// Serial.println("%");
Humidity = humidityChar.substring(0, 6);
// Temperature Celsius
// Serial.print("Humidity:");
// Serial.print(Humidity);
// Serial.println("%");
// // display LEDState
// Serial.print("LEDState:");
// Serial.println(LEDStateChar);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void setup()
{
Serial.begin(115200); /* prepare for possible serial debug */
Blinker_Init();
Display_init();
Bluetooth_Init();
TaskAPPStart();
Serial.println("Setup done");
}
void loop()
{
// Serial.println("Loop");
// sleep(1);
}
图2.4 服务端代码流程
图2.5 传感器端流程图
作品源码:
https://bbs.eeworld.com.cn/my/home.php?cur=myhome&act=download
作品演示视频:
4、项目总结
https://bbs.eeworld.com.cn/thread-1290998-1-1.html
https://bbs.eeworld.com.cn/thread-1291483-1-1.html
https://bbs.eeworld.com.cn/thread-1292193-1-1.html
https://bbs.eeworld.com.cn/thread-1295979-1-1.html
感谢EEworld提供的平台,有机会向各位朋友分享自己的DIY成果,谢谢!!!
本帖最后由 mingzhe123 于 2024-10-29 20:27 编辑引用: 秦天qintian0303 发表于 2024-10-27 12:27 ESP32 S3做服务器是不是有点性能弱啊
数据量不大。功能比较初级。如果在家里布局智能家居,这个只能作为一个子节点