オーディオタイマーで換気2
 
前に書いた記事
https://ameblo.jp/fc2miha/entry-12833772945.html


ソースが間違っていたので修正。
arduinoのmillis関数が約50日間でオーバーフローし、ゼロに戻ります。
の件で、対処のプログラムを入れておいたはずだけどー
それにまんまとハマったらしいので
治しました。
■ソース
 
これも間違っておりましたので
 修正版は→https://ameblo.jp/fc2miha/entry-12833773004.html

 

 

#include <stdio.h>
#include <time.h>

#include <LiquidCrystal.h>
//LCD        arduino
// 4(rs)     D12
// 5(rw)     D11
// 6(enable) D10 
// 11(db4)    D5
// 12(db5)    D4
// 13(db6)    D3
// 14(db7)    D2
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

//
//D8をSSRへ接続
//

struct BUTTON
{
  int value;
  int flag;
  int input_pin;
};
struct BUTTON bt_select;
struct BUTTON bt_enter;
int lcd_back_light = 1;

void button_initialize()
{
  memset(&bt_select, NULL, sizeof(bt_select));
  bt_select.input_pin = 6;
  memset(&bt_enter, NULL, sizeof(bt_enter));
  bt_enter.input_pin = 7;
}

void tick_button(struct BUTTON *bt)
{
  int value = digitalRead(bt->input_pin);
  if(value!=bt->value){
    bt->value = value;
    bt->flag = 1;
//    if(value==HIGH){
//      digitalWrite(13, HIGH);
//      lcd_back_light = 1;
//    }
    delay(10);
  }
}

int get_button(int *status, struct BUTTON *bt)
{
  if(bt->flag == 1){
    *status = bt->value;
    bt->flag = 0;
    return 1;
  }
  else{
    return 0;
  }
}

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

  Serial.print("AcPowerControler version0.2 ¥n");
  
  //
  button_initialize();
  alarm_initialise();

  //lcd back light
  digitalWrite(13, HIGH);

  //SSR
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  //Input
  pinMode(6, INPUT);  //enter button
  pinMode(7, INPUT);  //select button
  //back light
  pinMode(13, OUTPUT);  //LCD back light

  //LCD
  lcd.begin(2,16);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("AcPowerControler");
  delay(500);
  //
  setup_time_input();
}

void setup_time_input()
{
  int YYYY = input("input year?", 4, 2020, 2020, 2100);
  int MM = input("input month?", 2, 1, 1, 12);
  int DD = input("input day?", 2, 1, 1, 31);
  int hh = input("input hour?", 2, 0, 0, 23);
  int mm = input("input minits?", 2, 0, 0, 59);

  initDateTime(YYYY, MM, DD, hh, mm);

  lcd.clear();

}

int input(char *str, int keta, int def, int mMin, int nMax)
{
  lcd.clear();
  lcd.print(str);

  int  i = 0;
  char buf[17];
  char ch[2];
  //
  lcd.blink();
  //
  int value = def;

  int flag = 1;
  int status;
  while(1){
    tick_button(&bt_select);
    tick_button(&bt_enter);

    if(flag==1){
      //
      if(keta==4){
        sprintf(buf, "%04d", value);
      }
      if(keta==2){
        sprintf(buf, "%02d", value);
      }
      if(keta==1){
        sprintf(buf, "%01d", value);
      }
      lcd.setCursor(0, 1);
      lcd.print(buf);
      lcd.setCursor(keta-1, 1);
      flag = 0;
    }
    if(get_button(&status, &bt_enter)){
      if(status==HIGH){
        return value;
      }
    }
    if(get_button(&status, &bt_select)){
      if(status==HIGH){
        flag = 1;
        value++;
        if(value>nMax){
          value = mMin;
        }
      }
    }
  }
}

void lcd_print(int x, int y, char *str)
{
  lcd.setCursor(x, y);
  lcd.print(str);
}

struct DateTime {
  time_t base_time;
  unsigned long BaseMillis;
  unsigned long base_startup_keika_sec;
};
struct DateTime date_time;


