2011年12月24日 星期六

多台 Arduino 間的通訊 - 透過 I2C #4

在前面幾篇 (#1, #2#3) 中,我們已經學會 Arduino 的 I2C 通訊 - 也就是 Wire Library 的基本用法,知道怎麼讓 Master 送資料給 Slave,而且也知道怎麼讓 Slave 送資料給 Master。

不管是讓 Master 送資料給 Slave,或者是讓 Slave 送資料給 Master,這些基本上都是單向的傳輸。其實當我們在使用 I2C 通訊的時候,實際情況下並不會這麼單純,因為很多 I2C 的電子設備通常都會用到雙向傳輸。

例如底下 DS1307 這個 Real Time Clock 就是一個很好的例子:

image
▲ DS1307 Real Time Clock

DS1307 時鐘用的正是 I2C 介面, 我們既可以用 Arduino 讀取 DS1307 的時間資訊:

而且也可以設定它的時間:

底下我們就來做個簡單的 I2C 雙向傳輸的練習。

接線

一樣,我們用兩台 Arduino 來做實驗,一台是 Master,一台是 Slave,其中 Slave 所用的 address 為 1。為了方便觀察,我們在 Slave 的 pin 13 加上一顆 LED:

image

程式

底下是 Master 的程式:

程式說明:

  • Master 使用 Wire.begin() 加入 I2C bus
  • 在 loop() 函式中,程式每隔一秒鐘就呼叫 requestFromSlave(DIGITAL_WRITE) 要求 Slave 切換 LED 狀態,接著呼叫 requestFromSlave(DIGITAL_READ) 向 Slave 詢問 LED 目前的狀態
  • 在 requestFromSlave() 函式中,首先會送一個 byte 的資料給 slave,假若資料內容是 DIGITAL_READ 程式會跟著發一個 request 給 slave 請 slave 送一個 byte 的資料回來,這個 byte 的內容代表的是 slave 的 LED 狀態。

底下是 Slave 的程式:

程式說明:

  • Slave 一樣是使用 Wire.begin() 加入 I2C bus,但是必須傳入一個參數指定所用的 address
  • 在 receiveEvent() 中,Slave 會讀取 Master 送過來的資料放在 requestRegister 變數裏,假如是 DIGITAL_WRITE,程式會切換 pin 13 上的 LED 狀態
  • 在 requestEvent() 中,Slave 做的事很簡單,只是把目前 LED 的狀態傳給 Master 而已
執行結果

把兩支程式上傳到兩塊 Arduino 板子上,並且打開 Master 的 Serial Monitor。這時候你會看到 Slave 的 LED 每秒鐘會閃爍一次,而且在 Serial Monitor 上每 1 秒鐘會出現一行訊息告訴你目前 Slave 的 LED 狀態是 HIGH 還是 LOW:

image  
▲ Master 的 Serial Monitor

參考資料

4 意見:

Jack 提到...

所以加上這個DS1307, arduino就有現實時間了!!
實用性爆增, 紀錄飛行資訊

Cooper Maa 提到...

沒錯,如果有網路的話,也可以用 NTP 取得網路時間。
歡迎來這,你在用 Arduino 做飛行器嗎?

Unknown 提到...

想請問您一下關於NTP的使用方式,我使用的是ATMEAGA2560那塊板子,以及WIZ5100的網路模組,但是在燒錄ETHERNET裡面的UDPNTP的範例時卻整個沒有反應,我是利用DLINK往外接我的網路模組使用的(因為在實驗室),想請問一下DLINK在運用這個範例時該如何設定內容?還是有其他問題我要考慮的嗎?

Cooper Maa 提到...

Sorry, 我還沒玩過 Ethernet Shield,沒這方面的經驗

NTP 的運作跟 Dlink router/ap 應該是沒有關係的
你的板子 Ping 得到嗎?
也許唯一的方式是用 Serial Port 訊息來 Debug