arduino 时间灯控

arduino 时间灯控

总体介绍一下这个灯控是具体干啥的。最开始是老师看了我那个阿里云灯控之后,然后来活了。做一个可以控制220V灯通过时间控制的通过按键设置时间的灯控,然后就有了这个创作。
开始搭建前,就要有一个大致的思路,于是我画了一个思维导图。
在这里插入图片描述大概讲解一下我的思路.
1.我是基于arduino Nano制作的(arduino uno也可以引脚接法一模一样),之所以选择它,是因为其体积小,之后打算画一块板子,将它们直接插上去,省得杜邦线绕来绕去
2.按键就用了两个,通过按键来进行具体设置,我的想法是先长按按键2大约1秒的样子,开始设置小时时间的十位数,通过按键2来加减。然后再通过按键2设置小时时间个位,分钟设置同理。然后就是设置开启时间和关闭时间。显示屏上哪个亮哪个就是所设置的量
3.220V的电压是通过继电器来控制的,注意电流,如果继电器的工作范围在0~10A之间,我推荐电流不要超过5A,因为我那个工作没几天就坏了,可能是瞬间开启时电流过大对其的损耗比较大。(个人经验所得)
4.本来打算在arduino上跑操作系统的,任务之间来回调度。苦于刚学打算还是跑裸机慢慢学。
5.其实项目整体难度并不大,难就难在程序怎么写,它偏算法和逻辑方面的程序比较多。

软件部分

OLED屏
说一说雷区,很多人都会用这一套代码在这里插入图片描述的确,这是基础代码,但是我发现它一定要在while( u8g.nextPage() ); 这一串代码中跑,而这一串代码返回的是0,0,0,1循环发送,而且它库给的IIC通讯速度特别慢,达不到我的速度要求(后来选择的是SPI协议),我很快就把这条思路扔掉了,而且我的循环要逐步的往深处走,后续整体代码解析会讲到的。
所以我用了以下代码:

//显示中英文字符程序

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define LOGO16_GLCD_HEIGHT 16 //定义显示高度
#define LOGO16_GLCD_WIDTH  16 //定义显示宽度

//中文:中  (存储点阵变量,用函数display.drawBitmap()调用即可)
static const unsigned char PROGMEM str_1[] =
{0x00,0xFE,0x02,0x12,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x12,0x02,0xFE,0x00,0x00,
0x00,0xFF,0x40,0x48,0x48,0x48,0x48,0x4F,0x48,0x4A,0x4C,0x48,0x40,0xFF,0x00,0x00};/*"国",0*/


//中文:国
static const unsigned char PROGMEM str_2[] =
{
0x00,0x7F,0x40,0x48,0x49,0x49,0x49,0x4F,0x49,0x49,0x49,0x48,0x40,0x7F,0x00,0x00,
0x00,0xFF,0x02,0x12,0x12,0x12,0x12,0xF2,0x12,0x52,0x32,0x12,0x02,0xFF,0x00,0x00,
};/*"国",0*/
/* (16 X 16 , 宋体 )*/

#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {                
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  // init done
  
  display.clearDisplay(); //清屏

  //英文字符显示,直接用display.println或print显示字符串就行
  //println换行,print不换行
  display.setTextSize(1);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.println("Hello, world!");   //输出字符并换行
  
  display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
  display.println(3.141592);          //输出数字并换行
  
  display.setTextSize(2);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体白色
  display.print("0x");                //输出字符
  display.println(0xDEADBEEF, HEX);   //输出为ASCII编码的十六进制
  //display.clearDisplay(); //清屏
  delay(2000);
  display.display();                  //显示以上
   display.clearDisplay(); //清屏
  delay(2000);
  //display.drawRect(38, 38, 51, 6, WHITE);//以(38,38)为起点绘制一个长度51宽度为6的矩形
  //中文字符显示
  //delay(3000);
  //display.clearDisplay(); //清屏
 // display.drawBitmap(26, 32, str_1, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH, 1); //在坐标X:26  Y:16的位置显示中文字符凌
  //display.drawBitmap(42, 32, str_2, 16, 16, 1); //在坐标X:42  Y:16的位置显示中文字符顺
 //display.display();                  //把缓存的都显示
}

void loop() {
  display.setTextSize(1);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.println("Hello, world!");   //输出字符并换行
  
  display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
  display.println(3.88);          //输出数字并换行
  display.display();                  //显示以上
}

