nobcha23の日記

PICマイコンやArduinoを使う電子回路遊びを紹介します

RTC+CSM のスケッチです

ARDUINOにi2cでRTCとLCDとキャパシティブセンシングキースレーブをくっつけて時計機能とか、アラーム機能を試作しました。
RTCはばんとさんのライブラリーを利用。
LCDはエレキジャックの光村さんのライブラリーを利用。
キャパシティブセンシングのキースレーブはPIC16F1827で自作です。

タイマーコールして、割り込みでタイムアップを表示します。
一回きりタイマーのみ実装。

0x34キーでタイマー設定画面が起動し、分単位でのタイマー値が
できるようになります。UP/DOWNキーで0から59までを選択
0x31キーで時計表示に戻り、タイマースタート。

次の59秒時(設定した秒によりタイマー実時間が縮むのがイマイチ)
になるとD13のLEDが点灯し、LCDの2行目右側にTimeUp表示が出ます。
表示はおよそ10秒間で消えます。

繰り返しタイマーと年月時秒指定アラームは今回は取り組まず。
これにてばんとさんのRTC-8564ライブラリーの主たる機能は確かめ
たということになります。


さて、ちょいと長くなりますが、スケッチは次の通りです。

    // i2c RTC-8564NB -> i2c Lcd
    // Using BANT's library by nobcha 05/06/2013
    // RTC8564 http://memo.tank.jp/archives/7734
    // Using MITSUNAGA's library by nobcha 05/06/2013
    // i2c_lcd http://n.mtng.org/ele/arduino/i2c.html
    // nobcha
    // 2013.06.09 debugged
    // RTC_TIME ok RTC_setTIMER ok    

    #include <I2CLiquidCrystal.h>
    #include <Wire.h>
    #include <RTC8564.h>

    RTC8564 RTC;
    RTC_TIME rtc_time;
    bool fWakeUp;

    const char* dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    char key_data, key_ref, set_pos,fWake_cnt;

    char LCD_CUR[7][2]={{0x03,0},{0x06,0},{0x09,0},{0x0C,0},
                       {0x2,1},{0x5,1},{0x8,1}};
                                           // cursor position
    char RTC_VALUE[8][3]  =  {{11,30,5},   // initial,MAX,MIN
			     {10,12,1},
		 	     {10,31,1},
                             {1,6,0},
			     {18,23,0},
			     {59,59,0},
			     {59,59,0}, 
                             {59,59,00}};	
	// year,month,day,weekday,hour,minute,second,timer
    
    // initialize the library
    I2CLiquidCrystal lcd(50, true);
    // | +--- set true if the power suply is 5V, false if it is 3.3V
    // +-------- contrast (0-63)
    void wakeup()
    {
      fWakeUp = true;
    }

    void setup()
    {
      Wire.begin();
      lcd.begin(16,2); // set lib for display size (16x2)
      lcd.clear(); // clear the screen
      RTC.begin();
      fWakeUp = false;
      attachInterrupt(0, wakeup, FALLING);
      pinMode(13,OUTPUT);
      fWake_cnt=10;
      if(rtc_time.month==0)
      {
      /* 2013年5月6日 0時0分0秒に時刻合わせ */
        rtc_time.year = 2013;
        rtc_time.month = 5;
        rtc_time.day = 6;
        rtc_time.hour = 12;
        rtc_time.min = 0;
        rtc_time.sec = 0;
        RTC.adjust( rtc_time );
      }

    }
    
    char Key_get( )
    {
      char key;
      key_ref=0x0;
      Wire.requestFrom(0x38,1);  // scm key:0x70
      key=Wire.read();
      Wire.endTransmission();
      if(key==key_data) key_ref=0x0;
      else key_ref=0x1;
      return key;
    }
    
     // data increment and MAX check
    void data_inc(char set_pos )
    {
      RTC_VALUE[set_pos][0]++;
      if(RTC_VALUE[set_pos][0]>(RTC_VALUE[set_pos][1]))
      {
	RTC_VALUE[set_pos][0]=RTC_VALUE[set_pos][2];
      }
    }

    // data decrement and 0 check
    void data_dec(char set_pos)
    {
      if(RTC_VALUE[set_pos][0]==RTC_VALUE[set_pos][2])
      {
	RTC_VALUE[set_pos][0]=RTC_VALUE[set_pos][1]+1;
      }
      RTC_VALUE[set_pos][0]--;
    }

    // RTC_VALUE loading from rtc_data
    void  rtc_value_load()
    {
      RTC_VALUE[0][0]=(char)(rtc_time.year-2000);
      RTC_VALUE[1][0]=rtc_time.month;
      RTC_VALUE[2][0]=rtc_time.day;
      RTC_VALUE[3][0]=rtc_time.wday;  
      RTC_VALUE[4][0]=rtc_time.hour;
      RTC_VALUE[5][0]=rtc_time.min;
      RTC_VALUE[6][0]=rtc_time.sec;   
    }
    // RTC_VALUE recovering to rtc_data  
    void rtc_value_recover()
    {         
      rtc_time.year=RTC_VALUE[0][0]+2000;
      rtc_time.month=RTC_VALUE[1][0];
      rtc_time.day=RTC_VALUE[2][0];
      rtc_time.wday=RTC_VALUE[3][0];  
      rtc_time.hour=RTC_VALUE[4][0];
      rtc_time.min=RTC_VALUE[5][0];
      rtc_time.sec=RTC_VALUE[6][0]; 
  
    }

