[作品提交] 【2024 DigiKey 创意大赛】室内智能照明灯设计-完结篇

mingzhe123   2024-10-26 23:52 楼主

【2024 DigiKey 创意大赛】室内智能照明灯设计

  1. 背景介绍

物联网技术是指通过互联网将各种设备、传感 器、控制器等连接在一起,形成一个能够实时互通信息的网络。物联网技术的基本原理是通过传感器采集设备产生的数据,并通过控制器进行处理和控制,最终将数据传输到互联网上,实现设备之间的智能交互。物联网技术的核心特点是实时性、数据共享、智能化和互联性。物联网技术的实时性意味着设备和传感器能够即时收集和传输数据,使得用户可以实时了解设备状态和环境情况。数据共享可 以使不同设备之间共享数据,实现更高效的资源利用和协同工作。智能化指的是物联网设备具备处理和分析数据的能力,可以根据用户需求自动调整设备工作模式。互联性表示物联网技术可以实现设备与设备、设备与人之间的无缝连接和交互,实现更强大的功能和用户体验。物联网技术广泛应用于智能家居、智能交通、智慧城市等领域,为人们的生活带来便利和智能化。

  1. 室内智能照明灯设计

室内照明灯系统硬件如图2.1所示分,为三部分:基于ESP32 S3的服务端、基于ESP32 PICO的传感器端与小爱音箱。其中,ESP32 S3服务端使用的是乐鑫的ESP32 S3 LCD EV开发板。如图2.2所示,主要负责与小爱音箱通信,接收传感器端数据、LCD实时显示传感器数据以及灯光的控制;ESP32 PICO传感器端为单独设计的ESP32板卡,如图2.3所示,主要功能为采集MPU6050数据与SHT30数据应通过BLE传输到服务端;小爱音箱主要是与服务端实现语音交互功能。

 

系统架构图.png

图2.1 系统架构图

 

2024102623501663.png

图2.2ESP32 S3 LCD EV

传感器端板块.png

图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);
}

 

                                               

服务端代码流程.png
服务端代码流程.png

图2.4 服务端代码流程

 
传感器端流程图.png

图2.5 传感器端流程图

  1. 作品资料

作品源码:

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 编辑

回复评论 (2)

ESP32 S3做服务器是不是有点性能弱啊   

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞  2024-10-27 12:27
引用: 秦天qintian0303 发表于 2024-10-27 12:27 ESP32 S3做服务器是不是有点性能弱啊   

数据量不大。功能比较初级。如果在家里布局智能家居,这个只能作为一个子节点

点赞  2024-10-27 13:27
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复