void initDateTime(int YYYY, int MM, int DD, int hh, int mm)
{
    struct tm now;
    now.tm_year = YYYY-1900;     /* 2001年 */
    now.tm_mon  = MM-1;       /* 5月    */
    now.tm_mday = DD;      /* 20日   */
    now.tm_wday = 0;       /* 日曜日 */
    now.tm_hour = hh;      /* 14時   */
    now.tm_min  = mm;      /* 20分   */
    now.tm_sec  = 0;       /* 00秒   */
    now.tm_isdst= -1;      /* 夏時間無効 */
    
    date_time.base_time = mktime(&now);
    if (date_time.base_time == (time_t) - 1) { //error
      date_time.base_time = 0;
    }
    date_time.BaseMillis = millis();
    date_time.base_startup_keika_sec = date_time.BaseMillis / 1000;
}

struct HHMM{
  int HH;
  int MM;
  int YOUBI;
};
struct HHMM hhmm;

unsigned long getSec()
{
  //現在時刻累積秒を求める
  unsigned long now_startup_keika_sec = millis() / 1000;
  return date_time.base_time + ((time_t)now_startup_keika_sec - (time_t)date_time.base_startup_keika_sec);
}

void getDateTime(struct HHMM *hhmm)
{
  //現在時刻累積秒を求める
  unsigned long now_startup_keika_sec = millis() / 1000;
  time_t now_time = date_time.base_time + ((time_t)now_startup_keika_sec - (time_t)date_time.base_startup_keika_sec);
  
  //localtimeにする
  //now_time = now_time + 60 * 60 * 9;

  struct tm   *time_inf;
  time_inf = localtime(&now_time);

  hhmm->HH = time_inf->tm_hour;
  hhmm->MM = time_inf->tm_min;
  hhmm->YOUBI = time_inf->tm_wday;
}

void getDateTimeStr(char *buf1, char *buf2)
{
  //現在時刻累積秒を求める
  unsigned long now_startup_keika_sec = millis() / 1000;
  time_t now_time = date_time.base_time + ((time_t)now_startup_keika_sec - (time_t)date_time.base_startup_keika_sec);
  
  //localtimeにする
  //now_time = now_time + 60 * 60 * 9;

  struct tm   *time_inf;
  time_inf = localtime(&now_time);

  int year = time_inf->tm_year + 1900;
  int month = time_inf->tm_mon + 1;
  int day = time_inf->tm_mday;
  int hour = time_inf->tm_hour;
  int minute = time_inf->tm_min;
  int second = time_inf->tm_sec;
  char *wday[] = {"SUN","MON","TUE","WED","TUE","FRI","SAT"};
  sprintf(buf1, "%04d/%02d/%02d %s", year, month, day, wday[time_inf->tm_wday]);
  sprintf(buf2, "%02d:%02d:%02d", hour, minute, second);
}

int debugCount=0;
void tick_time()
{
  int debugFlag = ((debugCount%100)==0);
  debugCount++;
  if(debugFlag){
    Serial.println("tick_time() start");
  }
  unsigned long now = millis();
  if(debugFlag){
    Serial.print("now=");
    Serial.println(now);
    Serial.print("date_time.BaseMillis=");
    Serial.println(date_time.BaseMillis);
  }
  if(now < date_time.BaseMillis){
    date_time.BaseMillis = now;
    //date_time.base_startup_keika_sec  = ((4294967295 - date_time.BaseMillis) + now)/1000;
    date_time.base_startup_keika_sec = date_time.BaseMillis / 1000;
    Serial.println("tick_time() point 1");
  }
  if(debugFlag){
    Serial.println("tick_time() end");
  }
}

struct ALARM
{
  int mode;   //  0=week, 1=alway on, 2=alway off, 3=after on, 4=after off
  int SUN;
  int MON;
  int TUE;
  int WED;
  int THU;
  int FRI;
  int SAT;
  int start_hh;
  int start_mm;
  int end_hh;
  int end_mm;
  int after_on_hh;
  int after_off_hh;
  unsigned long setSec;
};
struct ALARM alarm;

