ESP8266的花样点灯
WS2812B
实物预览效果
.
.
.
.
实物制作
材料清单
名称 | 数量 |
---|---|
D1 mini (esp8266) | 1 |
5050灯珠 (WS2812B) | 16 |
DS18B20 | 1 |
光敏电阻 | 1 |
1206贴片电容(104) | 16 |
1206贴片电阻(105) | 1 |
1206贴片电阻(4701) | 1 |
2mm铜柱 | 10+ |
球形灯罩 | 1 |
.
DS18B20 电路原理图
注意:不要将数据引脚接到D8引脚!D8引脚已经被下拉,被上拉的话会导致esp8266无法启动。
.
光敏电阻电路原理图
.
5050灯珠 电路原理图
.
底座(可以用纸盒当作底座)
第一层:
第二层
第三层
实物
部分功能测试
- 光强检测
Serial.println(analogRead(A0));
- 温度检测
#include <DallasTemperature.h>
#include <OneWire.h>
#define ONE_WIRE_Pin D7
OneWire oneWire(ONE_WIRE_Pin);
DallasTemperature sensors(&oneWire);
//初始化
void setup()
{
sensors.begin();
sensors.setWaitForConversion(false);
}
//打印温度
void loop()
{
float tempC = sensors.getTempCByIndex(0);
if (tempC != DEVICE_DISCONNECTED_C)//如果温度正常
{
char TEMP[10];
sprintf(TEMP,"%f*C",tempC);
Serial.print("Temp:");
Serial.println(TEMP);
}
else
{
Serial.println("ERROR!");
}
sensors.requestTemperatures(); //发起新的温度转换
/*
* 其他代码
*/
//delay(1000);
}
- led显示
#include <FastLED.h> //直接在库管理器搜索 FastLED 下载
#define LED_PIN D1 //控制引脚
#define NUM_LEDS 6 //灯珠数量
CRGB leds[NUM_LEDS];
//初始化
void setup()
{
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
//将灯珠全部熄灭
for(int i=0;i<NUM_LEDS;i++)leds[i] = CRGB(0, 0, 0);
FastLED.show();
}
//测试
void loop()
{
//全部点亮
for(int i=0;i<NUM_LEDS;i++)
{
leds[i] = CRGB(5, 5, 5); //0~255
}
FastLED.show();
delay(3000);
//逐个点亮
for(int i=0;i<NUM_LEDS;i++)
{
for(int j=0;j<NUM_LEDS;j++)leds[j] = CRGB(0, 0, 0);
leds[i] = CRGB(5, 0, 5);
FastLED.show();
delay(400);
}
}
- 时间获取
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com",60*60*8, 30*60*1000);//时间已经校准
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(D4,OUTPUT); //板载led灯
digitalWrite(D4,LOW);
WiFi.begin("ssid","password");//设置名称及密码
while(WiFi.status() != WL_CONNECTED ) //等待WiFi连接
{
delay(250);
digitalWrite(D4,LOW); //点亮
delay(250);
digitalWrite(D4,HIGH); //熄灭
}
timeClient.begin();
timeClient.update();
delay(200);
ntpUDP.stop();
WiFi.disconnect();
delay(100);
WiFi.mode(WIFI_OFF);
}
void loop()
{
//获取时间
timeClient.update();
int H = timeClient.getHours();
int M = timeClient.getMinutes();
int S = timeClient.getSeconds();
//打印
Serial.println("Time:");
Serial.println( H );
Serial.println( M );
Serial.println( S );
delay(1000);
}
代码部分
在写代码之前需要构思想要实现的功能
比如定时开关机,APP控制,颜色设置,温度检测等。由于程序有点长,就只列出部分程序,完整程序和APP代码以及PCB文件已经放入群文件,需要的话加群下载(群链接在文章结尾)。
.
.
ESP8266保存的信息
//需要EEPROM.h文件
struct config_type
{
char Ssid[64];
char Pswd[64];
char SleepState; //'1'为睡眠时间大于60分钟 '0'则睡眠时间小于60分钟
unsigned int SleepTime; //睡眠时间(分钟)
short int R; //led颜色
short int G;
short int B;
short int OFFH; //关机时间(小时)
short int OFFM; //关机时间(分钟)
short int ONH; //开机时间
short int ONM;
char clour; //0为手动设置颜色 1为随机颜色
};
config_type Config;
//保存
void saveConfig()
{
EEPROM.begin(2048);
uint8_t *p = (uint8_t*)(&Config);
for (int i = 0; i < sizeof(Config); i++)
{
EEPROM.write(i, *(p + i));
}
EEPROM.end();
}
//读取
void loadConfig()
{
EEPROM.begin(2048);
uint8_t *p = (uint8_t*)(&Config);
for (int i = 0; i < sizeof(Config); i++)
{
*(p + i) = EEPROM.read(i);
}
EEPROM.end();
}
.
.
开机功能
//由于ESP8266最长睡眠时间为71分钟
//为了达到长时间的睡眠效果,通过设置开机检测来判断是否达到开机时间
//未达到则继续进入睡眠状态
//单次最大睡眠时间为4,294,967,295us 约合4294s 即71分钟
void SleepSet(int t) //睡眠时间设置 输入单位 分钟
{
//MAX_SLEEPTIME为设置的最大睡眠时长 小于70
if(t>MAX_SLEEPTIME)
{
Config.SleepTime = t; //剩余睡眠时间
Config.SleepState = '1';//睡眠时间大于 MAX_SLEEPTIME
saveConfig(); //保存设置
delay(100);
ESP.deepSleep(MAX_SLEEPTIME*60*1000000,WAKE_NO_RFCAL);//睡眠 MAX_SLEEPTIME 分钟
}
else
{
Config.SleepTime = 0; //剩余睡眠时间
Config.SleepState = '0';
saveConfig();
delay(100);
ESP.deepSleep(t*60*1000000,WAKE_NO_RFCAL);//睡眠t分钟
}
}
//开机检测 放在setup()中
void CHECK_SLEEP()
{
//如果是睡眠了MAX_SLEEPTIME分钟 则判断是否继续睡眠
if(Config.SleepState == '1')
{
if(Config.SleepTime-MAX_SLEEPTIME>=MAX_SLEEPTIME)
{
//如果开机时间未达到 则重新计算剩余的睡眠时间
Config.SleepTime = Config.SleepTime-MAX_SLEEPTIME;
Config.SleepState = '1';
saveConfig();
delay(100);
ESP.deepSleep(MAX_SLEEPTIME*60*1000000,WAKE_NO_RFCAL);
}
else if(Config.SleepTime-MAX_SLEEPTIME>=1)
{
//如果剩余的睡眠时间小于MAX_SLEEPTIME分钟
//则睡眠时间清零 并睡眠时间设置为剩下的睡眠时间
Config.SleepTime = 0; //剩余睡眠时间清零
Config.SleepState = '0'; //更改睡眠状态
saveConfig();
delay(100);
ESP.deepSleep((Config.SleepTime-MAX_SLEEPTIME)*60*1000000,WAKE_NO_RFCAL);
}
}
}
.
.
关机功能
//检测关机时间 放在loop()中
void CLOCK()
{
static short int onH = Config.ONH;
static short int onM = Config.ONM;
static short int offH = Config.OFFH;
static short int offM = Config.OFFM;
//当数据被修改 保存修改后的设置
//并判断是否关闭定时功能
if(Config.ONH!=onH||Config.ONM!=onM||Config.OFFH!=offH||Config.OFFM!=offM)
{
onH = Config.ONH;
onM = Config.ONM;
offH = Config.OFFH;
offM = Config.OFFM;
//开启和关闭时间相同则关闭定时功能
if(Config.ONH==Config.OFFH&&Config.ONM==Config.OFFM)
{
Config.SleepState = '0';
client.print("@Lightsetcloseok#");//向APP反馈
saveConfig();
}
else
{
saveConfig();
}
}
//当开机时间和关机时间相同则关闭开关机功能
//判断是否开启关机功能 检测关机时间
if( Config.OFFH!=Config.ONH||Config.OFFM!=Config.ONM )
{
if(Hours == Config.OFFH)
{
if(Minutes == Config.OFFM)
{
//当达到关机时间则计算需要睡眠的时间
if(Config.OFFH<=Config.ONH)
{
int sleepH = Config.ONH - Config.OFFH;
int sleepM = Config.ONM - Config.OFFM;
SleepSet(sleepH*60+sleepM);
}
else
{
int sleepH = 23-Config.OFFH + Config.ONH;
int sleepM = Config.ONM - Config.OFFM;
SleepSet(sleepH*60+sleepM);
}
}
}
}
}
.
.
接入网络
//网络初始化 连接WiFi 时间获取 连接端口
void INIT_NETWORK()
{
pinMode(D4, OUTPUT);
digitalWrite(D4, HIGH);
WiFi.mode(WIFI_STA);
WiFi.begin(Config.Ssid, Config.Pswd);
uint32_t las = millis();
while(WiFi.status() != WL_CONNECTED )//等待8s连接 未连接则配网
{
delay(350);
digitalWrite(D4, LOW);
delay(650);
digitalWrite(D4, HIGH);
if(millis()-las>=8000)
{
webConfig();
break;
}
ESP.wdtFeed();
}
GetTime();//先获取网络时间
//连接IP
las = millis();
while(!client.connect(CLIENT_IP, CLIENT_PORT))
{
if(millis()-las>=5000)ESP.restart();
ESP.wdtFeed();
client.connect(CLIENT_IP, CLIENT_PORT);
delay(200);
}
digitalWrite(D4, HIGH);
//显示之前保存的颜色
for(int i=0;i<NUM_LEDS;i++)
{
leds[i] = CRGB(Config.R, Config.G, Config.B);
FastLED.show();
}
}
.
.
时间获取
/*如果不使用定时器更新时间而直接读取
Hours = timeClient.getHours();
Minutes = timeClient.getMinutes();
Seconds = timeClient.getSeconds();
开机30分钟后会发生卡顿(卡顿时长3~5s)
如果嫌麻烦可以直接调用函数读取时间 不影响关机功能
*/
Ticker updateTicker;
int Hours = 0;
int Minutes = 0;
int Seconds = 0;
//定时器回调函数 更新时间 每秒钟将上面三个变量更新一次
void updateTime()
{
Seconds++;
if(Seconds >= 60)
{
Seconds = 0;
Minutes++;
if(Minutes >= 60)
{
Minutes = 0;
Hours++;
if(Hours >=24 )
{
Hours = 0;
}
}
}
}
//时间获取 设置秒定时器 放在setup()中
void GetTime()
{
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp1.aliyun.com",60*60*8, 30*60*1000);
timeClient.begin();
timeClient.update();
Hours = timeClient.getHours();
Minutes = timeClient.getMinutes();
Seconds = timeClient.getSeconds();
updateTicker.attach_ms(1000, updateTime); //设置定时器 1s执行一次
ntpUDP.stop();
}
.
.
温度检测
static bool tempsend = false;//温度自动更新变量
char tempbuff[22];//向APP发送的温度
//放在loop()函数中
void TEMP_SEND()
{
static uint32_t ti = millis();
if(millis()-ti>=2000) //2s更新一次温度
{
ti = millis();
float tempc = sensors.getTempCByIndex(0);
if (tempc != DEVICE_DISCONNECTED_C) //读取正确
{
for(int i=0;i<22;i++)tempbuff[i]=0;
sprintf(tempbuff,"@Lighttemp=%.2f*C#",tempc);
}
else
{
sprintf(tempbuff,"@Lighttemp=读取错误#");
}
//判断是否开启温度自动功能
if(tempsend == true)
{
client.print(tempbuff);
}
sensors.requestTemperatures();
}
}
.
.
接收APP的数据
void GET_CMD()
{
if(client.available())
{
char clientbuff[50];
int buffnum=0;
bool rd = false;
for(int i=0;i<50;i++)clientbuff[i] = 0;
while(client.available())
{
clientbuff[buffnum] = client.read();
if(buffnum == 0){if(clientbuff[0] != '@')break;}
if(buffnum == 1){if(clientbuff[1] != 'L')break;}
if(buffnum == 2){if(clientbuff[2] != 'i')break;}
if(buffnum == 3){if(clientbuff[3] != 'g')break;}
if(buffnum == 4){if(clientbuff[4] != 'h')break;}
if(buffnum == 5){if(clientbuff[5] != 't')break;else rd = true;}
if(clientbuff[buffnum] == '#')break;
if(buffnum >= 50)break;
buffnum++;
}
if(rd == true)
{
//Serial.println(clientbuff);
ProcessingCMD(clientbuff);//处理数据
}
}
}
//处理数据
void ProcessingCMD(char *buff)
{
if(strstr(buff, "BLUE=") !=NULL) //@LightBLUE=56#
{
char *s = strstr(buff,"=");
s = s+strlen("=");
if(*s==0x00) return;
char temp[15];
int i=0,j=0,B=0;
char v=0;
for(i=0;i<strlen(s);i++)
{
if(*(s+i)!='#' || *(s+i)!=0x00)
{
temp[j++]=*(s+i);
}
if(*(s+i)=='#')
{
temp[j]=0x00;
if(v==0) B = atoi(temp);
v++;
j=0;
}
}
if(B>=0&&B<=128)
{
Config.B = B;
for(int i=0;i<NUM_LEDS;i++)
{
leds[i] = CRGB(Config.R, Config.G, Config.B);
FastLED.show();
}
}
}
else if(strstr(buff, "GREEN=") !=NULL) //@LightGREEN=56#
{
............
............
............
}
else if(strstr(buff, "RED=") !=NULL) //@LightRED=56#
{
............
............
............
}
else if(strstr(buff, "autocolour") !=NULL) //@Lightautocolour#
{
Config.clour = '1';
client.print("@Lightautocolourok#");
}
else if(strstr(buff, "handcolour") !=NULL) //@Lighthandcolour#
{
Config.clour = '0';
client.print("@Lighthandcolourok#");
}
//开关机时间设置
else if(strstr(buff, "seton=") !=NULL) //@Lightseton=18:50:12# @Lightseton=18:# @Lightseton=18:50#
{
char *s = strstr(buff,"=");
s = s+strlen("=");if(*s==0x00) return;
char temp[25];
int i=0,j=0;
short int H=0,M=0,S=0;
char v=0;
for(i=0;i<strlen(s);i++)
{
if(*(s+i)!=':' || *(s+i)!=0x00)
{
temp[j++]=*(s+i);
}
if(*(s+i)==':')
{
temp[j]=0x00;
if(v==0) H = atoi(temp);
if(v==1) M = atoi(temp);
if(v==2) S = atoi(temp);
v++;j=0;
}
}
if(*(s+strlen(s)-1) !=':')S = atoi(temp);
if(H>=0&&H<=23)Config.ONH = H;
if(M>=0&&M<=59)Config.ONM = M;
saveConfig();
client.print("@Lightsetonok#");
}
else if(strstr(buff, "setoff=") !=NULL) //@Lightsetoff=18:50:12# @Lightsetoff=18:# @Lightsetoff=18:50#
{
............
............
............
}
else if(strstr(buff, "autotemp") !=NULL) //@Lightautotemp#
{
tempsend = true;
client.print("@Lightautotempok#");
}
else if(strstr(buff, "handtemp") !=NULL) //@Lighthandtemp#
{
tempsend = false;
client.print("@Lighthandtempok#");
}
else if(strstr(buff, "temp") !=NULL) //@Lighttemp#
{
client.print(tempbuff);//发送温度
}
//重启 并保存设置
else if(strstr(buff, "RESTART") !=NULL) //@LightRESTART#
{
client.print("@LightRESTARTOK#");
saveConfig();
delay(600);
ESP.restart();
}
}
.
.
想要全部代码请加群(531774127)自行下载,所有文件在Light文件中