目次
前
次
RTC処理
Arduinoで、次のRTC(Real Time Clock)を扱えたので
備忘録として、残しておきます。
回路は、次のようにプルアップ抵抗を入れて、Arduinoの
IICバスに接続。
最初は、IICバスを利用した独自関数を製作していました。
WEBで検索すると、DS1307を扱うライブラリがあったので
こちらでどの程度のことができるのかを調べることに。
サンプルスケッチは、次のようになっています。
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
void setup () {
Serial.begin(9600);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop () {
DateTime now = RTC.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
delay(1000);
}
RTCをオブジェクトで扱えるようにし、クラス
インスタンスのメソッドで、情報を引き出す
仕様。
RTCは、どこかで年月日時分秒を設定しないと
使い物にならないので、それがどうなっている
のかを調べました。
C++のソースコードを読むのは面倒なので、ヘッダ
ファイルの内容を見てみました。
// Code by JeeLabs http://news.jeelabs.org/code/
// Released to the public domain! Enjoy!
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime {
public:
DateTime (uint32_t t =0);
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
DateTime (const char* date, const char* time);
uint16_t year() const { return 2000 + yOff; }
uint8_t month() const { return m; }
uint8_t day() const { return d; }
uint8_t hour() const { return hh; }
uint8_t minute() const { return mm; }
uint8_t second() const { return ss; }
uint8_t dayOfWeek() const;
// 32-bit times as seconds since 1/1/2000
long secondstime() const;
// 32-bit times as seconds since 1/1/1970
uint32_t unixtime(void) const;
protected:
uint8_t yOff, m, d, hh, mm, ss;
};
// RTC based on the DS1307 chip connected via I2C and the Wire library
class RTC_DS1307 {
public:
static uint8_t begin(void);
static void adjust(const DateTime& dt);
uint8_t isrunning(void);
static DateTime now();
};
// RTC using the internal millis() clock, has to be initialized before use
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
class RTC_Millis {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static DateTime now();
protected:
static long offset;
};
クラスRTC_DS1307のパブリックメソッドに
adjustがあるので、これで年月日時分秒を
調整するのだと合点。
クラスメソッドのadjustの引数が、DateTimeと
クラスを使うので、DateTimeに関して眺めます。
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
年月日時分秒を指定するメソッドが定義されている
ことから、初期化は以下の記述すればよいと判断。
RTC.adjust(DateTime(year,month,day,hh,mm,ss));
RTCに関係するコンストラクタ、メソッドを試験する
ために、次のスケッチを定義しました。
#include <MsTimer2.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include "RTClib.h"
/* Real Timer Clock */
RTC_DS1307 RTC;
/* LCD rs , e , D4 , D5 , D6 , D7 */
LiquidCrystal lcd(28,29,30,31,32,33);
/* Real Time Clock address */
#define RTC_ADRSX 0x68
#define OFF 0
#define ON OFF+1
#define XINTERVAL 25
#define RSIZE 8
#define BSIZE 32
#define BSIZEX 52
#define LED_BIT 13
#define RST_WDT 26
#define ENTRY_LCD 28
#define ENTRY_LCD_EXIT 34
#define MON_OUT 46
/* function prototype */
void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
char get_asc(byte x);
byte get_hex(char x);
void show_value_byte(byte x);
void show_value_word(word x);
void init_led();
void init_rst_wdt();
void init_lcd();
void put_lcd_line(byte lx,char *ptr);
void put_lcd_open();
void getCDateTime();
/* variables */
boolean tflag ;
boolean uflag ;
boolean xflag ;
boolean aflag ;
char sbuf[16] ;
byte sindex ;
char cmd ;
word year ;
byte month ;
byte day ;
byte hh ;
byte mm ;
byte ss ;
/* system timer counter */
byte xcnt ;
byte ycnt ;
byte zcnt ;
void setup()
{
/* initialize serial port */
Serial.begin(9600); /* Firmware or Debug */
rs_puts("Hello !");
crlf();
show_help();
sindex = 0 ;
/* clear flags */
tflag = OFF ;
uflag = OFF ;
aflag = OFF ;
/* initialize port */
init_led();
init_rst_wdt();
init_lcd();
/* variables */
xcnt = 0 ;
ycnt = 0 ;
zcnt = 0 ;
/* enable RTC */
Wire.begin();
RTC.begin();
if ( !RTC.isrunning() ) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
/* enable LCD */
init_lcd();
/* 25ms period */
MsTimer2::set(XINTERVAL,update_trigger);
/* enable */
MsTimer2::start();
/* WDT power control */
digitalWrite(A3,LOW);
pinMode(A3,OUTPUT);
digitalWrite(A3,HIGH);
}
void loop()
{
/* command interpreter (debug) */
if ( uflag ) {
/* clear flag */
uflag = OFF ;
/* get command */
cmd = *(sbuf+0) ;
/* ? */
if ( cmd == '?' ) { show_help(); }
/* T set date and time */
if ( cmd == 'T' ) {
/* get information from receive buffer */
getCDateTime();
/* get information from receive buffer */
RTC.adjust(DateTime(year,month,day,hh,mm,ss));
}
/* t show date and time */
if ( cmd == 't' ) {
DateTime now = RTC.now();
/* get values */
year = now.year();
month = now.month();
day = now.day();
hh = now.hour();
mm = now.minute();
ss = now.second();
/* */
show_value_word(year); rs_putchar('/');
show_value_byte(month); rs_putchar('/');
show_value_byte(day); rs_putchar(' ');
show_value_byte(hh); rs_putchar(':');
show_value_byte(mm); rs_putchar(':');
show_value_byte(ss); crlf();
}
/* L check LCD */
if ( cmd == 'L' ) {
put_lcd_line(0,"RTC TEST ");
put_lcd_line(1," LCD DISPLAY ");
put_lcd_line(2," MINOR TEST ");
put_lcd_line(3," CAPITAL LETTER");
}
/* l check LCD */
if ( cmd == 'l' ) {
put_lcd_line(0,"rtc test ");
put_lcd_line(1," lcd display ");
put_lcd_line(2," ");
put_lcd_line(3,"******* test *******");
}
/* start auto test */
if ( cmd == 'A' ) { aflag = ON ; }
/* ext auto test */
if ( cmd == 'a' ) { aflag = OFF ; }
/* new line */
crlf();
}
/* timer handling */
if ( tflag ) {
/* clear flag */
tflag = OFF ;
/* flash LEDs */
xflag = bitRead( zcnt , 0 );
digitalWrite( LED_BIT , xflag );
digitalWrite( MON_OUT , xflag );
/* auto test */
if ( aflag == ON && xflag == ON ) {
DateTime cur = RTC.now();
/* */
show_value_word(cur.year()); rs_putchar('/');
show_value_byte(cur.month()); rs_putchar('/');
show_value_byte(cur.day()); rs_putchar(' ');
show_value_byte(cur.hour()); rs_putchar(':');
show_value_byte(cur.minute()); rs_putchar(':');
show_value_byte(cur.second()); crlf();
}
/* increment */
zcnt++ ;
}
}
void update_trigger()
{
if ( xcnt == 39 ) {
xcnt = 0 ;
tflag = ON ;
}
/* increment */
xcnt++ ;
/* WDT handling */
digitalWrite( RST_WDT , LOW );
if ( ycnt & ON ) { digitalWrite( RST_WDT , HIGH ); }
/* increment */
ycnt++ ;
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("T set date and time") ; crlf();
rs_puts("t show date and time") ; crlf();
rs_puts("L test LCD") ; crlf();
rs_puts("l test LCD") ; crlf();
rs_puts("A start auto clock show") ; crlf();
rs_puts("a exit auto clock show") ; crlf();
}
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *ptr)
{
while ( *ptr ) {
rs_putchar( *ptr );
ptr++;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
char get_asc(byte x)
{
char result ;
/* default */
result = '0' ;
/* judge */
if ( x > 9 ) { result = x - 10 + 'A' ; }
else { result = x + '0' ; }
return result;
}
byte get_hex(char x)
{
byte result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result;
}
void show_value_byte(byte x)
{
char msg[4];
byte xtmp ;
/* copy */
xtmp = x ;
/* default */
*(msg+3) = 0 ;
/* separate */
*(msg+2) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+1) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+0) = get_asc( xtmp % 10) ;
/* zero surpress */
if ( *(msg+0) == '0' ) {
*(msg+0) = ' ';
}
/* show */
rs_puts( msg );
}
void show_value_word(word x)
{
char msg[6];
word xtmp ;
/* copy */
xtmp = x ;
/* default */
*(msg+5) = 0 ;
/* separate */
*(msg+4) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+3) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+2) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+1) = get_asc( xtmp % 10) ; xtmp /= 10 ;
*(msg+0) = get_asc( xtmp % 10) ;
/* zero surpress */
if ( *(msg+0) == '0' ) {
*(msg+0) = ' ';
if ( *(msg+1) == '0' ) {
*(msg+1) = ' ';
if ( *(msg+2) == '0' ) {
*(msg+2) = ' ';
if ( *(msg+3) == '0' ) {
*(msg+3) = ' ';
}
}
}
}
/* show */
rs_puts( msg );
}
void init_led()
{
/* set initial value */
digitalWrite( LED_BIT , LOW );
digitalWrite( MON_OUT , LOW );
/* pin direction */
pinMode( LED_BIT , OUTPUT );
pinMode( MON_OUT , OUTPUT );
}
void init_rst_wdt()
{
/* set initial value */
digitalWrite( RST_WDT , LOW );
/* pin direction */
pinMode( RST_WDT , OUTPUT );
}
void init_lcd()
{
byte ii ;
/* pinMode */
for ( ii = ENTRY_LCD ; ii < ENTRY_LCD_EXIT ; ii++ ) {
pinMode(ii,OUTPUT);
}
/* 20 columns x 4 lines */
lcd.begin( 20, 4 );
lcd.clear();
put_lcd_open();
}
void put_lcd_line(byte lx,char *ptr)
{
/* judge */
if ( lx > 3 ) return ;
/* select line */
lcd.setCursor(0,lx);
/* put strings */
lcd.print( ptr );
}
void put_lcd_open()
{
put_lcd_line(0,"Hello , World ! ");
put_lcd_line(1," RTC TEST ");
put_lcd_line(2," OTARU ");
put_lcd_line(3," HOKKAIDO ");
}
void getCDateTime()
{
byte ii ;
byte jj ;
byte xx[12];
byte xtmp ;
/* copy and convert */
for ( ii = 1 ; ii < 13 ; ii++ ) {
jj = ii - 1 ;
*(xx+jj) = get_hex( *(sbuf+ii) );
}
/* deliver */
for ( ii = 0 ; ii < 6 ; ii++ ) {
jj = 2 * ii ;
xtmp = xx[jj] * 10 + xx[jj+1] ;
/* year */
if ( ii == 0 ) { year = xtmp ; }
/* month */
if ( ii == 1 ) { month = xtmp ; }
/* day */
if ( ii == 2 ) { day = xtmp ; }
/* hh */
if ( ii == 3 ) { hh = xtmp ; }
/* mm */
if ( ii == 4 ) { mm = xtmp ; }
/* day */
if ( ii == 5 ) { ss = xtmp ; }
}
}
/* receive interrupt (debug) */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
端末ソフトTeraTermで、年月日時分秒の設定と
読み出しをすると、次のようになりました。
年月日時分秒の設定と読み出しを、1文字の
コマンドで実現できてます。
クラスメソッドの使い方は、正しいと判断できました。
目次
前
次