// main loop
    void loop(void)
    {
      char buf[32];
      char  key_1;
      if(RTC.now(&rtc_time))
      {
        snprintf(buf,16,"%04u-%02u-%02u(%s)",
        rtc_time.year,
        rtc_time.month,
        rtc_time.day,
        dayofweek[rtc_time.wday]);

        lcd.setCursor(0,0);
        delay(100);
        lcd.print(buf);
        delay(100);
        snprintf(buf,16," %02u:%02u:%02u",
        rtc_time.hour,
        rtc_time.min,
        rtc_time.sec );

        lcd.setCursor(0,1);
        delay(100);
        lcd.print(buf);
      }
      
      key_data=Key_get();
    
      if(key_data!=0)
      {
        lcd.setCursor(9,1);
        snprintf(buf,8," k=%02X%02X",
        key_data, key_ref );
        lcd.print(buf);
      }
      if((key_data==0x31)&(key_ref==1))
      {
           
        set_pos=0;		// YEAR->Month->day->hour->minuts->second
        rtc_value_load();

        lcd.blink();
        delay(300);
 
        while(set_pos<7)
        {		       // set_pos:5->0
          char line, cur, key_in_data;
          line=LCD_CUR[set_pos][1];
          cur=LCD_CUR[set_pos][0];
          lcd.setCursor(cur,line);
          delay(100);
	  key_data=Key_get();
          lcd.setCursor(9,1);    
          snprintf(buf,8," k=%02X%02X",
          key_data, key_ref );
          lcd.print(buf);
    
          if(key_ref==0) key_in_data=0;
          else key_in_data=key_data;
          if(key_in_data==0x32)         // 0x32:increment
          { data_inc(set_pos);}
          else if(key_in_data==0x33)    // 0x33:decrement
          { data_dec(set_pos);}
          else if(key_in_data==0x31)
          {	set_pos++;}
          delay(100);
          rtc_value_recover();
          RTC.adjust( rtc_time );      
                
          snprintf(buf,16,"%04u-%02u-%02u(%s)",
          rtc_time.year,
          rtc_time.month,
          rtc_time.day,
          dayofweek[rtc_time.wday]);

          lcd.setCursor(0,0);
          delay(100);
          lcd.print(buf);
        
          delay(100);
          snprintf(buf,16," %02u:%02u:%02u",
          rtc_time.hour,
          rtc_time.min,
          rtc_time.sec );

          lcd.setCursor(0,1);
          delay(100);
          lcd.print(buf);
        } 
        delay(100);
      }
      lcd.setCursor(9,1);    
      snprintf(buf,8,"         " );
      lcd.print(buf);
      
      
      if((key_data==0x34)&(key_ref==1))  // 0x34 ?
      {    
        delay(200);
        RTC_VALUE[7][0]=0;
        while(Key_get( )!=0x31)
        { 
          char key_in_data;
          key_data=Key_get( );       
          snprintf(buf,16,"Timer set %02uMIN",RTC_VALUE[7][0]);
          lcd.setCursor(0,0);
          delay(100);
          lcd.print(buf);
          lcd.setCursor(11,0);
          lcd.blink();
          delay(300);
          if(key_ref==0) key_in_data=0;
          else key_in_data=key_data;
          if(key_in_data==0x32)         // 0x32:increment
          { data_inc(7);}
          else if(key_in_data==0x33)    // 0x33:decrement
          { data_dec(7);}
        }  
        RTC.setTimer(RTC.TIMING_1_MIN, RTC_VALUE[7][0] , true, true);
      }
      if((fWakeUp == true)&(fWake_cnt!=0))
      {
        digitalWrite(13,HIGH);
        snprintf(buf,16,"TimeUP");
        lcd.setCursor(9,1);
        delay(100);
        lcd.print(buf);
        fWake_cnt--;
        if(fWake_cnt==0)
        {
          fWakeUp=false;
          fWake_cnt=10;
          digitalWrite(13,LOW);
          snprintf(buf,16,"      ");
          lcd.setCursor(9,1);
          delay(100);
          lcd.print(buf);
        }
      }

      delay(500);
    }
  
// 2013.06.08
// Timer set indicator ok
// Alarm function debugging ok
// How can I read out REG value?