這次的目標是做出有小綠人的交通號誌,要完成下列需求:

  • 1) 紅燈、綠燈、黃燈
  • 2) 紅燈、綠燈秒數倒數
  • 3) 小綠人在紅燈的時候會站立不動
  • 4) 小綠人在綠燈時會走動,在綠燈剩下5秒時,會加速走動,並帶有閃爍

 

 需要的零件有:

  • 1) 許多單心線
  • 2) 紅色、綠色、黃色 LED 各一
  • 3) 2位數的7段顯示器
  • 4) 8*8 (或是其他尺寸) 的矩陣LED
  • 5) 220歐姆電阻好幾個
  • 6) 74HC595 shift register 位移暫存器 3個

 

這次動手做的主題有幾個:練習 timer interrupt、與使用多個 74HC595 以減少 arduino 腳位的使用。

因為 arduino 的 digital out 只有 13 個,而上面的零件一共需要 9 (2位數七段顯示器)+ 16 (8*8矩陣LED)+ 3 (紅綠黃LED燈)會不夠用,因此我們需要使用 74HC595 來減少腳位的使用。

74HC595 是一種位移暫存器(shift register)作用是將序列的輸入暫存住,並輸出到 8bit 的腳位上,例如我們需要輸出 10100101b ,只要將這 8 個 bits 以串列的方式餵入 74HC595,在 74HC595 的輸出 pin 腳就會出現 10100101b。因為是序列輸入,所以只需要 1 個資料腳位,再搭配另外 2 根控制腳位,就可以達到用 3 根腳位輸出 8 bits 的功能。方便的是,74HC595 提供第 9 個 bit 的輸出,可以用來串接下一個 74HC595,於是就可以用 3 根腳位控制 16 bits 輸出了,這樣就夠 8*8 矩陣 LED 使用了。

Cooper Maa: 使用 74HC595 和三支腳位控制 8 顆 LED
Cooper Maa: 使用兩顆 74HC595 和三支腳位控制 16 顆 LED

 

我將程式主體分成兩部份:計時器與顯示,整體是設計成「有限狀態機」的架構。這樣一來 loop() 可以專心在顯示的部份,也就是根據目前狀態(紅綠黃)判斷要顯示何者。而計時器的部份則是倒數時間,當時間到 0 時就換到下一個狀態。

投影片1  

有限狀態機的部份是全部交給 timer ISR 完成,這樣就不必干擾 loop() 函式的執行了。Timer interrupt 提供了開發者設定計時器的功能,並註冊一個函式,當設定的計時器到了之後,開發者所註冊的函式就會被呼叫,不管現在執行到哪裡,這個函式稱作 Interrupt Service Routine (ISR)。我將 timer 設定為 1/100 秒,不設定成秒的原因在於小綠人的動作必須拆解,且不能顯示太快(每個動作約0.2秒),不像七段顯示器一樣只要一直切換兩個數字的顯示就可以搞定。此外將計時器部份獨立於 loop() 之外也可以確保時間計算的準確性,因為當 loop() 執行了一大堆指令之後,實在是很難拿捏,sleep要睡多久了。

請參考 timer ISR 的撰寫教學:

Cooper Maa - Timers
Cooper Maa - Timer ISR

小綠人加速的實做方式是當目前是綠燈狀態且剩餘秒數小於 5 的時候,這時候小綠人的動作每個 frame 就要縮小到 0.1 秒,並再加入一個全白的 frame,如此一來便能夠製造出閃爍的效果了。

最後,我們直接來看影片吧!!

  

阿...我知道那個小綠人畫得很糟糕,因為我一時懶得想怎麼畫,就直接去找了當年參加 FPGA 設計比賽的決賽題目的小綠人來抄上去 XDDDD

, , ,

koukaipan 發表在 痞客邦 PIXNET 留言(8) 人氣()


留言列表 (8)

發表留言
  • 小惠
  • 你好,想請教,如果我要連接四個led矩陣,接法都一樣嗎
    我想做大一點的小綠人,但單一的矩陣太小,想連接四個來做,
    但不知怎麼做連接
  • Hi, 你的想法是行得通的,但是 Arduino Uno 的針腳沒那麼夠用,所以一樣的你可能需要串接 74HC595,一顆 74HC595 可以控制 8 個輸出,而一組8*8 LED 需要 16 隻腳,這也是我用兩顆 74HC595 的原因。以你的例子4塊8*8 LED 來看,可能需要8顆 74HC595 串接,原理相同,只是線會很多小心一點規劃接線,應該是不會有問題的。祝你好運!! :))

    koukaipan 於 2013/06/19 14:15 回覆

  • 小惠
  • 好的,我來試試看,謝謝大大。
  • 阿群
  • 你好,我想請教關於ISR與loop之間的關係。
    因為我有點搞不太清楚ISR裏頭的程式會不會被TIMER設定的時間給中斷掉,
    假使TIMER的TCNT設0.1秒中斷一次,
    到ISR時,如果程式執行超過0.1秒是否會重頭再做一遍,
    或是會等ISR裡的程式執行完後,才重新開始算TIMER的0.1秒?
  • 台灣猛男
  • 那請問能透露程式的部分嗎??
  • james
  • no







  • 李天仁
  • 甘我屁事
  • 鍾秉彥
  • noooooooooooooooo
  • Lebron James
  • Tower Of Saviors