借鉴资料:
https://blog.csdn.net/jiayan0428/article/details/105254403
他的关键就在于
display.setTextSize(1); //设置字体大小
display.setTextColor(WHITE); //设置字体颜色白色
display.setCursor(0,0); //设置字体的起始位置
display.println(“Hello, world!”); //输出字符并换行
这几行代码的限制条件几乎没有,你可以在任何函数中调用,方便了我们的函数构造。

DS1302
说一说雷区,我最开始用的是DS1302库的示例代码,但是将它和OLED代码拼装的时候,set up中的在这里插入图片描述在这里插入图片描述这几段代码执行之后就停止了,想实现的循环结构被打破了。后来想了想是不是wire库之间冲突了,所以我借鉴了这个大佬的程序
https://blog.csdn.net/TonyIOT/article/details/105778466

#include <DS1302.h>

DS1302 rtc(2, 3, 4); //对应DS1302的RST,DAT,CLK

void initRTCTime(void)//初始化RTC时钟
{
  rtc.writeProtect(false); //关闭写保护
  rtc.halt(false); //清除时钟停止标志
  Time t(2020, 4, 25, 21, 50, 50, 7); //新建时间对象 最后参数位星期数据,周日为1,周一为2以此类推
  rtc.time(t);//向DS1302设置时间数据
}

void printTime()//打印时间数据
{
  Time tim = rtc.time(); //从DS1302获取时间数据
  char buf[50];
  snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
           tim.yr, tim.mon, tim.date,
           tim.hr, tim.min, tim.sec);

  Serial.println(buf);
}

void setup() {
  Serial.begin(9600);

  //新模块上电需要设置一次当前时间,
  //下载完成后需屏蔽此函数再次下载,否则每次上电都会初始化时间数据
  initRTCTime();

}

void loop() {
  printTime();
  delay(1000);
}

推荐认真看一下,他的库我放到后续百度网盘链接中。

继电器

