|
最近在GitHub捣鼓了一个ESP8266控制WS2812B彩灯,表白或炫技的神器,分享出来给有兴趣的坛友。
一.硬件部分
1. ESP8266开发板:
NodeMCU1.0是一个开源的搭载ESP8266wifi芯片的ESP-12F模组,集合CP2102,USB转串口的开发板,网上价格极低,深受电子DIYer喜爱 。当然也可以使用其它采用ESP8266主控的开发板。
动手能力好的同学也可以自己制作,附上PCB文件:
2. WS2812B灯带:
WS2812B是一颗现在大量使用的景观灯,氛围灯灯带的集成控制功能的LED灯珠,具有16777216种颜色的全真色彩显示,单线通讯,一进一出方便级联。
网上很多灯带或者是矩阵或者圆形PCB成品出售,可以按喜好选择
我使用的是一个开源的硬件,60灯的圆形灯串,它由4个弧形PCB级联而成。自己打PCB手工焊接,有些难度,但好在这个灯珠比较耐焊,焊好一次成功,没有损坏。
同样附上PCB文件:
3. 0.96寸OLED显示屏
网上购买,使用ssd1306主控,分辨率128*64,I2C接口
4. 接线方法:
注意:图中WS2812灯串直接接在了开发板3.3V上,测试发现60灯以内电流是OK的,可以正常工作。如果你的灯串数量更多,请单独增加一个电源,或者使用7805降压给开发板和灯串供电,电流不够会引起数据异常,灯串显示不正常。
二.软件部分
1. Arduino IDE工具搭建ESP8266平台
使用Arduino IDE工具ESP8266平台开发,想要仿制的入门级坛友,需要首先搭建好平台,具体可参考相关帖子或使用搜索引擎。
Arduino IDE工具,最新版本1.8.10
搭建好ESP8266平台,选择NodeMCU1.0(ESP-12E Module),其它按默认配置
相关代码及库文件:
配置好软件后在《工具》《管理库》的库管理器中搜索安装以下库文件:
WS2812FX
WiFiManager
ArduinoOTA
ArduinoJson
Adafruit_GFX
Adafruit_SSD1306
其实,我的这个代码是基于WS2812FX库中的示例文件做了修改而成。主要修改2点使其能够脱离电脑便携使用:
1.原来wifi配置是固定在代码中,只能在固定的wifi网络使用,修改为wifi配置可以手机端配置账号密码;
2.另外APP需要用到一个IP地址,原代码需要电脑串口打印出来,修改为使用0.96OLED屏幕显示。(手头上有现成的屏幕就拿来用了,如果熟悉Arduino也可以使用手头上其它显示方式,比如LED数码管 )
当然串口上也会打印这个IP地址,你没有连接OLED,只是测试的话也可以用电脑串口工具查看。
同时为了方便升级更新ESP8266,增加了OTA局域网空中升级功能,具体OTA升级方式可搜索相关帖子。
代码配置:
- uint8_t dataPin = D3; // default digital pin used to drive the LED strip
- uint16_t numLeds = 13; // default number of LEDs on the strip
复制代码
定义NodeMCU1.0 模块驱动灯串的输出口,D3
定义输出灯串的级联LED数量,这里是13,这个是初始定义,影响不大,在APP中可以动态调整。
- Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
复制代码
定义0.96OLED屏幕配置,我使用的是128*64分辨率,这里配置成128,64,市面决大多数0.96OLED都是这个规格,如有不同可以按规格配置,比如128,32
- display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x64
复制代码
定义0.96OLED屏幕I2C地址,0x3C,以实际地址为准,一般不需要更改
- if (!wifiManager.autoConnect("WS2812FX"))
复制代码
引号中的"WS2812FX",为wifi配置页显示配置热点的名称,可以随意修改为你喜欢的名字。注意只能修改引号中的名称,引号格式不能变动。
整个工程代码如下:
- /*
- This sketch introduces the idea of patterns.
- A pattern is a collection of segments. Each pattern plays for a specific
- duration and you can setup an array of patterns that play in a continuous loop.
- A web API is included which receives and stores pattern data in JSON format.
- It's the companion sketch for the LEDfx Android app available in the Google Play
- app store: https://play.google.com/store/apps/details?id=com.champlainsystems.ledfx
- Keith Lord - 2018
- LICENSE
- The MIT License (MIT)
- Copyright (c) 2018 Keith Lord
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- CHANGELOG
- 2018-02-21 initial version
- 2018-11-30 added custom aux functions and OTA update
- */
- #include <WS2812FX.h>
- #include <ESP8266WebServer.h>
- #include <WiFiManager.h>
- #include <ArduinoOTA.h>
- #include <ArduinoJson.h>
- #include <EEPROM.h>
- #include <Wire.h>
- #include <Adafruit_GFX.h>
- #include <Adafruit_SSD1306.h>
- #define VERSION "2.1.0"
- uint8_t dataPin = D3; // default digital pin used to drive the LED strip
- uint16_t numLeds = 13; // default number of LEDs on the strip
- Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
- #define HTTP_PORT 80
- #define MAX_NUM_PATTERNS 8
- // duration, brightness, numSegments, [ { first, last, speed, mode, options, colors[] } ]
- //#define DEFAULT_PATTERN {30, 64, 1, { {0, numLeds-1, numLeds*20, FX_MODE_STATIC, NO_OPTIONS, {RED, BLACK, BLACK}} }}
- #define DEFAULT_PATTERN {30, 64, 1, { {0, numLeds-1, numLeds*20, FX_MODE_STATIC, NO_OPTIONS, {RED, BLUE, BLUE}} }}
- typedef struct Pattern { // 208 bytes/pattern
- int duration;
- uint8_t brightness;
- uint8_t numSegments;
- WS2812FX::segment segments[MAX_NUM_SEGMENTS];
- } pattern;
- // setup a default patterns array
- Pattern patterns[MAX_NUM_PATTERNS] = { DEFAULT_PATTERN };
- int numPatterns = 1;
- int currentPattern = 0;
- unsigned long lastTime = 0;
- WS2812FX ws2812fx = WS2812FX(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
- ESP8266WebServer server(HTTP_PORT);
- void (*customAuxFunc[])(void) { // define custom auxiliary functions here
- [] { Serial.println("running customAuxFunc[0]"); },
- [] { Serial.println("running customAuxFunc[1]"); },
- [] { Serial.println("running customAuxFunc[2]"); }
- };
- void setup() {
- Serial.begin(115200);
- display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x64
- delay(500);
- display.clearDisplay();
- display.setTextSize(2);
- display.setTextColor(SSD1306_WHITE);
- display.setCursor(0,0);
- display.println("WiFi Setup...");
- display.setCursor(0,0);
- display.display();
- ws2812fx.init();
- ws2812fx.setBrightness(0);
-
- Serial.println("\r\n");
- EEPROM.begin(2048); // for ESP8266 (comment out if using an Arduino)
- // init WiFi
- /* WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
- WiFi.mode(WIFI_STA);
- Serial.print("Connecting to " WIFI_SSID);
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.print("\nServer IP is ");
- Serial.println(WiFi.localIP());
- */
- WiFiManager wifiManager;
- //wifiManager.resetSettings();
- wifiManager.setAPStaticIPConfig(IPAddress(10, 0, 1, 1), IPAddress(10, 0, 1, 1), IPAddress(255, 255, 255, 0));
- wifiManager.setConfigPortalTimeout(180);
- if (!wifiManager.autoConnect("WS2812FX"))
- {
- Serial.println(F("Failed to connect. Reset and try again..."));
- delay(3000);
- //重置并重试
- ESP.reset();
- delay(5000);
- }
- if (WiFi.status() == WL_CONNECTED) {
- Serial.println("WiFi Connected!");
- Serial.print("\nIP ssid: ");
- Serial.println(WiFi.SSID());
- Serial.print("\nServer IP is ");
- Serial.println(WiFi.localIP());
- // text display tests
- display.clearDisplay();
- display.setTextSize(2);
- display.setTextColor(SSD1306_WHITE);
- display.setCursor(0,0);
- display.println(WiFi.localIP());
- display.setCursor(0,0);
- display.display(); // actually display all of the above
- delay(3000);
- display.clearDisplay();
- display.setTextSize(2);
- display.setTextColor(SSD1306_WHITE);
- display.setCursor(0,0);
- display.println(" ");
- display.setCursor(0,0);
- display.display(); // actually display all of the above
- }
- // init OTA
- ArduinoOTA.onStart([]() {
- Serial.println("OTA start");
- });
- ArduinoOTA.onEnd([]() {
- Serial.println("\nOTA end");
- });
- ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
- Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
- });
- ArduinoOTA.onError([](ota_error_t error) {
- Serial.printf("Error[%u]: ", error);
- if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
- else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
- else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
- else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
- else if (error == OTA_END_ERROR) Serial.println("End Failed");
- });
- ArduinoOTA.begin();
- // init LED strip with a default segment
- // ws2812fx.init();
- ws2812fx.setBrightness(128);
- ws2812fx.setSegment(0, 0, numLeds - 1, FX_MODE_STATIC, RED, 3000, false);
- // if not rebooting due to catastrophic error, restore pattern data from eeprom
- struct rst_info *rstInfo = system_get_rst_info();
- //Serial.print("rstInfo->reason:"); Serial.println(rstInfo->reason);
- if (rstInfo->reason != REASON_EXCEPTION_RST) { // not reason 2
- restoreFromEEPROM();
- }
- ws2812fx.start();
- // config and start the web server
- configServer();
- server.begin();
- }
- void loop() {
- ArduinoOTA.handle();
- ws2812fx.service();
- server.handleClient();
- // if it's time to change pattern, do it now
- unsigned long now = millis();
- if (lastTime == 0 || (now - lastTime > patterns[currentPattern].duration * 1000)) {
- ws2812fx.clear();
- ws2812fx.resetSegments();
- currentPattern = (currentPattern + 1) % numPatterns;
- ws2812fx.setBrightness(patterns[currentPattern].brightness);
- for (int i = 0; i < patterns[currentPattern].numSegments; i++) {
- WS2812FX::segment seg = patterns[currentPattern].segments[i];
- ws2812fx.setSegment(i, seg.start, seg.stop, seg.mode, seg.colors, seg.speed, seg.options);
- }
- lastTime = now;
- }
- }
- void configServer() {
- server.onNotFound([]() {
- server.sendHeader("Access-Control-Allow-Origin", "*");
- server.send(404, "text/plain", "Page not found");
- });
- // return the WS2812FX status
- // optionally set the running state or run custom auxiliary functions
- server.on("/status", []() {
- server.sendHeader("Access-Control-Allow-Origin", "*");
- String running = server.arg("running");
- if (running.length() > 0) {
- if (running == "true") ws2812fx.start();
- else ws2812fx.stop();
- }
- String auxFunc = server.arg("auxFunc");
- if (auxFunc.length() > 0) {
- int auxFuncIndex = auxFunc.toInt();
- if (auxFuncIndex >= 0 && auxFuncIndex < sizeof(customAuxFunc) / sizeof(customAuxFunc[0])) {
- customAuxFunc[auxFuncIndex]();
- }
- }
- char status[50] = "{"version":"";
- strcat(status, VERSION);
- strcat(status, "","isRunning":");
- strcat(status, ws2812fx.isRunning() ? "true" : "false");
- strcat(status, "}");
- server.send(200, "application/json", status);
- });
- // send the WS2812FX mode info in JSON format
- server.on("/getModes", []() {
- char modes[1000] = "[";
- for (uint8_t i = 0; i < ws2812fx.getModeCount(); i++) {
- strcat(modes, """);
- strcat_P(modes, (PGM_P)ws2812fx.getModeName(i));
- strcat(modes, "",");
- }
- modes[strlen(modes) - 1] = ']';
- server.sendHeader("Access-Control-Allow-Origin", "*");
- server.send(200, "application/json", modes);
- });
- server.on("/upload", HTTP_OPTIONS, []() { // CORS preflight request
- server.sendHeader("Access-Control-Allow-Origin", "*");
- server.sendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
- server.sendHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
- server.send(200, "text/plain", "OK");
- });
- // receive the device info in JSON format and update the pattern data
- server.on("/upload", HTTP_POST, []() {
- String data = server.arg("plain");
- Serial.println(data);
- bool isParseOk = json2patterns(data);
- if (isParseOk && numPatterns > 0) {
- ws2812fx.stop();
- ws2812fx.clear();
- ws2812fx.resetSegments();
- saveToEEPROM();
- currentPattern = 0;
- lastTime = 0;
- ws2812fx.start();
- }
- server.sendHeader("Access-Control-Allow-Origin", "*");
- server.send(200, "application/json", "{"status":200, "message":"OK"}");
- });
- }
- #define EEPROM_MAGIC_NUMBER 0x010e0d05
- void saveToEEPROM() {
- Serial.println("saving to EEPROM");
- EEPROM.put(sizeof(int) * 0, (int)EEPROM_MAGIC_NUMBER);
- EEPROM.put(sizeof(int) * 1, (int)ws2812fx.getPin());
- EEPROM.put(sizeof(int) * 2, (int)ws2812fx.getLength());
- EEPROM.put(sizeof(int) * 3, (int)numPatterns);
- EEPROM.put(sizeof(int) * 4, patterns);
- EEPROM.commit(); // for ESP8266 (comment out if using an Arduino)
- }
- void restoreFromEEPROM() {
- int magicNumber = 0;
- int pin;
- int length;
- EEPROM.get(sizeof(int) * 0, magicNumber);
- if (magicNumber == EEPROM_MAGIC_NUMBER) {
- Serial.println("restoring from EEPROM");
- EEPROM.get(sizeof(int) * 1, pin);
- if (ws2812fx.getPin() != pin) {
- ws2812fx.setPin(pin);
- }
- EEPROM.get(sizeof(int) * 2, length);
- if (ws2812fx.getLength() != length) {
- ws2812fx.setLength(length);
- }
- EEPROM.get(sizeof(int) * 3, numPatterns);
- EEPROM.get(sizeof(int) * 4, patterns);
- }
- }
- int modeName2Index(const char* name) {
- for (int i = 0; i < ws2812fx.getModeCount(); i++) {
- if (strcmp_P(name, (PGM_P)ws2812fx.getModeName(i)) == 0) {
- return i;
- }
- }
- return 0;
- }
- #if ARDUINOJSON_VERSION_MAJOR == 5
- //#pragma message("Compiling for ArduinoJson v5")
- bool json2patterns(String &json) {
- DynamicJsonBuffer jsonBuffer(2000);
- JsonObject& deviceJson = jsonBuffer.parseObject(json);
- if (deviceJson.success()) {
- ws2812fx.setPin(deviceJson["dataPin"]);
- ws2812fx.setLength(deviceJson["numLeds"]);
- JsonArray& patternsJson = deviceJson["patterns"];
- if (patternsJson.size() > 0 ) {
- numPatterns = 0;
- for (int i = 0; i < patternsJson.size(); i++) {
- JsonObject& patt = patternsJson[i];
- // bool isEnabled = patt["isEnabled"];
- // if (! isEnabled) continue; // disabled patterns are not stored
- JsonArray& segmentsJson = patt["segments"];
- if (segmentsJson.size() == 0 ) continue;
- patterns[numPatterns].brightness = patt["brightness"];
- patterns[numPatterns].duration = patt["duration"];
- patterns[numPatterns].numSegments = segmentsJson.size();
- for (int j = 0; j < segmentsJson.size(); j++) {
- JsonObject& seg = segmentsJson[j];
- //seg.printTo(Serial);Serial.println();
- int start = seg["start"];
- if (start < 0 || start >= ws2812fx.getLength()) start = 0;
- patterns[numPatterns].segments[j].start = start;
- int stop = seg["stop"];
- if (stop < 0 || stop >= ws2812fx.getLength()) stop = ws2812fx.getLength() - 1;
- patterns[numPatterns].segments[j].stop = stop;
- if (seg["mode"].is<unsigned int>()) { // seg["mode"] can be a mode number or a mode name
- patterns[numPatterns].segments[j].mode = seg["mode"];
- } else {
- patterns[numPatterns].segments[j].mode = modeName2Index(seg["mode"]);
- }
- int speed = seg["speed"];
- if (speed < SPEED_MIN || speed >= SPEED_MAX) speed = 1000;
- patterns[numPatterns].segments[j].speed = speed;
- patterns[numPatterns].segments[j].options = 0;
- bool reverse = seg["reverse"];
- if (reverse) patterns[numPatterns].segments[j].options |= REVERSE;
- bool gamma = seg["gamma"];
- if (gamma) patterns[numPatterns].segments[j].options |= GAMMA;
- int fadeRate = seg["fadeRate"];
- if (fadeRate > 0) patterns[numPatterns].segments[j].options |= (fadeRate & 0x7) << 4;
- int size = seg["size"];
- if (size > 0) patterns[numPatterns].segments[j].options |= (size & 0x3) << 1;
- JsonArray& colors = seg["colors"]; // the web interface sends three color values
- // convert colors from strings ('#ffffff') to uint32_t
- patterns[numPatterns].segments[j].colors[0] = strtoul(colors[0].as<char*>() + 1, 0, 16);
- patterns[numPatterns].segments[j].colors[1] = strtoul(colors[1].as<char*>() + 1, 0, 16);
- patterns[numPatterns].segments[j].colors[2] = strtoul(colors[2].as<char*>() + 1, 0, 16);
- }
- numPatterns++;
- if (numPatterns >= MAX_NUM_PATTERNS) break;
- }
- } else {
- Serial.println(F("JSON contains no pattern data"));
- return false;
- }
- } else {
- Serial.println(F("Could not parse JSON payload"));
- return false;
- }
- return true;
- }
- #endif
- #if ARDUINOJSON_VERSION_MAJOR == 6
- //#pragma message("Compiling for ArduinoJson v6")
- bool json2patterns(String &json) {
- // in ArduinoJson v6 a DynamicJsonDocument does not expand as needed
- // like it did in ArduinoJson v5. So rather then try to compute the
- // optimum heap size, we'll just allocated a bunch of space on the
- // heap and hope it's enough.
- int freeHeap = ESP.getFreeHeap();
- DynamicJsonDocument doc(freeHeap - 3096); // allocate all of the available heap except 3kB
- DeserializationError error = deserializeJson(doc, json);
- if (!error) {
- JsonObject deviceJson = doc.as<JsonObject>();
- ws2812fx.setPin(deviceJson["dataPin"]);
- ws2812fx.setLength(deviceJson["numLeds"]);
- JsonArray patternsJson = deviceJson["patterns"];
- if (patternsJson.size() > 0 ) {
- numPatterns = 0;
- for (int i = 0; i < patternsJson.size(); i++) {
- JsonObject patt = patternsJson[i];
- // bool isEnabled = patt["isEnabled"];
- // if (! isEnabled) continue; // disabled patterns are not stored
- JsonArray segmentsJson = patt["segments"];
- if (segmentsJson.size() == 0 ) continue;
- patterns[numPatterns].brightness = patt["brightness"];
- patterns[numPatterns].duration = patt["duration"];
- patterns[numPatterns].numSegments = segmentsJson.size();
- for (int j = 0; j < segmentsJson.size(); j++) {
- JsonObject seg = segmentsJson[j];
- //seg.printTo(Serial);Serial.println();
- int start = seg["start"];
- if (start < 0 || start >= ws2812fx.getLength()) start = 0;
- patterns[numPatterns].segments[j].start = start;
- int stop = seg["stop"];
- if (stop < 0 || stop >= ws2812fx.getLength()) stop = ws2812fx.getLength() - 1;
- patterns[numPatterns].segments[j].stop = stop;
- if (seg["mode"].is<unsigned int>()) { // seg["mode"] can be a mode number or a mode name
- patterns[numPatterns].segments[j].mode = seg["mode"];
- } else {
- patterns[numPatterns].segments[j].mode = modeName2Index(seg["mode"]);
- }
- int speed = seg["speed"];
- if (speed < SPEED_MIN || speed >= SPEED_MAX) speed = 1000;
- patterns[numPatterns].segments[j].speed = speed;
- patterns[numPatterns].segments[j].options = 0;
- bool reverse = seg["reverse"];
- if (reverse) patterns[numPatterns].segments[j].options |= REVERSE;
- bool gamma = seg["gamma"];
- if (gamma) patterns[numPatterns].segments[j].options |= GAMMA;
- int fadeRate = seg["fadeRate"];
- if (fadeRate > 0) patterns[numPatterns].segments[j].options |= (fadeRate & 0x7) << 4;
- int size = seg["size"];
- if (size > 0) patterns[numPatterns].segments[j].options |= (size & 0x3) << 1;
- JsonArray colors = seg["colors"]; // the web interface sends three color values
- // convert colors from strings ('#ffffff') to uint32_t
- patterns[numPatterns].segments[j].colors[0] = strtoul(colors[0].as<char*>() + 1, 0, 16);
- patterns[numPatterns].segments[j].colors[1] = strtoul(colors[1].as<char*>() + 1, 0, 16);
- patterns[numPatterns].segments[j].colors[2] = strtoul(colors[2].as<char*>() + 1, 0, 16);
- }
- numPatterns++;
- if (numPatterns >= MAX_NUM_PATTERNS) break;
- }
- } else {
- Serial.println(F("JSON contains no pattern data"));
- return false;
- }
- } else {
- Serial.print(F("Could not parse JSON payload: "));
- Serial.println(error.c_str());
- return false;
- }
- return true;
- }
- #endif
复制代码
代码打包:
库文件打包:
解压到C:\Users\...(对应你的账户)\Documents\Arduino\libraries
注意:Adafruit_SSD1306 库需要进库文件目录修改OLED配置为128*64
附件提供的库已配置好。
2. 配套安卓APP
安卓APP:
三.具体使用方法:
编辑配置OK之后,连接NodeMCU1.0目标板,点击《上传》代码上传到目标板中
手机端下载安装好APP,连接好电路,插入Micro USB线,开发板上电。
OLED屏显示:WiFi Setup...
系统进入wifi配置状态,打开手机wifi设置搜索热点:WS2812FX, 并点击登录到该热点
点击第一个配置WiFi,找到你路由器的ID点击,然后输入密码,最后点击save保存,模块会自动配置wifi,配置界面会自动退出。正确配置并连接网络就不会再出现该热点,没有连接到网络的话可以再次连接热点配置,更换网络同理。
同时注意,OLED显示屏会提示一个IP地址。(因为OLED的特性,为了保护OLED屏幕,该地址只显示5秒左右,可在程序中更改时间或长显)
记住该地址,后面的APP中需要该地址进行操作。
手机连接到开发板同一个WiFi,打开帖子中提供的LEDfx APP,点击Devices后面的+
几个关键的设置:
IP or Host: 输入之前设置wifi后OLED屏显示的IP地址,我这里是:192.168.3.3,你的需要按实际填写。
Data Pin:你的驱动脚,帖子中是连接的D3, gpio脚是:0
Num LEDs:你的灯串的数量,我的硬件是:60
填好后,点击Pattems后面+号
这里可以设置灯串的亮度 Brightness,时间 Duration 保持默认或按需修改。
点击Segments后面的+号
设置一些参数,
灯串的起始,60灯串起始为0-59.
Mode下拉选择闪烁模式,几十种各式各样的闪烁可选。
速度,颜色等等,设置后点击播放图标可即时看到效果。
退回到最上层菜单,点击播放按钮,即可按你的配置闪烁,点击SAVE可以保存到ESP8266的EEPROM中,下次上电直接可以调取保存的模式闪烁。
APP可以多路,多组合闪烁,组合绚丽多彩的闪灯模式。如果使用矩阵式灯串,甚至可以设置显示出字体。
作为家里的氛围灯小装饰,孩子的创意玩具,甚至情侣的表白神器,就靠各位发挥自己的想象力了。
ESP8266系列制作:
ESP8266 驱动圆形60串WS2812全彩LED制作的模拟走时动画时钟(DIY系列二)
https://www.mydigit.cn/forum.php?mod=viewthread&tid=109677
ESP8266 WIFI自动校时LED点阵滚动时钟(DIY系列三)
https://www.mydigit.cn/forum.php?mod=viewthread&tid=111420
ESP8266基于Arduino使用FastLED驱动WS2812B灯带的心得
https://www.mydigit.cn/forum.php?mod=viewthread&tid=112534
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|