Arduino ESP8266学习(5)

ESP8266的花样点灯

WS2812B

实物预览效果

.
.
.
.

实物制作

材料清单

名称数量
D1 mini (esp8266)1
5050灯珠 (WS2812B)16
DS18B201
光敏电阻1
1206贴片电容(104)16
1206贴片电阻(105)1
1206贴片电阻(4701)1
2mm铜柱10+
球形灯罩1

.
DS18B20 电路原理图
注意:不要将数据引脚接到D8引脚!D8引脚已经被下拉,被上拉的话会导致esp8266无法启动。
DS18B20
.
光敏电阻电路原理图
在这里插入图片描述
.
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文件中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值