#define LIGHT_PIN  9  //设置继电器的控制数字引脚
void setup() {
  // put your setup code here, to run once:
  pinMode(LIGHT_PIN,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
    Serial.print("turn off the light");
    digitalWrite(LIGHT_PIN,LOW);
    
   
    Serial.print("turn on the light");
    digitalWrite(LIGHT_PIN,HIGH);
}

以上就是继电器的代码,通过高低电平控制其开关即可。
按键
按键我用的是上拉电阻
在这里插入图片描述我借鉴的是太极创客的资料代码,非常推荐这个网站,本人arduino7成的知识都来自于这个网站。

#define button1 6   //按键1,加减
#define button2 7   //按键2,开启设置,确定
void setup() {
  // put your setup code here, to run once:
  pinMode(button1,INPUT);
  pinMode(button2,INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

}

EEPROM
之所以用它,相必也猜到了,掉电我也要保证数据不会丢失。

#include <EEPROM.h>
char TimeOn[6]={'0','8',':','0','0'};
char TimeOff[6]={'2','1',':','0','0'};
char All[12];
void setup() {
  // put your setup code here, to run once:
  // 初始化串口
  Serial.begin(9600);
  //等待串口准备好
  //在地址0~3依次写入2~5
  for(int i = 0;i<6;i++){
    EEPROM.write(i,TimeOn[i]);
    //延时100ms 等待写入
    delay(10);
  }
  for(int i = 0;i<6;i++){
    EEPROM.write(i+6,TimeOff[i]);
    //延时100ms 等待写入
    delay(10);
  }
    for(int i = 0;i<12;i++){
     All[i]=EEPROM.read(i);
    Serial.print(All[i]);
  }
// for(int i = 0;i<6;i++){
//    EEPROM.write(i, 0);
//  }
//  Serial.println("clear");
//  TimeOn[0]={'0'};TimeOn[1]={'8'};
//  
//  Serial.println(EEPROM.length());
//  for (int i = 0 ; i < 6 ; i++) {
//    TimeOn[i]=EEPROM.read(i);
//    //Serial.println(i);
//    delay(3);
//  }
//  for(int i=0;i<6;i++)
//  Serial.print(TimeOn[i]);
//   Serial.println("read data end");
//   TimeOn[0]={'0'};TimeOn[1]={'8'};
//   for(int i=0;i<6;i++)
//  Serial.print(TimeOn[i]);
}

void loop() {
  // put your main code here, to run repeatedly:

}

以上是EEPROM调试代码,注意它是有寿命的可擦除次数在20000次左右。
整体代码
写代码,首先就要有思路,大致的讲一讲:
1.时间变量有5位(09:00)我用了一个char型6位数组放置数据,因为我发现5位的话,OLED屏上会有乱码。然后再构建了一个timeOn[6],timeOff[6]用于贮存开关灯时间,再用EEPROM的12位储存以上数据。
2.当按键2按下后,让其再子循环中无限循环,设置小时或者分钟时,让其在它的子循环中无限循环所以我的while(1)用的比较多,这时候我不能用break了太麻烦,我选择了goto。
3.设置时按键1,按键2高电平为设置,OLED屏
display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色,用于显示。
4.设置步骤先按下按键2一秒左右,OLED屏小时出现设置框图,通过按键1加数,加至24后归0;再按下按键2,开始设置分钟,按键2设置分钟时间,加到60之后返回至0;再次按下按键2,选择设置的时间是开灯时间或者是关灯时间;再按下按键2,OLED屏会显示OK,表示设置完成。
6.初始化开启时间为08:00,关闭时间为21:00

#include <DS1302.h>
#include <EEPROM.h>
//#include <Arduino_FreeRTOS.h>
//void serilafun1(void *param);
//void serilafun2(void *param);

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//注意时钟模块需要断电和程序重装才能有时间改变

DS1302 rtc(2, 3, 4); //对应DS1302的RST,DAT,CLK
int sec_temp;
char datestring[20];char days[11];char times[6];int val=0;int var=0;char light[2]="ON";
char TimeOn[6]={'0','8',':','0','0'};
char TimeOff[6]={'2','1',':','0','0'};
#define button1 6   //按键1,加减
#define button2 7   //按键2,开启设置,确定
#define button3 8
#define LIGHT_PIN  9  //设置继电器的控制数字引脚
#define OLED_RESET 4
#define SSD1306_LCDHEIGHT 64
Adafruit_SSD1306 display(OLED_RESET);

#define LOGO16_GLCD_HEIGHT 16 //定义显示高度
#define LOGO16_GLCD_WIDTH  16 //定义显示宽度

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
void initRTCTime(void)//初始化RTC时钟
{
  rtc.writeProtect(false); //关闭写保护
  rtc.halt(false); //清除时钟停止标志
  Time t(2020, 4, 25, 21, 50, 50, 7); //新建时间对象 最后参数位星期数据,周日为1,周一为2以此类推
  rtc.time(t);//向DS1302设置时间数据
}

void updatTime()//打印时间数据
{
  Time tim = rtc.time(); //从DS1302获取时间数据
  char date[20];
  char timer[20];
  snprintf(date, sizeof(date), "%04d-%02d-%02d",
           tim.yr, tim.mon, tim.date);
  snprintf(timer, sizeof(timer), "%02d:%02d:%02d",
           tim.hr, tim.min, tim.sec);
    for(int i=0;i<10;i++)
    days[i]=date[i]; 
    for(int i=0;i<5;i++)    //5 第三位是:
    times[i]=timer[i]; 
  if (tim.sec != sec_temp) { //一秒刷新一次   
    
    display.clearDisplay();//清屏
    display.setCursor(0, 2);//设置显示位置
    display.println(days);
    display.setCursor(0, 24);//设置显示位置
    display.println(times);
    display.setCursor(30, 50);//设置显示位置
    display.print("ON");
    display.setCursor(55,50);//设置显示位置
    display.print("/");
    display.setCursor(65,50);//设置显示位置
    display.println("OFF");
    display.display(); // 开显示
  }
  sec_temp = tim.sec;
}

void setup(){
  Serial.begin(9600);
  pinMode(button1,INPUT);
  pinMode(button2,INPUT);
  pinMode(LIGHT_PIN,OUTPUT);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.setTextColor(WHITE);//开像素点发光
  display.clearDisplay(); //清屏
  display.setTextSize(2); //设置字体大小
//  while (!Serial);//等待串口连接后执行
//  xTaskCreate(serilafun1, "serilaName1" ,100, NULL, 4, NULL);//任务函数,任务名称,任务堆栈,任务输入参数(可以为NULL),任务优先级(0是最低优先级),任务传递句柄
//  xTaskCreate(serilafun2, "serilaName2" ,100, NULL, 3, NULL);
// // xTaskCreate(serilafun3, "serilaName3" ,100, NULL, 5, NULL);
//  vTaskStartScheduler();

}


//void serilafun1(void *param)
//{
//  while (1)
//  {
//    RtcDateTime now = Rtc.GetDateTime(); //调用printDateTime函数
//    printDateTime(now);
//  }
//}
//void serilafun2(void *param)
//{
//  while (1)
//  {
//   u8g2.firstPage();
//  do
//  {
//    page1();
//    vTaskDelay(1000);
//  }while(u8g2.nextPage());
//  }
//}
//void serilafun3(void *param)
//{
//   while (1)
//  {
//    readbutton();
//  }
//}

void loop(){
    updatTime();
    readbutton();
    LightCotrol();
    delay(1000);
}


void readbutton(){
  //Serial.println(digitalRead(button2));
  //Serial.println(digitalRead(button1));
  if(digitalRead(button2)==1)
  {
    delay(50);
    Serial.println("开始设置");
    display.setTextSize(2); 
    display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
    display.setCursor(0,25);          //128*64的点阵屏对应x,y轴,x,y的起始点
    display.print(times[0]);   //这里输入显示内容,可以是变量
    display.print(times[1]);   //这里输入显示内容,可以是变量
    display.display();
    while(1){
    if(digitalRead(button1)==1&&val==0){
    while(1){
      Serial.println();
      int hours[2];
      for(int i=0;i<2;i++)
      hours[i]=(int)times[i]-48;   //把char改成int型,中间变量方便人工改变时间
      int a=hours[0];int b=hours[1];unsigned int sum=a*10+b;
    
      display.setTextSize(2); 
      display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
      display.setCursor(0,25);          //128*64的点阵屏对应x,y轴,x,y的起始点
      display.print(sum);   //这里输入显示内容,可以是变量
      display.display();
      Serial.print(a);Serial.print("  ");Serial.println(b);
  
    while(1){
      if(digitalRead(button1)==1){  //按键加减
        delay(50);
        if(digitalRead(button1)==1){
        sum=sum+1;
        Serial.print("小时 ");
        delay(500);
        Serial.println(sum);
        if(sum>=24 ||sum<=0){
          sum=0;
        }
      }
      }
      
      a=sum/10;b=sum%10;   //变回char,用于显示
      char ac=char(a+48);
      char bc=char(b+48);
      times[0]=ac;
      times[1]=bc; 
      Serial.print("小时时间设置为 ");
      Serial.print(times[0]);
      Serial.println(times[1]);
      //Serial.println(sum);
      delay(100);
      display.setTextSize(2); 
      display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
      display.setCursor(0,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
      display.print(times[0]);   //这里输入显示内容,可以是变量
      display.print(times[1]);   //这里输入显示内容,可以是变量
      display.display();
      if(digitalRead(button2)==1){
      val=1;
      goto start;}
     
    }
     
    }
    start:{
     Serial.println("小时时间设置完成");
     display.setTextSize(2);
     display.setCursor(0,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
     display.print(times[0]);   //这里输入显示内容,可以是变量
     display.print(times[1]);   //这里输入显示内容,可以是变量
     //display.display(); 
    display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
    display.setCursor(35,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
    display.print(times[3]);   //这里输入显示内容,可以是变量
    display.print(times[4]);   //这里输入显示内容,可以是变量
    display.display();
     }
    }
    if(digitalRead(button1)==1&&val==1){
    display.setTextSize(2); 
    display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
    display.setCursor(35,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
    display.print(times[3]);   //这里输入显示内容,可以是变量
    display.print(times[4]);   //这里输入显示内容,可以是变量
    display.display();
      while(1){
      int minutes[2];
      for(int i=0;i<2;i++)
      minutes[i]=int(times[i+3])-48;   //把char改成int型,中间变量方便人工改变时间
      int a1=minutes[0];int b1=minutes[1];int sum1=a1*10+b1;
      
      display.setTextSize(2);
      display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色  
      display.setCursor(35,24);          //分钟对应的位置
      display.print(sum1);   //这里输入显示内容,可以是变量
      display.display();  
       Serial.print(a1);Serial.print("  ");Serial.println(b1);
      if(digitalRead(button1)==1){  //按键加减
        delay(20);
        if(digitalRead(button1)==1){
        sum1=sum1+1;
        Serial.print("分钟 ");
        delay(10);
        Serial.println(sum1);
        if(sum1>=60||sum1<0){
          sum1=0;
        }
      }
      }
      a1=sum1/10;b1=sum1%10;   //变回char,用于显示
      times[3]=char(a1+48);
      times[4]=char(b1+48);
      Serial.print("分钟时间设置为 ");
      Serial.print(times[3]);
      Serial.println(times[4]);

      display.setTextSize(2); 
      display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
      display.setCursor(35,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
      display.print(times[3]);   //这里输入显示内容,可以是变量
      display.print(times[4]);   //这里输入显示内容,可以是变量
      display.display();
      if(digitalRead(button2)==1){
      val=2;
      goto start1;
      }
     
    }
    start1:
     Serial.println("分钟时间设置完成");
      display.setTextSize(2); 
          display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色   
          display.setCursor(30,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
          display.print("ON");   //这里输入显示内容,可以是变量
          Serial.print("ON");   //这里输入显示内容,可以是变量
          display.setCursor(65,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
          display.print("OFF");   //这里输入显示内容,可以是变量
          display.display(); 
    }

      if(digitalRead(button1)==1&&val==2){
         delay(20);
      if(digitalRead(button1)==1&&val==2){  //按键加减
        int lights=1;
        Serial.println("设置开关灯");
       while(1){
       
        if(digitalRead(button1)==1&&lights==1){
          light[2]="ON";
          lights=0;
          display.setTextSize(2); 
          display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色   
          display.setCursor(30,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
          display.print("ON");   //这里输入显示内容,可以是变量
          Serial.print("ON");   //这里输入显示内容,可以是变量
          Serial.println(lights);
          display.setTextColor(WHITE,BLACK);
          display.setCursor(65,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
          display.print("OFF");   //这里输入显示内容,可以是变量
          display.display(); 
        }
       if(digitalRead(button1)==1&&lights==0){
        if(digitalRead(button1)==1&&lights==0){  //按键加减
          delay(30);
          light[2]="OF";
          lights=1;
         display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
         display.setTextSize(2); 
         display.setCursor(65,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
         display.print("OFF");   //这里输入显示内容,可以是变量
         Serial.print("OFF");   //这里输入显示内容,可以是变量
         Serial.println(lights);
         display.setTextColor(WHITE,BLACK);
         display.setCursor(30,50);          //128*64的点阵屏对应x,y轴,x,y的起始点
         display.print("ON");   //这里输入显示内容,可以是变量
         display.display();}
         
         }
       if(digitalRead(button2)==1&&lights==0){   //on 设置开启时间
       delay(20);
       if(digitalRead(button2)==1&&lights==0){
       Serial.println("完成设置");
       val=0;
       display.setTextColor(WHITE,BLACK);
       display.setCursor(80,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
       display.print("OK");   //这里输入显示内容,可以是变量
        display.display();
       delay(3000);
       display.setCursor(60,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
       display.print("    ");
       display.display();                  //显示以上
       for(int i=0;i<6;i++)
       TimeOn[i]=times[i];
       for(int i = 0;i<6;i++){
    EEPROM.write(i,TimeOn[i]);
    //延时100ms 等待写入
    delay(10);
  }
       goto start3;
       }
         
    }
     else if(digitalRead(button2)==1&&lights==1){   //off 设置关闭时间
       delay(20);
       if(digitalRead(button2)==1&&lights==1){
       Serial.println("完成设置");
       val=0;
       display.setTextColor(WHITE);
       display.setCursor(80,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
       display.print("OK");   //这里输入显示内容,可以是变量
        display.display();
       delay(3000);
       display.setCursor(60,24);          //128*64的点阵屏对应x,y轴,x,y的起始点
       display.print("    ");
       display.display();                  //显示以上
       for(int i=0;i<6;i++)
       TimeOff[i]=times[i];
       for(int i = 6;i<12;i++){
    EEPROM.write(i,TimeOff[i-6]);
    //延时100ms 等待写入
    delay(10);
  }
       goto start3;
       }
         
    }
  }
 }
}
    }
  }
  start3:
  Serial.println("end");
  }


 void LightCotrol(){
  for (int i = 0 ; i < 6 ; i++) {
   TimeOn[i]=EEPROM.read(i);
   //delay(10);
  }
  for (int i = 6 ; i < 12 ; i++) {
   TimeOff[i-6]=EEPROM.read(i);
   //delay(10);
  }
//  char All[12];
//   for(int i = 0;i<12;i++){
//     All[i]=EEPROM.read(i);
//    Serial.print(All[i]);
//  }
  int hour_ten_OFF,hour_ge_OFF,minute_ten_OFF,minute_ge_OFF;
  int hour_ten_ON,hour_ge_ON,minute_ten_ON,minute_ge_ON;
   Serial.println("关闭时间为:");
   Serial.println(TimeOff);    //通过它输出日历
   int hour_ten=(int)TimeOff[0]-48;     //小时十位  ASCLL码对应2
   int hour_ge=(int)TimeOff[1]-48; //小时个位  ASCLL码对应2
   int minute_ten =(int)TimeOff[3]-48;
   int minute_ge=(int)TimeOff[4]-48;

   Serial.println("开启时间为:");
   Serial.println(TimeOn);    //通过它输出日历
   int hour_ten1=(int)TimeOff[0]-48;     //小时十位  ASCLL码对应2
   int hour_ge1=(int)TimeOff[1]-48; //小时个位  ASCLL码对应2
   int minute_ten1 =(int)TimeOff[3]-48;
   int minute_ge1=(int)TimeOff[4]-48;
   //Serial.print(hour_ten);
   //Serial.print(hour_ge);
   //Serial.print(minute_ten);
   //Serial.println(minute_ge);

   if(hour_ten_OFF==hour_ten&&hour_ge_OFF==hour_ge&&minute_ten_OFF==minute_ten&&minute_ge_OFF==minute_ge){
    Serial.print("turn off the light");
    digitalWrite(LIGHT_PIN,LOW);
   }
   if(hour_ten_ON==hour_ten1&&hour_ge_ON==hour_ge1&&minute_ten_ON==minute_ten1&&minute_ge_ON==minute_ge1){
    Serial.print("turn on the light");
    digitalWrite(LIGHT_PIN,HIGH);
   }
  }

更具以上思路我写下了以上代码,然后我发现了一个问题,即便是构造了一个全局变量,贮存初始化的时间,但是我优先考虑的应该是EEPROM里边有没有时间,当时没想到什么好的逻辑算法进行两者之间的判断。所以打算把初始化的时间直接放到EEPROM里边。所以外加了一段初始化时间的代码,一定要在整体代码之前烧录,这是发现问题之后才写的代码,所以我补充在了后边。

初始化时间代码

#include <EEPROM.h>
char TimeOn[6]={'0','8',':','0','0'};
char TimeOff[6]={'2','1',':','0','0'};
char All[12];
void setup() {
  // put your setup code here, to run once:
  // 初始化串口
  Serial.begin(9600);
  //等待串口准备好
  //在地址0~3依次写入2~5
  for(int i = 0;i<6;i++){
    EEPROM.write(i,TimeOn[i]);
    //延时100ms 等待写入
    delay(10);
  }
  for(int i = 0;i<6;i++){
    EEPROM.write(i+6,TimeOff[i]);
    //延时100ms 等待写入
    delay(10);
  }
    for(int i = 0;i<12;i++){
     All[i]=EEPROM.read(i);
    Serial.print(All[i]);
  }
// for(int i = 0;i<6;i++){
//    EEPROM.write(i, 0);
//  }
//  Serial.println("clear");
//  TimeOn[0]={'0'};TimeOn[1]={'8'};
//  
//  Serial.println(EEPROM.length());
//  for (int i = 0 ; i < 6 ; i++) {
//    TimeOn[i]=EEPROM.read(i);
//    //Serial.println(i);
//    delay(3);
//  }
//  for(int i=0;i<6;i++)
//  Serial.print(TimeOn[i]);
//   Serial.println("read data end");
//   TimeOn[0]={'0'};TimeOn[1]={'8'};
//   for(int i=0;i<6;i++)
//  Serial.print(TimeOn[i]);
}

void loop() {
  // put your main code here, to run repeatedly:

}

以下是其的接线图
在这里插入图片描述设置时间图片
在这里插入图片描述
在这里插入图片描述串口调试初始化EEPROM时间
在这里插入图片描述成功设置时间后
在这里插入图片描述它会将初始化数据覆盖,掉电重启后数据依旧在。

以上就是整体设计,我将代码和库,等资料放在了百度网盘中,有需要的话,请带走

百度网盘链接:https://pan.baidu.com/s/1r93L29XekVZWya7f2A175w
提取码:khgi

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RouDragon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值