int flag = 0;
unsigned long nCount = 0;
void loop()
{
  nCount++;

  //lcd.noCursor();

  tick_time();
  tick_button(&bt_select);
  tick_button(&bt_enter);

  //LCD back light
  if(lcd_back_light==1){
    digitalWrite(13, HIGH);
  }
  else{
    digitalWrite(13, LOW);
  }
  
  //DEBUG
  //int kakeru = 60;    //DEBUG
  int kakeru = 3600;  //本番向け
  //
  unsigned long nowSec = getSec();
  //表示
  if(alarm.mode==0 || alarm.mode==1 || alarm.mode==2){  //week alway
    char date[20];
    char time[20];
    getDateTimeStr(date, time);
    lcd_print(0, 0, date);
    lcd_print(0, 1, time);
    if(alarm.mode==0){
      lcd_print(8, 1, " weekly  ");
    }
    if(alarm.mode==1){
      lcd_print(8, 1, " all ON  ");
    }
    if(alarm.mode==2){
      lcd_print(8, 1, " all OFF ");
    }
  }else
  if(alarm.mode==3 || alarm.mode==4){
    int sec;
    if(alarm.mode==3){
      sec = alarm.setSec+(alarm.after_on_hh * kakeru) - nowSec;
    }
    else{
      sec = alarm.setSec+(alarm.after_off_hh * kakeru) - nowSec;
    }
//    Serial.print("sec=");
//    Serial.println(sec);
    if(sec<0){
      sec=0;
    }
    int hh = sec / 3600;
    int mm = (sec - (hh * 3600))/60;
    int ss = sec % 60;
    char buf[17];
    sprintf(buf, "%02d:%02d:%02d", hh, mm, ss);
    lcd_print(0, 0, buf);
    if(alarm.mode==3){
      lcd_print(8, 1, " afterON ");
    }
    if(alarm.mode==4){
      lcd_print(8, 1, "afterOFF");
    }
  }
  

  lcd.setCursor(1, 0);

  //現在時刻取得
  struct HHMM hhmm;
  getDateTime(&hhmm);
  //日付跨ぎの補正
  int alarmStartHHMM = (alarm.start_hh * 100 + alarm.start_mm)  ;
  int alarmEndHHMM   = (alarm.end_hh * 100 + alarm.end_mm);
  int nowHHMM = (hhmm.HH * 100 + hhmm.MM);
  if(alarmStartHHMM>alarmEndHHMM){
    alarmEndHHMM = alarmEndHHMM + 2400;
  }
  if(alarmStartHHMM>nowHHMM){
    nowHHMM = nowHHMM + 2400;
  }
  //
  if(alarm.mode==0){  //week
    //
    if((hhmm.YOUBI==0 && alarm.SUN==1)
     ||(hhmm.YOUBI==1 && alarm.MON==1)
     ||(hhmm.YOUBI==2 && alarm.TUE==1)
     ||(hhmm.YOUBI==3 && alarm.WED==1)
     ||(hhmm.YOUBI==4 && alarm.THU==1)
     ||(hhmm.YOUBI==5 && alarm.FRI==1)
     ||(hhmm.YOUBI==6 && alarm.SAT==1)){
  /*    
   *   if( (alarm.start_hh * 100 + alarm.start_mm) <= (hhmm.HH * 100 + hhmm.MM) 
                                                  && (hhmm.HH * 100 + hhmm.MM) < (alarm.end_hh * 100 + alarm.end_mm)){
  */
      if( alarmStartHHMM <= nowHHMM && nowHHMM < alarmEndHHMM){
        digitalWrite(8, HIGH);
      }
      else{
        digitalWrite(8, LOW);
      }
    }
    else{
      digitalWrite(8, LOW);
    }
  }else
  if(alarm.mode==1){    //alway on
    digitalWrite(8, HIGH);
  }else
  if(alarm.mode==2){    //alway off
    digitalWrite(8, LOW);
  }else
  if(alarm.mode==3){    //after on
    if(alarm.setSec+(alarm.after_on_hh * kakeru) >= nowSec){
      digitalWrite(8, LOW);
    }
    else{
      digitalWrite(8, HIGH);
    }
  }else
  if(alarm.mode==4){    //after off
    if(alarm.setSec+(alarm.after_off_hh * kakeru) <= nowSec){
      digitalWrite(8, LOW);
    }
    else{
      digitalWrite(8, HIGH);
    }
  }
  
  
  //
  int status;
  if(get_button(&status, &bt_select)){
    if(status==HIGH){
      //alarm_input();
      if(lcd_back_light==0){
        lcd_back_light = 1;
      }
      else{
        lcd_back_light = 0;
      }
    }
  }
  if(get_button(&status, &bt_enter)){
    if(status==HIGH){
      alarm_input();
    }
  }
  delay(10);
}

