2011年1月7日 星期五

Arduino 筆記 – Lab15 使用四位數七段顯示器製作計數器

實驗目的

使用四位數七段顯示器製作計數器,數字可以從 0000 計數到 9999。

四位數七段顯示器腳位圖

image

(圖片來源: 聯宇電子)

使用一個位數的七段顯示器的時候,如果是共陽極的,我們將共陽腳位接到電壓源 (Vdd),如果是共陰極的,我們將共陰腳位接到 GND。在使用多位數的七段顯示器時 (兩位數或四位數甚至更多位數),共陽或共陰的腳位是用來控制要顯示哪個位數。

跟電影攝影機的運作原理一樣,基於視覺暫留(Persistence of Vision)的原理,同一個時間只有一個數字是作用中的,因為電子掃瞄速度很快,肉眼便察覺不出來,人們就會以為七段顯示器上的所有數字都是同時顯示的。這個方法稱為多工(Multiplexing)。

要顯示哪個位數,我們直覺的反應,會認為應該直接用 Arduino 的腳位接到共陽或共極來控制,不過這個方法是行不通的,Arduino 的腳位沒辦法驅動共陽或共陰腳位,因為 Arduino 的腳位沒有能力送出(Source)或吸入(Sink)足夠的電流以點亮七段顯示器的所有節段。

解決辦法是使用雙載子接面電晶體(Bipolar Junction Transistor) (共陰極用 NPN 電晶體,共陽極用 PNP 電晶體,N 為 Negative 的縮寫,P 為 Positive 的縮寫),NPN 或 PNP 電晶體的功用有如一個電子開關,負責七段顯示器導通與否的控制,所以想要讓那一個七段顯示器可以顯示數字,只要打開對應的電晶體即可。

image

(圖片來源:Elektronika)

四位數七段顯示器一共有 12 支腳,其腳位圖如下:

image

(圖片來源:http://jade.ee.hit.edu.tw/jadeweb/MCS/Sch/Seg7x4.pdf)

其中,0 ~ 3 分別為個位數、十位數、百位數以及千位數的共陽腳或共陰腳。

材料
  • 麵包板 x 1
  • Arduino 主板 x 1
  • 共陽極四位數七段顯示器 x 1
  • 2N3906 PNP 電晶體 x 4
  • 1k ohm 電阻 x 4
  • 220 ohm 電阻 x 7
  • 單心線 x N
接線

步驟一:接上七段顯示器

  • 根據下表將七段顯示器接到 Arduino,並在每支接腳上串接一顆 220 ohm 電阻

Arduino 與四位數七段顯示器的腳位對應表:

Arduino 腳位 四位數七段示顯示器腳位 (筆劃)
5 11(A)
7 7 (B)
4 4 (C)
11 2 (D)
10 1 (E)
3 10 (F)
6 5 (G)

步驟二:接上 PNP 電晶體

  • 將四顆 PNP 電晶體射極 (Emitter)接到 +5V
  • 將四顆 PNP 電晶體基極(Base)分別接到 Arduino 的 pin 13, pin 12, pin 9, pin 8,並在每支接腳上串接一顆 1k ohm 電阻。這四支腳位依序用來控制個位數、十位數、百位數及千位數的顯示。

步驟三:連接七段顯示器與 PNP 電晶體

  • 將四顆 PNP 電晶體的集極(Collector)分別接到七段顯示器的四支共陽腳
PNP 電晶體 四位數七段示顯示器腳位 (共陽)
個位數 12
十位數 9
百位數 8
千位數 6
電路圖

image

假如使用的是 NPN 電晶體,接線方法可以參考下圖:

image

(圖片來源: MikroeElecktronika)

程式碼

版本一(Four_Digit_7_Segment.pde): 程式比較長,但比較容易懂

版本二(Four_Digit_7_SegmentV2.pde):簡化程式的寫法

範例照片/影片
動動腦
  1. 如果改用共陰極七段顯示器,除了改接線外,程式碼要做什麼調整才行?
  2. 參考「Lab4 使用可變電阻調光」與「Lab8 使用光敏電阻控制 LED 的開關」這兩篇,認識可變電阻與光敏電阻的讀取辦法,然後在四位數七段顯示器上顯示可變電阻或光敏電阻的讀值。
延伸閱讀

24 意見:

JAY 提到...

呵呵 謝謝指正 對 我用的是MSP430FG4619這顆MCU(這樣沒錯了吧^_^)(我這個算是一顆然後腳位都接出來讓你做應用開發的 等於說 我還是得自己在麵包版做些模組來測試程式)(板大的硬體電路資料等等實在太棒了! 真的省去我很多時間去找!萬分感謝) 我發現我沒買單顆的7-segment 我買的是這顆共陰四顆7-segment 所以我在這裡跟妳請教哦~~
這邊想請教 關於腳位定義 假設我 a,b,c,d,e,f,g,H 我接到mcu上的腳位是port 8.7 , 8.6 , 8.5 , 8.4 , 8.3 , 8.2 , 8.1 , 8.0
個位十位百位千位 設 port 7.7 7.6 7.5 7.4

那MSP程式碼部分我該怎麼定義...

JAY 提到...

嗯 我的確還是個學生~~ 補充: 我用的是IAR這套軟體來學習MSP430 編譯的時候會出現 digitalWrite 或是PINMODE這東西undefine 所以 板大的arduino是不是本身就有內建這些指令作用 那我用msp430該怎麼定義它呢~

coopermaa 提到...

編譯時會出現 undefined 是正常的,因為 MSP430 沒有 Arduino API,就是 pinMode, digitalWrite, digitalRead, delay, ... 這些 functions。這不是難事,也許你可以試著自己來寫這些 functions 喔! (這是一個訓練寫單晶片程式的好題目!呵~) MSP430 控制 I/O 腳位主要是 PxDIR, PxOUT, PxIN 這些暫存器,你可以參考 Arduino 的 wiring_digitail.c,然後把它改成 MSP430 的版本就行了。

j_lo2005 提到...
作者已經移除這則留言。
j_lo2005 提到...

您好,
想請教一下,我試著複製程式碼操作,但 pinMode(F, OUTPUT);,會出現 error: 'F' was not declared in this scope。
如果將[F]改成為[H], 則編譯成功,是為什麼呢!

coopermaa 提到...

複製程式碼後,你有改到這段程式碼嗎?

// 定義七段顯示器各節段與 Arduino 的腳位對應關係
#define A 5
#define B 7
#define C 4
#define D 11
#define E 10
#define F 3 // 看一下是不是不小心把 F 改成 H 了
#define G 6

j_lo2005 提到...

謝謝coopermaa,我沒有修改#define.
事實上我的問題是當#define F 3 <--complier會出現錯誤。所以我修改成#define H 3 <--正常(把全部的F->H)。我試過Arduino 1.0 & 1.01都有這樣的問題.
我只是好奇,不曉得是不是系統的關系(os:win7),還是有其它的問題

謝謝您,您的網站教學,讓我獲益良多。

coopermaa 提到...

你可以把完整程式碼貼上來嗎? 我來編譯看看

不客氣

j_lo2005 提到...

您好,
我是complier 您提供的二個範例,二個都出現"F was not declared in this scope"。我完全沒修改,下載後,直接開啟。
os: win7
arduino windows 1.0 & 1.01二個版本。

j_lo2005 提到...

https://docs.google.com/open?id=0B5r_jdatGk_hSUVzdDE0SVY4OEE

coopermaa 提到...

hi j_lo2005,

原來是 Arduino IDE 版本問題,Lab15 當初是在 Arduino-0022 上寫的,沒有遇到問題,我發現你用的是 Arduino 1.0,於是便以 Arduino 1.0 來編譯,結果真的會出錯: "error: 'F' was not declared in this scope".

好像是因為 Arduino core library 內部定義了一個 F 的 Macro,跟範例程式的變數名稱衝到了。所以只要把變數名稱修改一下就可以了。兩個範例我都改好,而且也在 Arduino 1.0 上試過囉。你再試試,應該沒問題了。

謝謝你的回饋

qw 提到...

實際掃描時會有殘影,我猜是電晶體還未完全關斷以致相鄰的七段顯示器會有微弱的殘影.
我的方法是寫一個副程式把七段顯示器關掉,在顯示完一個七段顯示器後呼叫它並持續1mS再顯示下一個七段顯示器 如此一來就不會有殘影了

coopermaa 提到...

hi qw,

感謝你提供的資訊! :)

