MaruduinoでXBeeを使ってみる。主に送信。 [アプリケーション]
※スケッチを書き込む時はXBeeを外すか、接続を全て外してから行ってください。
※2個のXBeeが必要です。また、Maruduinoと対向する側はPCに接続し、X-CTUでモニターします。
XBeeの使用例です。
これはLiquidCrystalライブラリとxbee-arduinoライブラリを使用しています。
http://code.google.com/p/xbee-arduino/
xbee-arduinoライブラリのインストールは適宜サイトを読んで行って下さい。
Xbeeはシリーズ1を使っています。上記ライブラリを使用するためにはX-CTUでMaruduinoに搭載する側のXBeeにAPI2モードを設定しておきます。端末通信速度はデフォルトの9600bpsに設定しています。使用チャンネルやPAN ID、16bitアドレスなどは適宜設定してください。
相手側はAPIモードでも良いのですが、今回はATモードにしてあります。ターミナル画面でSHOW HEXを設定しておくと、数字がインクリメントされるデータが送られてくるのが判ります。
※2個のXBeeが必要です。また、Maruduinoと対向する側はPCに接続し、X-CTUでモニターします。
XBeeの使用例です。
これはLiquidCrystalライブラリとxbee-arduinoライブラリを使用しています。
http://code.google.com/p/xbee-arduino/
xbee-arduinoライブラリのインストールは適宜サイトを読んで行って下さい。
Xbeeはシリーズ1を使っています。上記ライブラリを使用するためにはX-CTUでMaruduinoに搭載する側のXBeeにAPI2モードを設定しておきます。端末通信速度はデフォルトの9600bpsに設定しています。使用チャンネルやPAN ID、16bitアドレスなどは適宜設定してください。
相手側はAPIモードでも良いのですが、今回はATモードにしてあります。ターミナル画面でSHOW HEXを設定しておくと、数字がインクリメントされるデータが送られてくるのが判ります。
/* LiquidCrystal Library - Hello World Demonstrates the use a 16x2 LCD display. The LiquidCrystal library works with all LCD displays that are compatible with the Hitachi HD44780 driver. There are many of them out there, and you can usually tell them by the 16-pin interface. This sketch prints "Hello World!" to the LCD and shows the time. The circuit: * LCD RS pin to digital DI2 * LCD Enable pin to digital Di3 * LCD D4 pin to digital DI4 * LCD D5 pin to digital DI5 * LCD D6 pin to digital DI6 * LCD D7 pin to digital DI7 * LCD R/W pin to ground * 10K resistor: * ends to +5V and ground * wiper to LCD VO pin (pin 3) Library originally added 18 Apr 2008 by David A. Mellis library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net) example added 9 Jul 2009 by Tom Igoe modified 22 Nov 2010 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/LiquidCrystal */ /** * Copyright (c) 2009 Andrew Rapp. All rights reserved. * * This file is part of XBee-Arduino. * * XBee-Arduino is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * XBee-Arduino is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBee-Arduino. If not, see <http://www.gnu.org/licenses/>. */ // include the library code: #include <LiquidCrystal.h> #include <XBee.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #if 0 #define DI13 2 #define DI12 3 #define DI11 4 #define DI10 5 #define DI9 6 #define DI8 7 #define DI7 8 #define DI6 9 #define DI5 10 #define DI4 11 #define DI3 12 #define DI2 13 #define DI1 #define DI0 #else #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #endif // initialize the library with the numbers of the interface pins LiquidCrystal lcd(DI2, DI3, DI4, DI5, DI6, DI7); XBee xbee = XBee(); unsigned long start = millis(); uint8_t payload[] = { 0, 0 }; Tx16Request tx = Tx16Request(0, payload, sizeof(payload)); TxStatusResponse txStatus = TxStatusResponse(); int suc_cnt,flt_cnt,loop_cnt; void setup() { lcd.begin(16, 2); lcd.print("Xbee Test!"); xbee.begin(9600); } void loop() { // start transmitting after a startup delay. Note: this will rollover to 0 eventually so not best way to handle if (millis() - start > 15000) { payload[0] = loop_cnt >> 8 & 0xff; payload[1] = loop_cnt++ & 0xff; xbee.send(tx); } // after sending a tx request, we expect a status response // wait up to 5 seconds for the status response if (xbee.readPacket(5000)) { lcd.setCursor(0, 1); //0123456789012345 lcd.print(" "); // got a response! // should be a znet tx status if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) { xbee.getResponse().getZBTxStatusResponse(txStatus); // get the delivery status, the fifth byte if (txStatus.getStatus() == SUCCESS) { // success. time to celebrate lcd.setCursor(0, 1); lcd.print("OK:"); lcd.print(++suc_cnt);lcd.print(":");lcd.print(flt_cnt); } else { // the remote XBee did not receive our packet. is it powered on? lcd.setCursor(0, 1); lcd.print("NG:"); lcd.print(suc_cnt);lcd.print(":");lcd.print(++flt_cnt); } } } else { // local XBee did not provide a timely TX Status Response -- should not happen lcd.setCursor(0, 1); lcd.print("TRANSMIT ERR"); } delay(200); }
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ (Make:PROJECTS)
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
フリスクサイズ XBeeインタフェースボードの製作、配付 MTM06にて [アプリケーション]
作りました。
通常は下の写真の様な純正のUSBインタフェース基板を使うのですが、まあちょっとでかいですし、ハンドリングも悪いのでフリスクサイズの基板を作成しました。
ただし元々純正基板にあった機能をこのサイズに突っ込むのは難しいので、幾つかの機能は削除しています。ですが、実用上は問題無いでしょう。
削ってしまった機能は、まずRSSI表示がありません。これにあと3個もLEDを追加しても見るかどうか、、、。
DIN、DOUTのモニターLEDは有りますが、点灯時間を延長する回路は搭載していません。
本来USBの電源利用は、PC側から大きな電流使って良いよ!と許可が出るまでスタンバイに入っているのですが、まあ回路を載せられない事も無いのですが、部品増えますし、面倒なのでUSBに接続したらいきなりフルパワーになっています。
ここだけは削れなかった機能としてはDTR、RTS、CTSのサポートとリセットスイッチとBDMコネクターです。
DTRはUSBインタフェースボード上でXBeeをスリープモードにした場合、SLEEP_RQの制御に使いますし、RTS、CTSはファームの更新時には大量の更新データを通信でやり取りしますので、その際に必要です。
リセットスイッチはXBeeのモデムタイプを変更したりファームを更新する際には必ず必要です。それ以外にもCYCLIC SLEEPに設定した場合、コンフィギュレーションを変更しようにもXBeeがSLEEPに入っている場合はREADやWRITEが上手く行かない時が有ります。そんな時はREADやWRITEボタンを押した直後にこのリセットスイッチを押せば当然XBeeは起動からスタートしますので、すんなり通ります。
BDMコネクターはProgrammable XBeeのファームウエアをいじったり、その上で動作するアプリケーションのデバックには必須です。
このUSBインタフェースボードはMTM06にて実費(250円)で配付いたします。MTM06で配付するのは基板とドキュメントのみですが、事前に部品セット込みで予約いただければ、当日部品セットも用意いたしたいと思います。半田ごて等の工具も用意しておきますので、その場で組み立てOKです(笑)。
通常は下の写真の様な純正のUSBインタフェース基板を使うのですが、まあちょっとでかいですし、ハンドリングも悪いのでフリスクサイズの基板を作成しました。
ただし元々純正基板にあった機能をこのサイズに突っ込むのは難しいので、幾つかの機能は削除しています。ですが、実用上は問題無いでしょう。
削ってしまった機能は、まずRSSI表示がありません。これにあと3個もLEDを追加しても見るかどうか、、、。
DIN、DOUTのモニターLEDは有りますが、点灯時間を延長する回路は搭載していません。
本来USBの電源利用は、PC側から大きな電流使って良いよ!と許可が出るまでスタンバイに入っているのですが、まあ回路を載せられない事も無いのですが、部品増えますし、面倒なのでUSBに接続したらいきなりフルパワーになっています。
ここだけは削れなかった機能としてはDTR、RTS、CTSのサポートとリセットスイッチとBDMコネクターです。
DTRはUSBインタフェースボード上でXBeeをスリープモードにした場合、SLEEP_RQの制御に使いますし、RTS、CTSはファームの更新時には大量の更新データを通信でやり取りしますので、その際に必要です。
リセットスイッチはXBeeのモデムタイプを変更したりファームを更新する際には必ず必要です。それ以外にもCYCLIC SLEEPに設定した場合、コンフィギュレーションを変更しようにもXBeeがSLEEPに入っている場合はREADやWRITEが上手く行かない時が有ります。そんな時はREADやWRITEボタンを押した直後にこのリセットスイッチを押せば当然XBeeは起動からスタートしますので、すんなり通ります。
BDMコネクターはProgrammable XBeeのファームウエアをいじったり、その上で動作するアプリケーションのデバックには必須です。
このUSBインタフェースボードはMTM06にて実費(250円)で配付いたします。MTM06で配付するのは基板とドキュメントのみですが、事前に部品セット込みで予約いただければ、当日部品セットも用意いたしたいと思います。半田ごて等の工具も用意しておきますので、その場で組み立てOKです(笑)。
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 濱原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
超音波距離計測モジュール Ultrasonic Distanceの配付をMTM06辺りで行います。 #mtm06 [アプリケーション]
※欲しい方は事前に連絡ください。量産と言っても数に限りがあります。売り切れごめん(笑)です。
※秋月でニセラのT4016A1、R4016A1の扱いが無くなったと思いきや、今度は台湾メーカーでそっくりの品の扱いが始まったようです。
http://akizukidenshi.com/catalog/g/gI-00120/
購入して同様に使えるのか試してみます。
MTM05の時にブレッドボードで組んでArduinoで動かして、それをPrototyping Labのトークセッションにて小林さんに紹介してもらった超音波距離計のモジュール基板です。
バンドパスフィルターの定数を決めるのに随分時間が掛かってしまった気もするけれど、わりと安定して動くようになりましたので、基板も量産してMTM06に持ち込む予定です。
基本的に基板のみの配付を予定しています。価格は実費のみの250円を予定しています。ただ部品セットの要望が大きければ検討いたします。
と言いますか、MTM06の会場で工具を用意しておきますので、その場で作ってみるみたいな事をしたいと思っています。
計測距離は8cm位から3m強測れます。
左右、上下の広がりですが、結構広い範囲を拾ってしまいますねこのセンサーは。なのでスポットで計測したい場合はホーンを付けた方が良さそうです。
データシートは以下のアドレスのT4016A1とR4016A1をご覧ください。
http://www.nicera.co.jp/pro/ut/ut-02.html
動かすマイコンはArduinoに限らずなんでも良いです。但し40KHz位の信号を出せる必要があります。
※秋月でニセラのT4016A1、R4016A1の扱いが無くなったと思いきや、今度は台湾メーカーでそっくりの品の扱いが始まったようです。
http://akizukidenshi.com/catalog/g/gI-00120/
購入して同様に使えるのか試してみます。
MTM05の時にブレッドボードで組んでArduinoで動かして、それをPrototyping Labのトークセッションにて小林さんに紹介してもらった超音波距離計のモジュール基板です。
バンドパスフィルターの定数を決めるのに随分時間が掛かってしまった気もするけれど、わりと安定して動くようになりましたので、基板も量産してMTM06に持ち込む予定です。
基本的に基板のみの配付を予定しています。価格は実費のみの250円を予定しています。ただ部品セットの要望が大きければ検討いたします。
と言いますか、MTM06の会場で工具を用意しておきますので、その場で作ってみるみたいな事をしたいと思っています。
計測距離は8cm位から3m強測れます。
左右、上下の広がりですが、結構広い範囲を拾ってしまいますねこのセンサーは。なのでスポットで計測したい場合はホーンを付けた方が良さそうです。
データシートは以下のアドレスのT4016A1とR4016A1をご覧ください。
http://www.nicera.co.jp/pro/ut/ut-02.html
動かすマイコンはArduinoに限らずなんでも良いです。但し40KHz位の信号を出せる必要があります。
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
Maruduinoで時計を作る。Wireライブラリ対応版 [アプリケーション]
このボードはハムフェア(http://bit.ly/14qQxv)のマルツさんのブースで展示予定です。触ってネー。
もっとも自分でなんとかした訳ではなく、某所から、ロジアナまで持ち出しての動作解析をしてもらった結果です。
ある意味Wireライブラリの使い方の見本としてもどうぞ。
※Wireライブラリの中で割込みを使っている関係上、別の割り込みハンドラの中から呼んだり、割り込み禁止にしている状態では、Wireライブラリを使う事ができない様です。お気を付け。
もっとも自分でなんとかした訳ではなく、某所から、ロジアナまで持ち出しての動作解析をしてもらった結果です。
ある意味Wireライブラリの使い方の見本としてもどうぞ。
※Wireライブラリの中で割込みを使っている関係上、別の割り込みハンドラの中から呼んだり、割り込み禁止にしている状態では、Wireライブラリを使う事ができない様です。お気を付け。
/***********************************************************************/ /* LCD clock */ /* I2C bus control RTC()RTC8564 use */ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/ #include <string.h> #include <LiquidCrystal.h> #include <Wire.h> #include <avr/io.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define SW1 AN3 #define SW2 AN2 #define SW3 AN1 #define SW4 AN0 #define RTC8564_CTRL1 0x00 #define RTC8564_CTRL2 0x01 #define RTC8564_SEC 0x02 #define RTC8564_MIN 0x03 #define RTC8564_HOUR 0x04 #define RTC8564_DAY 0x05 #define RTC8564_WEEK 0x06 #define RTC8564_MONTH 0x07 #define RTC8564_YEAR 0x08 #define RTC8564_MIN_ALM 0x09 #define RTC8564_HOUR_ALM 0x0A #define RTC8564_DAY_ALM 0x0B #define RTC8564_WEEK_ALM 0x0C #define RTC8564_CLK_FREQ 0x0D #define RTC8564_TIM_CTRL 0x0E #define RTC8564_TIMER 0x0F #define RTC_BASE_ADDR (0xa2 >> 1) /*************************************************************************/ /* global parameter */ /*************************************************************************/ enum RTC8564Str {SECONDS,MINUTES,HOURS,DAYS,WEEKDAYS,MONTHS,YEARS}; /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ char date[ 20 ]; /**/ char alarm_set_time[] = "00:00"; unsigned long sectim; unsigned long lasttim; unsigned char switches[3]; boolean clock_disp = false; const char date_limit[][2] = /*offset = 2*/ { {'0','9'}, /*year 10*/ {'0','9'}, /*year 1*/ {'/','/'}, /**/ {'0','1'}, /*month 10*/ {'0','9'}, /*month 1*/ {'/','/'}, /**/ {'0','3'}, /*day 10*/ {'0','9'}, /*day 1*/ }; const char time_limit[][2] = /*offset = 0*/ { {'0','2'}, /*hour 10*/ {'0','9'}, /*hour 1*/ {':',':'}, /**/ {'0','5'}, /*monite 10*/ {'0','9'}, /*monite 1*/ {':',':'}, /**/ {'0','5'}, /*second 10*/ {'0','9'}, /*second 1*/ }; LiquidCrystal lcd(DI8, DI9, DI4, DI5, DI6, DI7); /*************************************************************************/ /* prototype */ /*************************************************************************/ static void date_print( const char *src, int x, int y ); static void time_print( const char *src, int x, int y ); static void ConvertFromRTC2DateTime( void ); int I2C_Write( int addr, unsigned char data ); int I2C_Read( int addr, unsigned char *data ); int InitRTC8564( int force ); unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ); char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ); int I2CRTC8564_Write( unsigned char addr, char data ); int I2CRTC8564_Read( unsigned char addr, char *buff ); int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ); int RTC8564_CalenderSet( const char *date_time ); #define CalenderRead(buf) I2CRTC8564_Blk_Read(RTC8564_SEC, buf, 7) /*************************************************************************/ /* digital2 external int handler */ /*************************************************************************/ static void di2_int_hdr( void ) { sectim++; } /*************************************************************************/ /* time display update */ /*************************************************************************/ static void time_disp_update( void ) { ConvertFromRTC2DateTime(); /*update clock*/ if( clock_disp == true ) { date_print(date,0,0); time_print(date,2,1); } } /*************************************************************************/ /* Switch down detection */ /*************************************************************************/ static unsigned char detect_sw_down( unsigned char *sw ) { unsigned char temp = PINC & 0x0f; sw[0] = sw[1]; sw[1] = sw[2]; sw[2] = temp ^ 0x0f; return sw[0] & sw[1] & temp; } /*************************************************************************/ /* RTC8564 data convert to date time strings. */ /*************************************************************************/ static void ConvertFromRTC2DateTime( void ) { char buf[10]; CalenderRead( buf ); RTC8564Str2DateStr( date, (const unsigned char *)buf ); /**/ } /*************************************************************************/ /* Date lcd print */ /*************************************************************************/ static void date_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, src, 10 ); buf[10] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time lcd print */ /*************************************************************************/ static void time_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, &src[11], 8 ); buf[8] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time adjust */ /*************************************************************************/ static void time_adjust_mode( void ) { int pos = 2; char copy_date[20]; boolean loop = true; memcpy( copy_date, date, sizeof(copy_date) ); lcd.clear(); date_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 10 ) { loop = false; break; } if( pos == 4 || pos == 7 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos] < date_limit[pos - 2][0] ) copy_date[pos] = date_limit[pos - 2][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos] > date_limit[pos - 2][1] ) copy_date[pos] = date_limit[pos - 2][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } pos = 0; loop = true; lcd.clear(); time_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 8 ) { loop = false; break; } if( pos == 2 || pos == 5 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos + 11] < time_limit[pos][0] ) copy_date[pos + 11] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos + 11] > time_limit[pos][1] ) copy_date[pos + 11] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00001000: /*abort*/ return; default: break; } } noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ memcpy( date, copy_date, sizeof(date) ); RTC8564_CalenderSet( date ); /*update calender.*/ EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* Alarm set */ /*************************************************************************/ static void Alarm_set_mode( void ) { int pos = 0; unsigned char temp; boolean loop = true; lcd.clear(); lcd.setCursor(0,0); lcd.print( alarm_set_time ); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 5 ) { loop = false; break; } if( pos == 2 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --alarm_set_time[pos] < time_limit[pos][0] ) alarm_set_time[pos] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00000100: /*up number*/ if( ++alarm_set_time[pos] > time_limit[pos][1] ) alarm_set_time[pos] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } temp = ((alarm_set_time[3] & 0x0f) << 4) + (alarm_set_time[4] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_MIN_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ temp = ((alarm_set_time[0] & 0x0f) << 4) + (alarm_set_time[1] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_HOUR_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* setup */ /*************************************************************************/ void setup() { char buf[16]; unsigned char temp; // static const char date_time[] = "2010/08/07 02:04:00"; lcd.begin(16, 2); lcd.clear(); lcd.println( "designed by hamayan." ); Wire.begin(); /*set i2c master device*/ TWSR &= 0xfc; /*baud rate control. prescaler=x1*/ TWBR = 72; /*baud rate control. 100khz*/ delay( 1000 ); if( InitRTC8564( 0 ) < 0 ) { lcd.clear(); lcd.println( "rtc init error." ); while(1) ; } I2CRTC8564_Read( RTC8564_MIN_ALM, (char *)&temp ); if( !(temp & 0x80) ) { alarm_set_time[3] = ((temp >> 4) & 0x07) + '0'; alarm_set_time[4] = (temp & 0x0f) + '0'; I2CRTC8564_Read( RTC8564_HOUR_ALM, (char *)&temp ); alarm_set_time[0] = ((temp >> 4) & 0x03) + '0'; alarm_set_time[1] = (temp & 0x0f) + '0'; } // RTC8564_CalenderSet( date_time ); /*force setting calender.*/ pinMode( SW1, INPUT ); /*set port at input mode*/ pinMode( SW2, INPUT ); /*set port at input mode*/ pinMode( SW3, INPUT ); /*set port at input mode*/ pinMode( SW4, INPUT ); /*set port at input mode*/ /*enable edge trigger interrupt*/ attachInterrupt(0, di2_int_hdr, FALLING); DDRD &= ~0b00000100; /*direction input*/ PORTD |= 0b00000100; /*enable pullup*/ /*display alarm set time*/ lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; lasttim = millis() + 100; } /*************************************************************************/ /* main loop */ /*************************************************************************/ void loop() { #define ALARM_PERIOD (60 * 5) unsigned char temp; static unsigned long oldsec; static int alarm_time; if( millis() > lasttim ) { lasttim = millis() + 100; /*next sample time update.*/ switch ( detect_sw_down( switches ) ) { case 0b00001010 : /*time adjust mode*/ clock_disp = false; time_adjust_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001100 : /*alarm set mode*/ clock_disp = false; Alarm_set_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001000 : /*stop alarm*/ alarm_time = 0; break; default : break; } } if( oldsec != sectim ) { oldsec = sectim; time_disp_update(); /*clock display update*/ if( date[18] == '0' && date[17] == '0' && alarm_set_time[4] == date[15] && alarm_set_time[3] == date[14] && alarm_set_time[1] == date[12] && alarm_set_time[0] == date[11] ) alarm_time = ALARM_PERIOD; /*? minutes*/ if( --alarm_time > 0 ) { if( alarm_time % 3 ) tone( DI13, 1000, 800 ); } else alarm_time = 0; } } /*************************************************************************/ /* I2C Write function */ /*************************************************************************/ int I2C_Write( int addr, unsigned char data ) { Wire.beginTransmission( addr ); Wire.send( data ); return Wire.endTransmission(); } /*************************************************************************/ /* I2C Read function */ /*************************************************************************/ int I2C_Read( int addr, unsigned char *data ) { Wire.requestFrom( addr, 1 ); while( Wire.available() == 0 ) ; *data = Wire.receive(); return 0; } /*************************************************************************/ /* I2CRTC8564_Write */ /*************************************************************************/ int I2CRTC8564_Write( unsigned char addr, char data ) { Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.send( data ); return Wire.endTransmission(); } /*************************************************************************/ /* I2CRTC8564_Read */ /*************************************************************************/ int I2CRTC8564_Read( unsigned char addr, char *buff ) { Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.endTransmission(); Wire.requestFrom( RTC_BASE_ADDR, 1 ); while( Wire.available() == 0 ) ; *buff = Wire.receive(); return 0; } /*************************************************************************/ /* I2CRTC8564_Blk_Read */ /*************************************************************************/ int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ) { Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.endTransmission(); Wire.requestFrom( RTC_BASE_ADDR, size ); while( Wire.available() < size ) ; for( ; size > 0; size-- ) { *buff++ = Wire.receive(); } return 0; } /*************************************************************************/ /* RTC-8564 initialize */ /*************************************************************************/ int InitRTC8564( int force ) { int i,ret; char temp,date_time[ 7 ],work[ 8 ]; unsigned char rtc_adr; static const unsigned char RTC8564_Init_Code[] = {0x20, 0x11, 0x00,0x10,0x18,0x07,0x04,0x05, 0x10,0x80, 0x80, 0x80, 0x80, 0x00,0x81,63 }; /*ctrl1,ctrl2,sec, min, hour,day, week,month,year,min_a,hour_a,day_a,week_a,freq,cont,timer*/ /*RTC8564 confirmed VLbit*/ if( I2CRTC8564_Read( RTC8564_SEC, &date_time[ SECONDS ] ) != 0 ) return (-1); if( date_time[ SECONDS ] & 0x80 || force ) /*VLbit was 1 then detected low voltage*/ { for( rtc_adr = 0; rtc_adr < sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); /*timer start*/ for( i = 0; i < 100; i++ ) { if( I2CRTC8564_Read( RTC8564_YEAR, &date_time[ YEARS ] ) != 0 ) return (-1); /*RTC is not there.*/ if( date_time[ YEARS ] == RTC8564_Init_Code[ RTC8564_YEAR ] ) /**/ { break; } else { for( rtc_adr = 0; rtc_adr <= sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); } } if( i != 100 ) ret = 1; /**/ else ret = (-2); /*initialize error*/ } else ret = 0; if( ret > (-1) ) { if( I2CRTC8564_Blk_Read( RTC8564_SEC, work, 7 ) != 0 ) return (-1); RTC8564Str2DateStr( date, (const unsigned char *)work ); /**/ } return ret; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /* DateStr2RTC8564Str( (unsigned char *)work, "2007/12/31 23:59:00" ); */ /* I2CRTC8564_Blk_Write( RTC8564_SEC, (const char *)work, 7 ); */ /*************************************************************************/ unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ) { dest[ 0 ] = ((source[ 17 ] & 0x07) << 4) | (source[ 18 ] & 0x0f); /*second*/ dest[ 1 ] = ((source[ 14 ] & 0x07) << 4) | (source[ 15 ] & 0x0f); /*minute*/ dest[ 2 ] = ((source[ 11 ] & 0x03) << 4) | (source[ 12 ] & 0x0f); /*hour*/ dest[ 3 ] = ((source[ 8 ] & 0x03) << 4) | (source[ 9 ] & 0x0f); /*day*/ dest[ 4 ] = 0; /*week*/ dest[ 5 ] = ((source[ 5 ] & 0x01) << 4) | (source[ 6 ] & 0x0f); /*month*/ dest[ 6 ] = ((source[ 2 ] & 0x0f) << 4) | (source[ 3 ] & 0x0f); /*year*/ return dest; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /*************************************************************************/ char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ) { dest[ 0 ] = '2'; dest[ 1 ] = '0'; dest[ 2 ] = (source[YEARS] >> 4) + '0'; dest[ 3 ] = (source[YEARS] & 0x0f) + '0'; dest[ 4 ] = '/'; dest[ 5 ] = ((source[MONTHS] >> 4) & 0x01) + '0'; dest[ 6 ] = (source[MONTHS] & 0x0f) + '0'; dest[ 7 ] = '/'; dest[ 8 ] = ((source[DAYS] >> 4) & 0x03) + '0'; dest[ 9 ] = (source[DAYS] & 0x0f) + '0'; dest[ 10 ] = ' '; dest[ 11 ] = ((source[HOURS] >> 4) & 0x03) + '0'; dest[ 12 ] = (source[HOURS] & 0x0f) + '0'; dest[ 13 ] = ':'; dest[ 14 ] = ((source[MINUTES] >> 4) & 0x07) + '0'; dest[ 15 ] = (source[MINUTES] & 0x0f) + '0'; dest[ 16 ] = ':'; dest[ 17 ] = ((source[SECONDS] >> 4) & 0x07) + '0'; dest[ 18 ] = (source[SECONDS] & 0x0f) + '0'; dest[ 19 ] = '\0'; return dest; } /*************************************************************************/ /* RTC-8564 Calender Set */ /*************************************************************************/ int RTC8564_CalenderSet( const char *date_time ) { int i; unsigned char rtc_adr,work[ 8 ]; DateStr2RTC8564Str( work, date_time ); /*timer stop*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x20 ) != 0 ) return (-1); /*date and time write*/ for( rtc_adr = RTC8564_SEC, i = 0; rtc_adr <= RTC8564_YEAR; rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, work[ i++ ] ) != 0 ) return (-1); } /*timer start*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); return 0; } /***********************************************************************/ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
printfって便利だよね [アプリケーション]
LiquidCrystalのprintライブラリは軽くて良いのですけれど、ちょっと不便なんですよね。
やっぱりprintfの簡単さは捨て難い物がある。特にデバッカーのサポートを受け難いArduinoでは、メッセージの出し方で随分開発効率が変わってくる。
と言う訳でツイッターでprintfの実現方法に触れられていましたので、LCD出力に適用してみました。
簡単なスケッチを下記に記載しておきます。
LCDとの接続はスケッチを参考としてください。と言うか、適宜自分の環境に合わせて変更してください。
※浮動小数点型には対応していないみたいです。
※生成可能な文字列の最大は、以下のスケッチなら127です。
やっぱりprintfの簡単さは捨て難い物がある。特にデバッカーのサポートを受け難いArduinoでは、メッセージの出し方で随分開発効率が変わってくる。
と言う訳でツイッターでprintfの実現方法に触れられていましたので、LCD出力に適用してみました。
簡単なスケッチを下記に記載しておきます。
LCDとの接続はスケッチを参考としてください。と言うか、適宜自分の環境に合わせて変更してください。
※浮動小数点型には対応していないみたいです。
※生成可能な文字列の最大は、以下のスケッチなら127です。
#include <string.h> #include <stdarg.h> #include <LiquidCrystal.h> LiquidCrystal lcd(12, 10, 5, 4, 3, 2); void LCDPrintf( const char *fmt, ... ) { char tmp[128]; va_list args; va_start( args, fmt ); vsnprintf( tmp, sizeof(tmp), fmt, args ); va_end( args ); lcd.print( tmp ); } void setup() { lcd.begin(16, 2); lcd.clear(); LCDPrintf( "designed by hamayan." ); } void loop() { static int i; lcd.setCursor(0,1); LCDPrintf( "count %+04d", i-- ); delay( 100 ); }
MaruduinoでDual Displayを実現する [アプリケーション]
実際のところとっても簡単に表示でき、情報量が2倍~です(笑)。
※タイプミスしているし(笑)
※ああ勿論、もっと沢山のLCDを増設できるんですよ。
方法をご紹介するだけなので、サンプルアプリケーションも手抜きでexampleのHello,Worldを流用します。
まずその前に接続を行う必要があります。
今回使用するLCDは、基本パーツセットのLCDと、Prototyping Labの著者の小林様に譲っていただいたLCDシールド基板を組み立てた、この2つです。
LCDシールド基板の配線は既に基板上で行われていますので、敢えていじる所はありません。
基本パーツセットのLCDはご存知の様にユーザーが好きな接続を選べる様になっています。
以下の様に配線してください。
DI12(CN5)をRS(CN14)
DI10(CN5)をE(CN14)
DI5(CN5)をD4(CN14)
DI4(CN5)をD5(CN14)
DI3(CN5)をD6(CN14)
DI2(CN5)をD7(CN14)
です。つまりHello,Worldの基本的な接続の内、信号線Eへの配線が異なるのみです。
これは、個々のLCDを識別する為の信号線はEのみで済み、それ以外は共通化できるからです。
Eのみ個別の接続にし、新たにLCDインスタンスを生成すれば、LiquidCrystalライブラリで今まで通りに2つのLCDの制御が可能となります。
では具体的に改造したスケッチを以下に記載しておきます。すっごい簡単ですね。この辺がArduinoの良いところです。
※タイプミスしているし(笑)
※ああ勿論、もっと沢山のLCDを増設できるんですよ。
方法をご紹介するだけなので、サンプルアプリケーションも手抜きでexampleのHello,Worldを流用します。
まずその前に接続を行う必要があります。
今回使用するLCDは、基本パーツセットのLCDと、Prototyping Labの著者の小林様に譲っていただいたLCDシールド基板を組み立てた、この2つです。
LCDシールド基板の配線は既に基板上で行われていますので、敢えていじる所はありません。
基本パーツセットのLCDはご存知の様にユーザーが好きな接続を選べる様になっています。
以下の様に配線してください。
DI12(CN5)をRS(CN14)
DI10(CN5)をE(CN14)
DI5(CN5)をD4(CN14)
DI4(CN5)をD5(CN14)
DI3(CN5)をD6(CN14)
DI2(CN5)をD7(CN14)
です。つまりHello,Worldの基本的な接続の内、信号線Eへの配線が異なるのみです。
これは、個々のLCDを識別する為の信号線はEのみで済み、それ以外は共通化できるからです。
Eのみ個別の接続にし、新たにLCDインスタンスを生成すれば、LiquidCrystalライブラリで今まで通りに2つのLCDの制御が可能となります。
では具体的に改造したスケッチを以下に記載しておきます。すっごい簡単ですね。この辺がArduinoの良いところです。
#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2); LiquidCrystal lcd2(12, 10, 5, 4, 3, 2); void setup() { // set up the LCD's number of rows and columns: lcd.begin(16, 2); lcd2.begin(16, 2); // Print a message to the LCD. lcd.print("LCD1 display demo."); lcd2.print("LCD2 display demo."); } void loop() { // set the cursor to column 0, line 1 // (note: line 1 is the second row, since counting begins with 0): lcd.setCursor(0, 1); lcd2.setCursor(0, 1); // print the number of seconds since reset: lcd.print(millis()/1000); lcd2.print(millis()/1000); }
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
武蔵野電波のブレッドボーダーズ―誰でも作れる!遊べる電子工作
- 作者: スタパ齋藤
- 出版社/メーカー: オーム社
- 発売日: 2009/11
- メディア: 単行本
Maruduinoにシールド基板を搭載する。 [組み立て]
Maruduinoもシールド基板を搭載する事ができます。
何故かここの実装について今まで書いていなかったので、今回、書いておきます。
シングルラインのソケットヘッダー(6ピン2個と8ピン2個)を実装しますが、やはり一旦シールド基板側にソケットヘッダーを挿してしまって、その上でMaruduinoと合体させると、ヘッダーを気持ちよく実装できます。
ひっくり返して四隅を半田付け後、問題が無い事を確認したら全部半田付けして完了です。
何故かここの実装について今まで書いていなかったので、今回、書いておきます。
シングルラインのソケットヘッダー(6ピン2個と8ピン2個)を実装しますが、やはり一旦シールド基板側にソケットヘッダーを挿してしまって、その上でMaruduinoと合体させると、ヘッダーを気持ちよく実装できます。
ひっくり返して四隅を半田付け後、問題が無い事を確認したら全部半田付けして完了です。
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
Maruduinoで時計を作る。リアルタイムクロック(RTC MRX-8564)の利用。 [アプリケーション]
組み立て編はこちらです。
http://maruduino.blog.so-net.ne.jp/2010-08-07
組み立てが完了したので、簡単な?スケッチを記述してみました。ご参考になれば幸いです。
Wireライブラリを使って通信してみたのですが、あまり安定しない、読み出しがおかしい?などがあったので、ソフトウエアでI2C通信を実現しています。
Arduinoは勿論マスターモードとしています。
操作方法を書いておきます。
時刻設定モード:
SW1とSW3の同時押しで時刻設定モードに入ります。
LCDの上段には変更する日付または時刻が表示され、下段には変更位置を示すポインターが表示されています。
SW2で数字を増やし、SW3で数字を減らしますが、上限、下限まで達すると循環します。
数字が確定したらSW4で次の項目に移動します。最後の項目である秒の変更が完了してSW4を押すと、その時点で時刻設定が確定します。
※SW1を押すと入力を取りやめ、通常の時刻表示モードに戻ります。
日付や時刻の整合性はあまりチェックしていませんので、注意してください。
アラーム設定モード:
SW1とSW2の同時押しでアラーム設定モードに入ります。
時刻設定モードと同様上段には時刻、下段にはポインターが表示されます。
その他操作も時刻設定モードと同じです。
時刻の整合性はあまりチェックしていませんので、注意してください。
※アラームを鳴らしたくない時は24:00に設定してください。
アラーム鳴動解除:
アラーム鳴動中にSW1を押す事で鳴動を解除できます。
バッテリーバックアップがされているので、電源を落としても時刻の更新やアラーム時刻の保持は行われています。
こうやってプロトタイピングして、もっとコンパクトであったり、電池で駆動できるものを作って日々の生活に役立てるとか良いですよね。
実際、Arduinoではありませんが、別のOne Chipマイコンで作った自作の目覚まし時計に日々起こされていますヨ。
以下にスケッチを記述しておきます。
※関数time_adjust_mode、Alarm_set_modeにアトミックな処理を追加 2010/08/07 18:35
http://maruduino.blog.so-net.ne.jp/2010-08-07
組み立てが完了したので、簡単な?スケッチを記述してみました。ご参考になれば幸いです。
Wireライブラリを使って通信してみたのですが、あまり安定しない、読み出しがおかしい?などがあったので、ソフトウエアでI2C通信を実現しています。
Arduinoは勿論マスターモードとしています。
操作方法を書いておきます。
時刻設定モード:
SW1とSW3の同時押しで時刻設定モードに入ります。
LCDの上段には変更する日付または時刻が表示され、下段には変更位置を示すポインターが表示されています。
SW2で数字を増やし、SW3で数字を減らしますが、上限、下限まで達すると循環します。
数字が確定したらSW4で次の項目に移動します。最後の項目である秒の変更が完了してSW4を押すと、その時点で時刻設定が確定します。
※SW1を押すと入力を取りやめ、通常の時刻表示モードに戻ります。
日付や時刻の整合性はあまりチェックしていませんので、注意してください。
アラーム設定モード:
SW1とSW2の同時押しでアラーム設定モードに入ります。
時刻設定モードと同様上段には時刻、下段にはポインターが表示されます。
その他操作も時刻設定モードと同じです。
時刻の整合性はあまりチェックしていませんので、注意してください。
※アラームを鳴らしたくない時は24:00に設定してください。
アラーム鳴動解除:
アラーム鳴動中にSW1を押す事で鳴動を解除できます。
バッテリーバックアップがされているので、電源を落としても時刻の更新やアラーム時刻の保持は行われています。
こうやってプロトタイピングして、もっとコンパクトであったり、電池で駆動できるものを作って日々の生活に役立てるとか良いですよね。
実際、Arduinoではありませんが、別のOne Chipマイコンで作った自作の目覚まし時計に日々起こされていますヨ。
以下にスケッチを記述しておきます。
※関数time_adjust_mode、Alarm_set_modeにアトミックな処理を追加 2010/08/07 18:35
/***********************************************************************/ /* LCD clock */ /* I2C bus control RTC()RTC8564 use */ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/ #define _SOFT_I2C_ #if defined( _SOFT_I2C_ ) #else #include <Wire.h> #endif #include <string.h> #include <LiquidCrystal.h> #include <avr/io.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define SW1 AN3 #define SW2 AN2 #define SW3 AN1 #define SW4 AN0 #define SCL_BIT 0b00100000 /*PC5=SCL*/ #define SDA_BIT 0b00010000 /*PC4=SDA*/ #define SCL_IS_HIGH PORTC |= SCL_BIT /*about 120ns swittching*/ #define SCL_IS_LOW PORTC &= ~SCL_BIT /*about 120ns swittching*/ #define SDA_IS_HIGH PORTC |= SDA_BIT /*about 120ns swittching*/ #define SDA_IS_LOW PORTC &= ~SDA_BIT /*about 120ns swittching*/ #define SDA_OUTPUT DDRC |= SDA_BIT #define SDA_INPUT DDRC &= ~SDA_BIT #define SCL_OUTPUT DDRC |= SCL_BIT #define ACK 0 /*ACK Bit*/ #define NACK 1 /*NACK Bit*/ #define RTC8564_CTRL1 0x00 #define RTC8564_CTRL2 0x01 #define RTC8564_SEC 0x02 #define RTC8564_MIN 0x03 #define RTC8564_HOUR 0x04 #define RTC8564_DAY 0x05 #define RTC8564_WEEK 0x06 #define RTC8564_MONTH 0x07 #define RTC8564_YEAR 0x08 #define RTC8564_MIN_ALM 0x09 #define RTC8564_HOUR_ALM 0x0A #define RTC8564_DAY_ALM 0x0B #define RTC8564_WEEK_ALM 0x0C #define RTC8564_CLK_FREQ 0x0D #define RTC8564_TIM_CTRL 0x0E #define RTC8564_TIMER 0x0F #if defined( _SOFT_I2C_ ) #define RTC_BASE_ADDR (0xa2) #else #define RTC_BASE_ADDR (0xa2 >> 1) #endif /*************************************************************************/ /* global parameter */ /*************************************************************************/ enum RTC8564Str {SECONDS,MINUTES,HOURS,DAYS,WEEKDAYS,MONTHS,YEARS}; /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ char date[ 20 ]; /**/ char alarm_set_time[] = "00:00"; unsigned long sectim; unsigned long lasttim; unsigned char switches[3]; boolean clock_disp = false; const char date_limit[][2] = /*offset = 2*/ { {'0','9'}, /*year 10*/ {'0','9'}, /*year 1*/ {'/','/'}, /**/ {'0','1'}, /*month 10*/ {'0','9'}, /*month 1*/ {'/','/'}, /**/ {'0','3'}, /*day 10*/ {'0','9'}, /*day 1*/ }; const char time_limit[][2] = /*offset = 0*/ { {'0','2'}, /*hour 10*/ {'0','9'}, /*hour 1*/ {':',':'}, /**/ {'0','5'}, /*monite 10*/ {'0','9'}, /*monite 1*/ {':',':'}, /**/ {'0','5'}, /*second 10*/ {'0','9'}, /*second 1*/ }; LiquidCrystal lcd(DI8, DI9, DI4, DI5, DI6, DI7); /*************************************************************************/ /* prototype */ /*************************************************************************/ static void clk100( void ); static void I2C_Terminate( void ); static void StartCondition( void ); static void StopCondition( void ); static int RcvAck( void ); static void ResAck( int ack ); static void BitWrite( int data ); static int BitRead( void ); static int ByteWrite( int data ); static int ByteRead( int ack ); static void date_print( const char *src, int x, int y ); static void time_print( const char *src, int x, int y ); static void ConvertFromRTC2DateTime( void ); void I2C_Init( void ); int I2C_Block_Write( int addr, const char *data, int size ); int I2C_Block_Read( int addr, char *data, int size ); int I2C_Write( int addr, unsigned char data ); int I2C_Read( int addr, unsigned char *data ); int InitRTC8564( int force ); unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ); char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ); int I2CRTC8564_Write( unsigned char addr, char data ); int I2CRTC8564_Read( unsigned char addr, char *buff ); int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ); int I2CRTC8564_Blk_Write( unsigned char addr, const char *data, int size ); int RTC8564_CalenderSet( const char *date_time ); #define CalenderRead(buf) I2CRTC8564_Blk_Read(RTC8564_SEC, buf, 7) /*************************************************************************/ /* digital2 external int handler */ /*************************************************************************/ static void di2_int_hdr( void ) { sectim++; ConvertFromRTC2DateTime(); /*update clock*/ if( clock_disp == true ) { date_print(date,0,0); time_print(date,2,1); } } /*************************************************************************/ /* Switch down detection */ /*************************************************************************/ static unsigned char detect_sw_down( unsigned char *sw ) { unsigned char temp = PINC & 0x0f; sw[0] = sw[1]; sw[1] = sw[2]; sw[2] = temp ^ 0x0f; return sw[0] & sw[1] & temp; } /*************************************************************************/ /* RTC8564 data convert to date time strings. */ /*************************************************************************/ static void ConvertFromRTC2DateTime( void ) { char buf[10]; CalenderRead( buf ); RTC8564Str2DateStr( date, (const unsigned char *)buf ); /**/ } /*************************************************************************/ /* Date lcd print */ /*************************************************************************/ static void date_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, src, 10 ); buf[10] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time lcd print */ /*************************************************************************/ static void time_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, &src[11], 8 ); buf[8] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time adjust */ /*************************************************************************/ static void time_adjust_mode( void ) { int pos = 2; char copy_date[20]; boolean loop = true; memcpy( copy_date, date, sizeof(copy_date) ); lcd.clear(); date_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 10 ) { loop = false; break; } if( pos == 4 || pos == 7 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos] < date_limit[pos - 2][0] ) copy_date[pos] = date_limit[pos - 2][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos] > date_limit[pos - 2][1] ) copy_date[pos] = date_limit[pos - 2][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } pos = 0; loop = true; lcd.clear(); time_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 8 ) { loop = false; break; } if( pos == 2 || pos == 5 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos + 11] < time_limit[pos][0] ) copy_date[pos + 11] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos + 11] > time_limit[pos][1] ) copy_date[pos + 11] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00001000: /*abort*/ return; default: break; } } noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ memcpy( date, copy_date, sizeof(date) ); RTC8564_CalenderSet( date ); /*update calender.*/ EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* Alarm set */ /*************************************************************************/ static void Alarm_set_mode( void ) { int pos = 0; unsigned char temp; boolean loop = true; lcd.clear(); lcd.setCursor(0,0); lcd.print( alarm_set_time ); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 5 ) { loop = false; break; } if( pos == 2 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --alarm_set_time[pos] < time_limit[pos][0] ) alarm_set_time[pos] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00000100: /*up number*/ if( ++alarm_set_time[pos] > time_limit[pos][1] ) alarm_set_time[pos] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } temp = ((alarm_set_time[3] & 0x0f) << 4) + (alarm_set_time[4] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_MIN_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ temp = ((alarm_set_time[0] & 0x0f) << 4) + (alarm_set_time[1] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_HOUR_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* setup */ /*************************************************************************/ void setup() { char buf[16]; unsigned char temp; // static const char date_time[] = "2010/08/07 02:04:00"; lcd.begin(16, 2); lcd.clear(); lcd.println( "designed by hamayan." ); #if defined( _SOFT_I2C_ ) I2C_Init(); #else /*_SOFT_I2C_*/ Wire.begin(); /*set i2c master device*/ TWSR &= 0xfc; /*baud rate control. prescaler=x1*/ TWBR = 72; /*baud rate control. 100khz*/ #endif /*_SOFT_I2C_*/ delay( 1000 ); if( InitRTC8564( 0 ) < 0 ) { lcd.clear(); lcd.println( "rtc init error." ); while(1) ; } I2CRTC8564_Read( RTC8564_MIN_ALM, (char *)&temp ); if( !(temp & 0x80) ) { alarm_set_time[3] = ((temp >> 4) & 0x07) + '0'; alarm_set_time[4] = (temp & 0x0f) + '0'; I2CRTC8564_Read( RTC8564_HOUR_ALM, (char *)&temp ); alarm_set_time[0] = ((temp >> 4) & 0x03) + '0'; alarm_set_time[1] = (temp & 0x0f) + '0'; } // RTC8564_CalenderSet( date_time ); /*force setting calender.*/ pinMode( SW1, INPUT ); /*set port at input mode*/ pinMode( SW2, INPUT ); /*set port at input mode*/ pinMode( SW3, INPUT ); /*set port at input mode*/ pinMode( SW4, INPUT ); /*set port at input mode*/ /*enable edge trigger interrupt*/ attachInterrupt(0, di2_int_hdr, FALLING); DDRD &= ~0b00000100; /*direction input*/ PORTD |= 0b00000100; /*enable pullup*/ /*display alarm set time*/ lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; lasttim = millis() + 100; } /*************************************************************************/ /* main loop */ /*************************************************************************/ void loop() { #define ALARM_PERIOD (60 * 5) unsigned char temp; static unsigned long oldsec; static int alarm_time; if( millis() > lasttim ) { lasttim = millis() + 100; /*next sample time update.*/ switch ( detect_sw_down( switches ) ) { case 0b00001010 : /*time adjust mode*/ clock_disp = false; time_adjust_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001100 : /*alarm set mode*/ clock_disp = false; Alarm_set_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001000 : /*stop alarm*/ alarm_time = 0; break; default : break; } } if( oldsec != sectim ) { oldsec = sectim; if( date[18] == '0' && date[17] == '0' && alarm_set_time[4] == date[15] && alarm_set_time[3] == date[14] && alarm_set_time[1] == date[12] && alarm_set_time[0] == date[11] ) alarm_time = ALARM_PERIOD; /*? minutes*/ if( --alarm_time > 0 ) { if( alarm_time % 3 ) tone( DI13, 1000, 800 ); } else alarm_time = 0; } } /*************************************************************************/ /* wait functions */ /*************************************************************************/ #define wait1u() delayMicroseconds(1) #define wait5u() delayMicroseconds(5) /*************************************************************************/ /* 100 clocks function */ /*************************************************************************/ static void clk100( void ) { int i; /*i2c lock release*/ for( i = 0; i < 100; i++ ) { SCL_IS_LOW; wait1u(); SCL_IS_HIGH; wait1u(); } } /*************************************************************************/ /* initialize function */ /*************************************************************************/ void I2C_Init( void ) { int i; PORTC |= SDA_BIT | SCL_BIT; DDRC |= SDA_BIT | SCL_BIT; /*pc4=sda,pc5=scl*/ for( i = 0; i < 100; i++ ) { SCL_IS_LOW; wait1u(); SCL_IS_HIGH; wait1u(); } SDA_IS_LOW; StopCondition(); wait5u(); } /*************************************************************************/ /* I2C Terminate function */ /*************************************************************************/ static void I2C_Terminate( void ) { SCL_OUTPUT; SDA_OUTPUT; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_HIGH; } /*************************************************************************/ /* start condition */ /*************************************************************************/ static void StartCondition( void ) { I2C_Terminate(); wait1u(); SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SCL_IS_LOW; } /*************************************************************************/ /* stop condition */ /*************************************************************************/ static void StopCondition( void ) { SCL_OUTPUT; SDA_OUTPUT; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_HIGH; } /*************************************************************************/ /* ACK confirm function */ /*************************************************************************/ static int RcvAck( void ) { int ret; SCL_IS_LOW; /*about 120ns*/ SDA_INPUT; wait1u(); SCL_IS_HIGH; ret = (PINC & SDA_BIT) ? 1 : 0; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_OUTPUT; SCL_IS_LOW; return ret; } /*************************************************************************/ /* ACK responce function */ /*************************************************************************/ static void ResAck( int ack ) { SCL_IS_LOW; /*about 120ns*/ if(ack) SDA_IS_HIGH; else SDA_IS_LOW; wait1u(); SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; SDA_IS_LOW; } /*************************************************************************/ /* Bit Write function */ /*************************************************************************/ static void BitWrite( int data ) { SCL_IS_LOW; /*about 120ns*/ if(data) SDA_IS_HIGH; else SDA_IS_LOW; wait1u(); SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; SDA_IS_LOW; } /*************************************************************************/ /* Bit Read function */ /*************************************************************************/ static int BitRead( void ) { int ret; SCL_IS_LOW; /*about 120ns*/ wait1u(); SCL_IS_HIGH; ret = (PINC & SDA_BIT) ? 1 : 0; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; return ret; } /*************************************************************************/ /* Byte Write function */ /*************************************************************************/ static int ByteWrite( int data ) { BitWrite( data & 0x80 ); BitWrite( data & 0x40 ); BitWrite( data & 0x20 ); BitWrite( data & 0x10 ); BitWrite( data & 0x08 ); BitWrite( data & 0x04 ); BitWrite( data & 0x02 ); BitWrite( data & 0x01 ); // SDA_IS_LOW; return ( RcvAck() == 0 ) ? 0 : (-1); } /*************************************************************************/ /* Byte Read function */ /*************************************************************************/ static int ByteRead( int ack ) { int data = 0; SDA_INPUT; data |= ( BitRead() ) ? 0x80 : 0x00; data |= ( BitRead() ) ? 0x40 : 0x00; data |= ( BitRead() ) ? 0x20 : 0x00; data |= ( BitRead() ) ? 0x10 : 0x00; data |= ( BitRead() ) ? 0x08 : 0x00; data |= ( BitRead() ) ? 0x04 : 0x00; data |= ( BitRead() ) ? 0x02 : 0x00; data |= ( BitRead() ) ? 0x01 : 0x00; SDA_OUTPUT; ResAck( ack ); return data; } /*************************************************************************/ /* I2C Block Write function */ /*************************************************************************/ int I2C_Block_Write( int addr, const char *data, int size ) { StartCondition(); if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); return (-1); } for( ; size > 0; size-- ) { if( ByteWrite( *data++ ) == (-1) ) { I2C_Terminate(); return (-1); } } StopCondition(); return 0; } /*************************************************************************/ /* I2C Block Read function */ /*************************************************************************/ int I2C_Block_Read( int addr, char *data, int size ) { StartCondition(); if( ByteWrite( addr | 0x01 ) == (-1) ) { I2C_Terminate(); return (-1); } for( ; size > 0; size-- ) *data++ = ByteRead( (size == 1) ? 1 : 0 ); StopCondition(); return 0; } /*************************************************************************/ /* I2C Write function */ /*************************************************************************/ int I2C_Write( int addr, unsigned char data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( data ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( addr ); Wire.send( data ); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2C Read function */ /*************************************************************************/ int I2C_Read( int addr, unsigned char *data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( addr | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } *data = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.requestFrom( addr, 1 ); while( Wire.available() == 0 ) ; *data = Wire.receive(); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Write */ /*************************************************************************/ int I2CRTC8564_Write( unsigned char addr, char data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( data ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.send( data ); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Read */ /*************************************************************************/ int I2CRTC8564_Read( unsigned char addr, char *buff ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } SDA_IS_HIGH; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ if( ByteWrite( RTC_BASE_ADDR | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } *buff = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.requestFrom( RTC_BASE_ADDR, 1 ); while( Wire.available() == 0 ) ; *buff = Wire.receive(); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Blk_Read */ /*************************************************************************/ int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ) { #if defined( _SOFT_I2C_ ) char *ptr = buff; char *limit = &buff[ size - 1 ]; StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } SDA_IS_HIGH; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ if( ByteWrite( RTC_BASE_ADDR | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } while( ptr < limit ) { *ptr++ = ByteRead( 0 ); } *ptr = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.requestFrom( RTC_BASE_ADDR, size ); while( Wire.available() < size ) ; for( ; size > 0; size-- ) { *buff++ = Wire.receive(); } return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Blk_Write */ /*************************************************************************/ int I2CRTC8564_Blk_Write( unsigned char addr, const char *data, int size ) { #if defined( _SOFT_I2C_ ) const char *ptr = data; const char *limit = &data[ size ]; StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } while( ptr < limit ) { if( ByteWrite( *ptr++ ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } } StopCondition(); return 0; #endif /*_SOFT_I2C_*/ return 0; } /*************************************************************************/ /* RTC-8564 initialize */ /*************************************************************************/ int InitRTC8564( int force ) { int i,ret; char temp,date_time[ 7 ],work[ 8 ]; unsigned char rtc_adr; static const unsigned char RTC8564_Init_Code[] = {0x20, 0x11, 0x00,0x10,0x18,0x07,0x04,0x05, 0x10,0x80, 0x80, 0x80, 0x80, 0x00,0x81,63 }; /*ctrl1,ctrl2,sec, min, hour,day, week,month,year,min_a,hour_a,day_a,week_a,freq,cont,timer*/ /*RTC8564 confirmed VLbit*/ if( I2CRTC8564_Read( RTC8564_SEC, &date_time[ SECONDS ] ) != 0 ) return (-1); if( date_time[ SECONDS ] & 0x80 || force ) /*VLbit was 1 then detected low voltage*/ { for( rtc_adr = 0; rtc_adr <= sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); /*timer start*/ for( i = 0; i < 100; i++ ) { if( I2CRTC8564_Read( RTC8564_YEAR, &date_time[ YEARS ] ) != 0 ) return (-1); /*RTC is not there.*/ if( date_time[ YEARS ] == RTC8564_Init_Code[ RTC8564_YEAR ] ) /**/ { break; } else { for( rtc_adr = 0; rtc_adr <= sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); } } if( i != 100 ) ret = 1; /**/ else ret = (-2); /*initialize error*/ } else ret = 0; if( ret > (-1) ) { if( I2CRTC8564_Blk_Read( RTC8564_SEC, work, 7 ) != 0 ) return (-1); RTC8564Str2DateStr( date, (const unsigned char *)work ); /**/ } return ret; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /* DateStr2RTC8564Str( (unsigned char *)work, "2007/12/31 23:59:00" ); */ /* I2CRTC8564_Blk_Write( RTC8564_SEC, (const char *)work, 7 ); */ /*************************************************************************/ unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ) { dest[ 0 ] = ((source[ 17 ] & 0x07) << 4) | (source[ 18 ] & 0x0f); /*second*/ dest[ 1 ] = ((source[ 14 ] & 0x07) << 4) | (source[ 15 ] & 0x0f); /*minute*/ dest[ 2 ] = ((source[ 11 ] & 0x03) << 4) | (source[ 12 ] & 0x0f); /*hour*/ dest[ 3 ] = ((source[ 8 ] & 0x03) << 4) | (source[ 9 ] & 0x0f); /*day*/ dest[ 4 ] = 0; /*week*/ dest[ 5 ] = ((source[ 5 ] & 0x01) << 4) | (source[ 6 ] & 0x0f); /*month*/ dest[ 6 ] = ((source[ 2 ] & 0x0f) << 4) | (source[ 3 ] & 0x0f); /*year*/ return dest; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /*************************************************************************/ char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ) { dest[ 0 ] = '2'; dest[ 1 ] = '0'; dest[ 2 ] = (source[YEARS] >> 4) + '0'; dest[ 3 ] = (source[YEARS] & 0x0f) + '0'; dest[ 4 ] = '/'; dest[ 5 ] = ((source[MONTHS] >> 4) & 0x01) + '0'; dest[ 6 ] = (source[MONTHS] & 0x0f) + '0'; dest[ 7 ] = '/'; dest[ 8 ] = ((source[DAYS] >> 4) & 0x03) + '0'; dest[ 9 ] = (source[DAYS] & 0x0f) + '0'; dest[ 10 ] = ' '; dest[ 11 ] = ((source[HOURS] >> 4) & 0x03) + '0'; dest[ 12 ] = (source[HOURS] & 0x0f) + '0'; dest[ 13 ] = ':'; dest[ 14 ] = ((source[MINUTES] >> 4) & 0x07) + '0'; dest[ 15 ] = (source[MINUTES] & 0x0f) + '0'; dest[ 16 ] = ':'; dest[ 17 ] = ((source[SECONDS] >> 4) & 0x07) + '0'; dest[ 18 ] = (source[SECONDS] & 0x0f) + '0'; dest[ 19 ] = '\0'; return dest; } /*************************************************************************/ /* RTC-8564 Calender Set */ /*************************************************************************/ int RTC8564_CalenderSet( const char *date_time ) { int i; unsigned char rtc_adr,work[ 8 ]; DateStr2RTC8564Str( work, date_time ); /*timer stop*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x20 ) != 0 ) return (-1); /*date and time write*/ for( rtc_adr = RTC8564_SEC, i = 0; rtc_adr <= RTC8564_YEAR; rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, work[ i++ ] ) != 0 ) return (-1); } /*timer start*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); return 0; } /***********************************************************************/ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 濱原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
Maruduinoの時計機能(リアルタイムクロック)追加パーツの組み立て [組み立て]
※このリアルタイムクロック部品セットはMaruduinoの拡張機能です。実装位置がブレッドボードの位置と重なっていますので、ブレッドボードを外すか、位置をずらす必要があります。
近日中にマルツ電波さんから時計機能モジュールMRX-8564が発売となりますので、RTC(Real Time Clock)周りの実装について解説します。
まず背の低い部品と言う事で2つのダイオードを実装します。極性方向に注意してください。
左のD7はショットキーバリアダイオード(RB441Q-40)。右のD6は一般的なシリコンダイオード(1N4148)です。
どちらも代替品は沢山有ると思います。但しD6にショットキーバリアダイオードは実装しないでくださいね。バックアップ電池があっという間に無くなってしまいますから。
MRX-8564を実装します。写真ではICソケットを使用していますが、実際のパーツセットにはICソケットは含まれていません。
ArduinoとI2CデバイスであるMRX-8564間の通信では信号線にプルアップ抵抗を必要とします。
プルアップを行う方法は2つありまして、MRX-8564上のジャンパーJ1とJ2の半田を盛ってショートするか、Maruduinoの基板上のR62~R64を実装するかです。
どちらかを使って信号線のプルアップを行います。
なおMRX-8564上のジャンパーJ3をショートすると、割込みに合わせてLEDがチカチカしますが、これはお好みで。
R62~R64のカラーコードですが、2KΩの抵抗は赤黒赤金、4.7KΩの抵抗は黄紫赤金です。
基本パーツセットの中の6ピンソケットヘッダーをCN15に実装します。ちょっとやり難い位置にありますので、注意してください。
半田面にコイン電池ホルダーを実装します。この電池でMRX-8564のバックアップを行い、電源が切れても時刻の更新、アラーム時刻の保持が出来るようになります。
※注意!電池を搭載するのは組み立てが完了してからです。
裏から搭載しますので、表から半田付けを行いますが、写真手前の半田付けが結構半田が乗り難いので、しっかり温めて半田付けを行ってください。もう少しサーマルを大きく取ればよかったですね。
必要な配線を行います。基板上の白い文字を参考にして以下を読んでください。
まずMRX-8564への配線です。
AN5(CN2)とSCL(CN15)
AN4(CN2)とSDA(CN15)
DI2(CN5)とINT(CN15)
これでArduinoからMRX-8564にアクセスできるようになります。
LCDへの配線です。
DI8(CN5)とRS(CN14)
DI9(CN5)とE(CN14)
DI4(CN5)とD4(CN14)
DI5(CN5)とD5(CN14)
DI6(CN5)とD6(CN14)
DI7(CN5)とD7(CN14)
スピーカー出力及びスイッチとの接続です。
DI13(CN5)とAUX1(CN11)
DI17(CN3)とSW1(CN11)
DI16(CN3)とSW2(CN11)
DI15(CN3)とSW3(CN11)
DI14(CN3)とSW4(CN11)
近日中にマルツ電波さんから時計機能モジュールMRX-8564が発売となりますので、RTC(Real Time Clock)周りの実装について解説します。
まず背の低い部品と言う事で2つのダイオードを実装します。極性方向に注意してください。
左のD7はショットキーバリアダイオード(RB441Q-40)。右のD6は一般的なシリコンダイオード(1N4148)です。
どちらも代替品は沢山有ると思います。但しD6にショットキーバリアダイオードは実装しないでくださいね。バックアップ電池があっという間に無くなってしまいますから。
MRX-8564を実装します。写真ではICソケットを使用していますが、実際のパーツセットにはICソケットは含まれていません。
ArduinoとI2CデバイスであるMRX-8564間の通信では信号線にプルアップ抵抗を必要とします。
プルアップを行う方法は2つありまして、MRX-8564上のジャンパーJ1とJ2の半田を盛ってショートするか、Maruduinoの基板上のR62~R64を実装するかです。
どちらかを使って信号線のプルアップを行います。
なおMRX-8564上のジャンパーJ3をショートすると、割込みに合わせてLEDがチカチカしますが、これはお好みで。
R62~R64のカラーコードですが、2KΩの抵抗は赤黒赤金、4.7KΩの抵抗は黄紫赤金です。
基本パーツセットの中の6ピンソケットヘッダーをCN15に実装します。ちょっとやり難い位置にありますので、注意してください。
半田面にコイン電池ホルダーを実装します。この電池でMRX-8564のバックアップを行い、電源が切れても時刻の更新、アラーム時刻の保持が出来るようになります。
※注意!電池を搭載するのは組み立てが完了してからです。
裏から搭載しますので、表から半田付けを行いますが、写真手前の半田付けが結構半田が乗り難いので、しっかり温めて半田付けを行ってください。もう少しサーマルを大きく取ればよかったですね。
必要な配線を行います。基板上の白い文字を参考にして以下を読んでください。
まずMRX-8564への配線です。
AN5(CN2)とSCL(CN15)
AN4(CN2)とSDA(CN15)
DI2(CN5)とINT(CN15)
これでArduinoからMRX-8564にアクセスできるようになります。
LCDへの配線です。
DI8(CN5)とRS(CN14)
DI9(CN5)とE(CN14)
DI4(CN5)とD4(CN14)
DI5(CN5)とD5(CN14)
DI6(CN5)とD6(CN14)
DI7(CN5)とD7(CN14)
スピーカー出力及びスイッチとの接続です。
DI13(CN5)とAUX1(CN11)
DI17(CN3)とSW1(CN11)
DI16(CN3)とSW2(CN11)
DI15(CN3)とSW3(CN11)
DI14(CN3)とSW4(CN11)
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 濱原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
Maruduino(Arduinoベースボード)基本パーツセット実装。おまけ編 [組み立て]
このタクトスイッチです。リセットスイッチとなっています。
MaruduinoをArduino化するキットには付属していたのですが、どうしても基本パーツセットにも欲しいので、マルツさんに付属すようにお願いしておきました。
安心してバンバンリセット掛けてください。
MaruduinoをArduino化するキットには付属していたのですが、どうしても基本パーツセットにも欲しいので、マルツさんに付属すようにお願いしておきました。
安心してバンバンリセット掛けてください。
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 濱原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本