Arduino ESP8266学习(5)
时间:2023-09-15 20:07:02
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 #include #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 下载
#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
#include
#include
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]元器件数据手册、IC替代型号,打造电子元器件IC百科大全!