ben 提到...

不好意思..我看到你的數字部分(0與1),好像全部顛倒了,第二,{//多工掃瞄,輪流點亮個、十、百、以及千位數的七段顯示器},請問這段的程式碼是哪一部部分,好像沒看到

coopermaa 提到...

沒錯啊,因為我用的是 PNP 電晶體,PNP 電晶體是 Low Active,所以才會 0 跟 1 都顛倒。


"//多工掃瞄,輪流點亮個、十、百、以及千位數的七段顯示器" 這段程式碼你看不到啊?咦....

maxwellyeh 提到...

你好我想請問,我用Mega接了三組四個數字的七段顯示器,但不知道為何會造成數字亮度不同的效果,

coopermaa 提到...

你是用共陽極還是共陰極的七段顯示器?

如果是共陰極,因為都是吃 MCU 的電,可能會造成 電力不足導致亮度不同的問題喔

賴東谷 提到...

您好,我想請問一段程式碼 (採用共陽極_PNP電晶體)
void pickDigit(int x) { //Switch off the display
digitalWrite(CA1, HIGH);
digitalWrite(CA2, HIGH);
digitalWrite(CA3, HIGH);
digitalWrite(CA4, HIGH);

switch(x) {
case 1: digitalWrite(CA1, LOW); break; //Switch on the display
case 2: digitalWrite(CA2, LOW); break;
case 3: digitalWrite(CA3, LOW); break;
case 4: digitalWrite(CA4, LOW); break;
}
}
請問若要開啟顯示器位數 (僅測試個位數)。
為什麼要先送1給基極_電晶體關閉,再送0給基極_電晶體打開?

law dick 提到...

學習了,總算解開了我多年的疑屯,謝謝,還有我猜樓上的答案是消除殘影

Lee James 提到...

請問如何確定 四位七段顯示器為共陰即或共陽極..??? 有甚麼辦法可以測試..???

Lee James 提到...
作者已經移除這則留言。
Lee James 提到...

又再自己做了測試 ; 我用電錶的電阻檔 , 黑色負極接接在 0123 任一腳, 再逐一用紅色正極量測 abcdefgh , 指針皆有些為偏動 ; 反之紅色正極接 0123 任一腳 , 再用黑色負極量 abcdefgh , 則指針絲毫不動 ; 這樣已可確定我的 七段顯示器為 NPN 型態..???

奈落この世何れしモノ 提到...
作者已經移除這則留言。
tomas 提到...
作者已經移除這則留言。