之前的《Android Things創(chuàng)客DIY第三課-Android Things入門配件包開發(fā)案例教程-數(shù)碼管顯示》中,介紹了如何使用Android Things控制1位數(shù)碼管顯示。本文先對之前的1位數(shù)碼管做一個回顧,再介紹4位數(shù)碼管顯示原理和動手實踐過程。
根據(jù)之前的介紹,我們知道,1位數(shù)碼管是通過8個GPIO控制8個顯示段的顯示,達(dá)到顯示不同數(shù)字的目的的。1位的8段數(shù)碼管,相當(dāng)于8個獨立的LED發(fā)光二極管。每個獨立的發(fā)光二極管都有正極(陽)和負(fù)極(陰)兩根引腳。
所謂共陽,就是把這8個發(fā)光二極管的正極(陽)連接在一起,接入到電源正極,通過GPIO分別控制每個發(fā)光管的負(fù)極,達(dá)到控制顯示的目的。
所謂共陰,就是把這8個發(fā)光二極管的負(fù)極(陰)連接在一起,接入到GND上,通過GPIO分別控制每個發(fā)光管的正極,達(dá)到控制現(xiàn)實的目的。
入門配件包中提供的1位數(shù)碼管是“1位共陰”的數(shù)碼管,所以在之前的例子中,我們是將共陰腳接在GND上,將8段的腳分別接在8個GPIO上,控制8個段的GPIO為高電平時該段顯示,為低電平時該段不顯示。
4位數(shù)碼管顯示的物料準(zhǔn)備
1. 樹莓派3B開發(fā)板 或 NXP Pico i.MX7D開發(fā)板
2. 1KΩ電阻8個(入門配件包中藍(lán)色電阻)
3. 4位數(shù)碼管
4. 透明熱縮管
5. 面包板
6. 杜邦線12根(公-母)
如需購買入門配件包,可訪問:淘寶(https://item.taobao.com/item.htm?id=564226570619)?或?微店(https://weidian.com/item.html?itemID=2238998104)
了解4位數(shù)碼管的顯示原理
如前文所述,1位數(shù)碼管的顯示需要8個GPIO,那么控制4位數(shù)碼管,是不是需要4*8=32個GPIO呢?什么樣的開發(fā)板會提供那么多GPIO???
答案當(dāng)然是否定的。我們說過數(shù)碼管每段有正極(陽)和負(fù)極(陰),如前面所述,我們將1位共陰數(shù)碼管的共陰腳接在GND上,那么如果我們將共陰腳接在另一個GPIO上呢?通過這個GPIO,我們就可以控制這一位數(shù)碼管是否顯示。那么對于4位數(shù)碼管,我們就可以通過4個GPIO選擇我們要顯示4位中的哪一位。
通過這種方式,我們只需要4+8個GPIO,就可以控制4位數(shù)碼管的每一位依次顯示了:
1. 設(shè)置第一位數(shù)字要顯示哪些段
2. 通過GPIO控制第一位數(shù)字顯示
3. 持續(xù)一段時間
4. 關(guān)閉第一位數(shù)字的顯示
5. 設(shè)置第二位數(shù)字要顯示哪些段
6. 通過GPIO控制第二位數(shù)字顯示
……如此周而復(fù)始
那么如何實現(xiàn)4位數(shù)字同時顯示呢?其實只要上面依次顯示的刷新速度足夠快,人眼看到的就是同時顯示的效果了。
動手實踐
入門配件包中提供的4位數(shù)碼管是”4位共陽“數(shù)碼管,即控制4位數(shù)字某位是否顯示的引腳接入正極(陽)——也就是高電平時該位顯示;控制數(shù)字中某段是否顯示的引腳接入負(fù)極(陰)——也就是低電平時該段顯示。
可以按上圖的原理,使用面包板進(jìn)行接線,先將4位數(shù)碼管插在面包板上,將數(shù)碼管的各段對應(yīng)的引腳,通過電阻引出,再接到開發(fā)板上。將每位數(shù)字的引腳,通過面包板接到開發(fā)板對應(yīng)的引腳上。連接效果如下圖所示:
接下來,我們就可以通過程序控制數(shù)碼管的顯示了。代碼同樣可以從Github上下載:https://github.com/sysolve/androidthings-digitalDisplay
案例代碼已升級到Android Things?Developer Preview 7版本,注意開發(fā)板系統(tǒng)與代碼版本一致。
代碼中的FourDigitalActivity.java即為控制4位數(shù)碼管顯示的程序,運行前需要將AndroidManifest.xml中FourDigitalActivity的啟動設(shè)置注釋取消,并將MainActivity的啟動設(shè)置注銷掉。
程序分析
首先,我們對控制數(shù)字的各個段的GPIO進(jìn)行定義,即digital[0]~digital[7];對控制數(shù)碼管4位數(shù)字是否顯示的GPIO進(jìn)行定義,即showDigital[0]~showDigital[3]。
初始化時,我們讓所有段、所有數(shù)字都不現(xiàn)實,因為是4位共陽數(shù)碼管,我們將所有段對應(yīng)的GPIO置為高電平,Gpio.DIRECTION_OUT_INITIALLY_HIGH;將各位數(shù)字是否顯示的GPIO設(shè)置低電平,Gpio.DIRECTION_OUT_INITIALLY_LOW。
初始化完成后,我們先依次顯示每位數(shù)字的每個段進(jìn)行一下測試,即代碼中調(diào)用testDigitalSegment()方法。具體代碼不再貼出,邏輯摘要如下:
for-each showDigital[d]? ? ? ? ? ? //循環(huán)每一位數(shù)字
? ? ? showDigital[d].setValue(true);? ?//控制這一位數(shù)字顯示(置高電平)
? ? ? for-each digital[i]? ? ? ? //循環(huán)數(shù)字的每一段
? ? ? ? ? ? ? digital[i].setValue(false);? ? ? ? ? ? //控制這一段顯示(置低電平)
? ? ? ? ? ? ? Thread.sleep(200);? ? ? ? ? ? ? ? ? ? //持續(xù)200ms
? ? ? ? ? ? ? digital[i].setValue(true);? ? ? ? ? ? ? //關(guān)閉這一段顯示(置高電平)
? ? ? showDigital[d].setValue(false);? ? //控制這一位數(shù)字不顯示(置低電平)
這樣,我們就能依次看到各位數(shù)字的各段依次顯示的效果了:https://github.com/sysolve/androidthings-digitalDisplay#testdigitalsegment
每段都顯示完成后,接下來依次顯示數(shù)字。
首先我們要定義0-9這10個數(shù)字對應(yīng)數(shù)碼管各段顯示的真值表,真值表與1位數(shù)碼管顯示的例子相同,即數(shù)字8顯示的真值表為7段都為true,只有最后個點為false。
因為我們用的4為數(shù)碼管是共陽的數(shù)碼管,低電平時對應(yīng)段才顯示,我已在使用真值表中的值時,需要先取反。接下來我們來看testDisplayDigital()方法,邏輯如下:
for i = -1 to 10? ? //依次顯示0-9的數(shù)字,為-1時不現(xiàn)實
? ? ? ? for-each showDigital[d]? ? //遍歷每一位數(shù)字,即依次在各位數(shù)碼管上顯示數(shù)字
? ? ? ? ? ? ? ? ?displayDigital(i);? ? //調(diào)用displayDigital(i)方法,設(shè)置顯示數(shù)字i
? ? ? ? ? ? ? ? ?showDigital[d].setValue(true);? ? //設(shè)置指定位的數(shù)碼管顯示
? ? ? ? ? ? ? ? ?Thread.sleep(500);? ? //持續(xù)500ms
? ? ? ? ? ? ? ? ?showDigital[d].setValue(false);? ? //設(shè)置指定位的數(shù)碼管不顯示
在displayDigital()方法中,我們從真值表中獲得指定數(shù)字d各段是否顯示,并循環(huán)設(shè)置GPIO,注意,設(shè)置GPIO時要先取反。
這樣我們就能看到0~9的數(shù)字,依次在數(shù)碼管的各位上顯示出來:https://github.com/sysolve/androidthings-digitalDisplay#testdisplaydigital
最后,我們來看看如何通過4位數(shù)碼管顯示4位數(shù)字,我們來做個自動累加計數(shù)器,并將計數(shù)器的數(shù)值顯示在數(shù)碼管上。
//自動計數(shù)
autoIncNumber();//將自動計數(shù)的數(shù)值顯示在4位數(shù)碼管上
display4Digitals();
autoIncNumber()每隔1秒調(diào)用一次,即每秒計數(shù)+1,并將計數(shù)器值轉(zhuǎn)換成4位數(shù)字分別存放在digitalForDisplay[]數(shù)組中。
display4Digitals()方法是一個持續(xù)掃描數(shù)碼管的各個數(shù)位,并將計數(shù)器值的對應(yīng)位顯示在對應(yīng)的數(shù)碼管對應(yīng)位上的方法。
while (true)? ? ? //持續(xù)刷新顯示
? ? ? ? ? ? for-each showDigital[d]? ? ? ? ?? //依次在每位數(shù)碼管上顯示 ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ?//先設(shè)置顯示的數(shù)碼管段
? ? ? ? ? ? ? ? ? ? ?displayDigital(digitalForDisplay[d]);? ? ? ? ? ? ? ? ? ? ?//設(shè)置對應(yīng)的數(shù)碼管位開啟顯示
? ? ? ? ? ? ? ? ? ? ?showDigital[d].setValue(true);? ? ? ? ? ? ? ? ? ? ?Thread.sleep(2);? ? ? ? ? ?//掃描時間越短,數(shù)字顯示的閃爍感越弱,如將數(shù)值改大,則會看到各個數(shù)字位依次顯示的效果
? ? ? ? ? ? ? ? ? ? ?//設(shè)置對應(yīng)的數(shù)碼管位關(guān)閉顯示
? ? ? ? ? ? ? ? ? ? ?showDigital[d].setValue(false);
這樣,我們就完成了數(shù)碼管顯示4位數(shù)字:https://github.com/sysolve/androidthings-digitalDisplay#display4digitals
寫在后面
1. 數(shù)碼管可以顯示小數(shù)點,感興趣的朋友,可以嘗試一下用4位數(shù)碼管顯示小數(shù)。
2. 4位數(shù)碼管顯示時,會發(fā)現(xiàn)亮度忽亮忽暗的情況,這是因為Android并非實時系統(tǒng),顯示延時并不精確,而掃描各位數(shù)字顯示時,時間長短直接影響顯示亮度。
3. 占用過多GPIO,樹莓派3B一共有13個GPIO,NXP Pico iMX7D只有12個,而這個4位數(shù)碼管就用掉了12個GPIO!
4. 本案例只是為了講解4位數(shù)碼管的原理,通常在實際使用中,我們會使用專門的控制芯片去控制數(shù)碼管的顯示,由專用芯片實現(xiàn)數(shù)碼管各位的掃描顯示。通常只需要2~3個GPIO進(jìn)行數(shù)據(jù)通訊,主控板將要顯示的內(nèi)容發(fā)送給數(shù)碼管控制芯片即可,具體的掃描顯示過程由專用芯片完成,專用芯片中的實時系統(tǒng)保證顯示的效果更穩(wěn)定。在《Android Things創(chuàng)客DIY第五課-硬件開發(fā)案例教程-PWM調(diào)色-觸摸開關(guān)-數(shù)碼管顯示-OLED顯示》中介紹的帶冒號4位數(shù)碼管,就是通過專用芯片控制數(shù)碼管顯示的。