オーディオタイマーで換気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;
}