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

  • 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

arrow
arrow

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