void alarm_initialise()
{
  memset(&alarm, NULL, sizeof(struct ALARM));
  alarm.SUN = 1;
  alarm.MON = 1;
  alarm.TUE = 1;
  alarm.WED = 1;
  alarm.THU = 1;
  alarm.FRI = 1;
  alarm.SAT = 1;
  alarm.after_on_hh = 1;
  alarm.after_off_hh = 1;
}

void alarm_input()
{
  //lcd back light
  digitalWrite(13, HIGH);
  //
  alarm.mode = select_input5("mode :", "weekly    ", "always on ", "always off", "after on  ", "after off ", alarm.mode);
  if(alarm.mode==0){
    //weekly
    alarm.SUN = select_input("[SUN] : ", "  ", "ON", alarm.SUN);
    alarm.MON = select_input("[MON] : ", "  ", "ON", alarm.MON);
    alarm.TUE = select_input("[TUE] : ", "  ", "ON", alarm.TUE);
    alarm.WED = select_input("[WED] : ", "  ", "ON", alarm.WED);
    alarm.THU = select_input("[THU] : ", "  ", "ON", alarm.THU);
    alarm.FRI = select_input("[FRI] : ", "  ", "ON", alarm.FRI);
    alarm.SAT = select_input("[SAT] : ", "  ", "ON", alarm.SAT);
  
    alarm.start_hh = input("start hour",   2, alarm.start_hh, 0, 23);
    alarm.start_mm = input("start minits", 2, alarm.start_mm, 0, 59);
    alarm.end_hh   = input("end hour",     2, alarm.end_hh,   0, 23);
    alarm.end_mm   = input("end minits",   2, alarm.end_mm,   0, 59);
  }
  if(alarm.mode==3){
    //after on
    alarm.after_on_hh = input("after hour",   1, alarm.after_on_hh, 1, 9);
    alarm.setSec = getSec();
    Serial.print("alarm.setSec=");
    Serial.println(alarm.setSec);
  }
  if(alarm.mode==4){
    //after off
    alarm.after_off_hh = input("after hour",   1, alarm.after_off_hh, 1, 9);
    alarm.setSec = getSec();
  }

  lcd.clear();

  lcd_back_light = 1;
}

int select_input(char *str, char *select1, char *select2, int def)
{
  lcd.clear();
  lcd.print(str);

  int  value = def;
  char buf[17];
  char select[17];
  //
  lcd.blink();
  //
  strcpy(buf, "");
  strcpy(select, select1);

  int flag = 1;
  int status;
  while(1){
    tick_button(&bt_select);
    tick_button(&bt_enter);

    if(flag==1){
      if(value==0){
        sprintf(buf, "%s", select1);
      }
      else{
        sprintf(buf, "%s", select2);
      }
      lcd.setCursor(0, 1);
      lcd.print(buf);
      lcd.setCursor(strlen(buf)-1, 1);
      flag = 0;
    }
    if(get_button(&status, &bt_enter)){
      if(status==HIGH){
        return value;
      }
    }
    if(get_button(&status, &bt_select)){
      if(status==HIGH){
        flag = 1;
        if(value==0){
          value = 1;
        }
        else{
          value = 0;
        }
      }
    }
  }
  return 0;
}

int select_input5(char *str, char *select1, char *select2, char *select3, char *select4, char *select5, int def)
{
  lcd.clear();
  lcd.print(str);

  int  value = def;
  char buf[17];
  char select[17];
  //
  lcd.blink();
  //
  int flag = 1;
  int status;
  while(1){
    tick_button(&bt_select);
    tick_button(&bt_enter);

    if(flag==1){
      if(value==0){
        sprintf(buf, "%s", select1);
      }else
      if(value==1){
        sprintf(buf, "%s", select2);
      }else
      if(value==2){
        sprintf(buf, "%s", select3);
      }else
      if(value==3){
        sprintf(buf, "%s", select4);
      }
      else{
        sprintf(buf, "%s", select5);
      }
      lcd.setCursor(0, 1);
      lcd.print(buf);
      lcd.setCursor(strlen(buf)-1, 1);
      flag = 0;
    }
    if(get_button(&status, &bt_enter)){
      if(status==HIGH){
        return value;
      }
    }
    if(get_button(&status, &bt_select)){
      if(status==HIGH){
        flag = 1;
        if(value==0){
          value = 1;
        }else
        if(value==1){
          value = 2;
        }else
        if(value==2){
          value = 3;
        }else
        if(value==3){
          value = 4;
        }
        else{
          value = 0;
        }
      }
    }
  }
  return 0;
}