资讯动态

不止于点灯:用XIAO ESP32-C3的EEPROM和蓝牙WiFi,做个能“记住”的物联网小项目

发布时间:2026/9/24 23:52:23 来源:尧图企业网站定制
从零构建智能记忆灯XIAO ESP32-C3的EEPROM与双模通信实战去年夏天我在工作室调试智能灯带时遇到一个尴尬场景每次断电重启后所有个性化设置都会重置。这种失忆问题在物联网设备中相当常见而解决它的关键就在于如何让设备记住用户偏好。今天我们就用XIAO ESP32-C3这款仅拇指大小的开发板打造一个能通过蓝牙接收指令、自动保存配置到EEPROM并支持WiFi双模连接的智能灯控系统。1. 项目架构设计这个项目的核心在于建立三层数据流架构用户交互层通过蓝牙接收手机发送的指令开关状态、亮度值、WiFi凭证等持久化层使用EEPROM非易失存储保存关键配置网络层根据存储的凭证自动连接WiFi或启动AP热点[图表已移除根据规范要求不使用mermaid图表]实际开发中我们需要解决几个关键问题EEPROM的写入寿命限制约10万次蓝牙与WiFi射频共存时的干扰处理配置数据的校验与容错机制2. EEPROM数据持久化实战ESP32-C3采用NVSNon-Volatile Storage实现EEPROM功能其存储结构类似键值数据库。我们先构建一个安全的数据存储模块#include Preferences.h #define MAX_SSID_LEN 32 #define MAX_PASS_LEN 64 struct DeviceConfig { char ssid[MAX_SSID_LEN]; char password[MAX_PASS_LEN]; uint8_t brightness; bool powerState; }; Preferences preferences; void saveConfig(const DeviceConfig config) { preferences.begin(iot-light, false); preferences.putBytes(config, config, sizeof(config)); // 添加CRC校验 uint32_t crc calculateCRC32((uint8_t*)config, sizeof(config)); preferences.putUInt(crc, crc); preferences.end(); } bool loadConfig(DeviceConfig config) { preferences.begin(iot-light, true); size_t len preferences.getBytesLength(config); if(len sizeof(config)) { preferences.getBytes(config, config, len); uint32_t savedCRC preferences.getUInt(crc, 0); uint32_t calcCRC calculateCRC32((uint8_t*)config, len); if(savedCRC calcCRC) { preferences.end(); return true; } } preferences.end(); return false; }关键优化点使用结构体打包所有配置参数添加CRC32校验防止数据损坏限制写入频率如配置变更后延迟5秒保存注意NVS存储空间有限通常1MB左右建议单个命名空间不超过512KB3. 蓝牙指令系统实现我们采用BLE GATT服务构建双向通信通道定义以下特征值UUID特征名权限数据类型说明0xA001PowerRWbool开关状态0xA002BrightnessRWuint8亮度(0-100)0xA003WiFiConfigWritejson{ssid:,pass:}0xA004StatusNotifystring设备状态推送完整服务实现代码#include BLEDevice.h #include BLE2902.h BLECharacteristic *pPowerChar; BLECharacteristic *pBrightnessChar; DeviceConfig currentConfig; class BluetoothCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pChar) { std::string value pChar-getValue(); uint16_t handle pChar-getHandle(); switch(handle) { case POWER_HANDLE: currentConfig.powerState *(bool*)value.data(); updateLED(); break; case BRIGHTNESS_HANDLE: currentConfig.brightness *(uint8_t*)value.data(); updateLED(); break; case WIFI_HANDLE: { DynamicJsonDocument doc(256); deserializeJson(doc, value); strncpy(currentConfig.ssid, doc[ssid], MAX_SSID_LEN); strncpy(currentConfig.password, doc[pass], MAX_PASS_LEN); saveConfig(currentConfig); wifiReconnect(); break; } } } }; void setupBLE() { BLEDevice::init(SmartLight-01); BLEServer *pServer BLEDevice::createServer(); BLEService *pService pServer-createService(SERVICE_UUID); pPowerChar pService-createCharacteristic( POWER_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY ); pPowerChar-setCallbacks(new BluetoothCallbacks()); // 其他特征值初始化... pService-start(); BLEAdvertising *pAdvertising BLEDevice::getAdvertising(); pAdvertising-addServiceUUID(SERVICE_UUID); pAdvertising-start(); }蓝牙连接优化技巧设置合适的MTU大小建议517字节启用BLE安全配对Just Works模式实现连接参数更新请求如间隔20ms延迟500ms4. 双模WiFi网络管理设备需要智能判断网络环境我的实现方案是优先尝试连接已保存的WiFi网络最多尝试3次失败后启动配置AP带Web配置页面连接成功后切换回STA模式#include WiFi.h #include WebServer.h WebServer configServer(80); void startAPMode() { WiFi.softAP(SmartLight-Config, setup123); configServer.on(/, HTTP_GET, [](){ String html form action/save methodPOST SSID: input typetext namessidbr Password: input typepassword namepassbr input typesubmit valueSave /form; configServer.send(200, text/html, html); }); configServer.on(/save, HTTP_POST, [](){ strncpy(currentConfig.ssid, configServer.arg(ssid).c_str(), MAX_SSID_LEN); strncpy(currentConfig.password, configServer.arg(pass).c_str(), MAX_PASS_LEN); saveConfig(currentConfig); configServer.send(200, text/plain, Config Saved); delay(1000); ESP.restart(); }); configServer.begin(); } bool connectToWiFi() { WiFi.begin(currentConfig.ssid, currentConfig.password); for(int i0; i30; i) { if(WiFi.status() WL_CONNECTED) { return true; } delay(1000); } return false; } void wifiManager() { if(strlen(currentConfig.ssid) 0) { if(connectToWiFi()) { Serial.println(WiFi Connected); return; } } startAPMode(); while(true) { configServer.handleClient(); delay(1); } }网络性能优化设置合理的WiFi.sleepTypeWIFI_PS_NONE禁用节电模式实现OTA升级服务需保留至少1MB Flash空间添加mDNS服务如smartlight.local访问5. 系统集成与电源管理将各模块整合时需要特别注意资源竞争问题。这是我的任务调度方案void loop() { static uint32_t lastSave 0; // 蓝牙事件处理 if(millis() - lastBLEEvent 5000) { // 高优先级处理 vTaskDelay(1); } // 网络事件处理 if(WiFi.status() WL_CONNECTED) { server.handleClient(); } // 延迟保存配置 if(needSave millis() - lastSave 5000) { saveConfig(currentConfig); needSave false; lastSave millis(); } // 低功耗处理 if(!digitalRead(USER_BTN)) { enterDeepSleep(); } }电源优化技巧使用esp_sleep_enable_timer_wakeup()实现定时唤醒关闭未使用的硬件外设如ADC、温度传感器调整CPU频率如设置为80MHz6. 项目进阶方向完成基础功能后可以考虑以下扩展场景模式# 通过蓝牙发送JSON指令 { scene: sunset, duration: 1800, colors: [ {r:255,g:100,b:0}, {r:255,g:50,b:0} ] }能耗监控float getPowerConsumption() { float voltage analogRead(VBAT_PIN) * 3.3 / 4095 * 2; float current analogRead(CURRENT_PIN) * 0.1; // 根据传感器调整 return voltage * current; }物理交互电容触摸控制加速度计手势识别环境光自适应调节在最近的一个客户项目中我们采用类似架构实现了美术馆智能照明系统。通过BLE信标定位参观者位置灯光能自动跟随移动并保存不同展区的亮度偏好。这个案例证明即使简单的记忆功能也能显著提升用户体验。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价