Sim's blog

電子工作はじめてみました

Arduinoに移植してみました

2010-09-15 19:05:33 | Netduino
NetduinoでI2Cの続きになります。

前回は秋月のリアルタイムクロックモジュールRTC8564NBを使った液晶時計をNetduinoで作ってみました。

今回は、ほぼ同じ機能をもつ液晶時計をArduinoに移植してみました。



一部違うのは、Netduinoでは、1秒割り込みを使って、1秒毎に時刻を拾いにいって表示していましたが、Arduino版では無条件に100ミリ秒毎に時刻を拾いにいっていることです。Arduinoでもピン割り込みの機能はあるのですが、ちょうどキャラクタLCDのピンとぶつかっていて使うことができませんでした。

RTC8564NBのCLKOUT出力(1秒割り込み)は、ArduinoのD7につないで、読み取ってLED(D13)でモニターできるようにしています。

RTC8564NBをArduinoから使うには、なんでも作っちゃう、かも。さんのRTC8564ライブラリ(記事)を使うのが便利でいいのですが、今回は比較の意味もこめて、全部自分で書いています。

ArduinoでI2Cを使うにはWireというライブラリを使います。仕様からすると、マルチマスタは考えられていないようですが、その分、.Net Microframeworkより使い方が簡単になっています。WireライブラリのマニュアルはArduino 日本語リファレンスにあります。

ソースコードです。
#include <LiquidCrystal.h>
#include <Wire.h>

#define RTC 0x51

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
uint8_t year, month, day, wday, hour, minute, second;
const char *weekday[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

// RTC-8564NB
// 1pin CLKOE  - open
// 2pin CLKOUT - Arduino D7
// 3pin INT    - open
// 4pin Vss    - Arduino GND
// 5pin SDA    - Arduino A4
// 6pin SCL    - Arduino A5
// 7pin NC     - open
// 8pin Vdd    - Arduino 5V <<<

void setup(){
  lcd.begin(16, 2);
  Wire.begin(); // init as master

  sendcmd(0x00, 0x20);  // stop
  sendcmd(0x01, 0x00);  // Control2
  sendcmd(0x0e, 0x00);  // Timer Control
  sendcmd(0x0d, 0x83);  // CLKOUT frequency
  
  sendcmd(0x02, 0x00);  // sec
  sendcmd(0x03, 0x05);  // min
  sendcmd(0x04, 0x23);  // hour
  sendcmd(0x05, 0x05);  // day
  sendcmd(0x06, 0);     // weekday 0:Sun
  sendcmd(0x07, 0x09);  // month
  sendcmd(0x08, 0x10);  // year low

  sendcmd(0x00, 0x00);  // start

  pinMode(13, OUTPUT);
  pinMode(7, INPUT);
}

void loop(){
  digitalWrite(13, digitalRead(7));
  readTime();
  lcd.home();
  hex2(0x20); // year high
  hex2(year);
  lcd.write('/');
  hex2(month);
  lcd.write('/');
  hex2(day);
  lcd.write(' ');
  lcd.print(weekday[wday]);
  
  lcd.setCursor(0, 1);
  hex2(hour);
  lcd.write(':');
  hex2(minute);
  lcd.write(':');
  hex2(second);

  delay(100);
}

void readTime(void)
{
  Wire.beginTransmission(RTC);
  Wire.send(0x02);
  Wire.endTransmission();
  
  Wire.requestFrom(RTC, 7);
  second = Wire.receive() & 0x7f;
  minute = Wire.receive() & 0x7f;
  hour   = Wire.receive() & 0x3f;
  day    = Wire.receive() & 0x3f;
  wday   = Wire.receive() & 0x07;
  month  = Wire.receive() & 0x1f;
  year   = Wire.receive();
}

void sendcmd(uint8_t addr, uint8_t data)
{
  Wire.beginTransmission(RTC);
  Wire.send(addr);
  Wire.send(data);
  Wire.endTransmission();
}

char hexchar[] = "0123456789abcdef";
void hex2(uint8_t x)
{
  lcd.write(hexchar[x >> 4]);
  lcd.write(hexchar[x & 15]);
}

思いつきで、同じものをNetduinoとArduinoの両方に実現してみました。VS2010の補完機能になれてしまうと、全部キータイプしないといけないArduinoが不安になってきます(笑)。このくらいのものだと、何で作ってもそうたいした違いはないですが、やはりデバッグ機能のあるNetduinoが安心して作れると思いました。

最新の画像もっと見る

4 コメント

コメント日が  古い順  |   新しい順
割込み (chobichan)
2010-09-15 21:56:05
確かATmega自体はdigital2、3以外のピンも割込みに設定できるはずだから、SIGNALで割込みハンドラを書けば行けそうな気がする。
返信する
re:割込み (Sim)
2010-09-16 00:37:48
こんにちは、chobichanさん
ArduinoのD2はPD2(INT0)に、D3はPD3(INT1)につながっているので、attachInterrupt()は外部割込み(INT0, INT1)を使っているみたいです。
他に使えそうなのは、PCINT(pin change interrupt)ですが、Arduinoはサポートしてないみたいです。
直接AVRをたたくみたいなコードを書く必要がありそうですね。
返信する
Unknown (chobichan)
2010-09-16 00:48:34
> 直接AVRをたたくみたいなコードを書く必要がありそうですね。

遠慮せずにどんどんやっちゃっていいのではと思います。

スケッチで直接割込みハンドラを書くと「Arduinoらしくない、、、」なんて事を思っちゃいますが、でもこれをライブラリ化してみんなに公開すれば、「さすがArduino!、やっぱりArduino」なんて評価に変わりますからね(笑)。
返信する
re:Unknown (Sim)
2010-09-16 01:16:02
こんにちは、chobichanさん
ええ、思わずひいちゃうところがありますね。そこを隠すのがライブラリというのは、そのとおりだと思います。
思いつきもしなかった時点で、まだまだ修行が足りないです><。
返信する

コメントを投稿