之前用LED製作呼吸燈與霹靂車燈,以揚聲器演奏青花瓷,這篇要使用seven-segment display七段顯示器製作時鐘。
首先使用Arduino的8個腳位,直接控制七段顯示器,讓七段顯示器從0數到9。然後改用4511控制七段顯示器,就只需要4個腳位即可。然後再加上三個七段顯示器、再加上三顆4511,製作時鐘。
電路圖(Fritzing格式)與程式原始碼,可在此下載。
開始吧,先直接以Arduino的腳位控制,讓七段顯示器亮起來吧。
注意:我使用的是共陰極七段顯示器,之後的4511不能搭配共陽極。
共陰極七段顯示器的腳位圖。
電路圖:
左方是Arduino的腳位,右方是七段顯示器的腳位。連接時,都加上一個220 ohm電阻。
2連到7(A)。
3連到6(B)。
4連到4(C)。
5連到2(D)。
6連到1(E)。
7連到9(F)。
8連到10(G)。
9連到5(DP)。
從Arduino的GND接到麵包版上,讓七段顯示器的3與8接地。
接好後,先寫個小程式測試看看,讓七段顯示器閃爍。
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};
void setup() {
for(int i = 0; i < NUM; i++){
pinMode(pins[i], OUTPUT);
}
}
void loop() {
for(int i = 0; i < NUM; i++){
digitalWrite(pins[i], HIGH);
}
delay(1000);
for(int i = 0; i < NUM; i++){
digitalWrite(pins[i], LOW);
}
delay(1000);
}
其實就跟閃爍單個LED一樣,只不過現在要閃爍8個LED罷了。
接下來,該讓七段顯示器作正事了,也就是顯示數字,底下程式碼要從0數到9。
首先要定義,顯示各數字時,要點亮、熄滅七段顯示器的哪些部分。
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};
// 底下就是顯示某數字時,該點亮熄滅哪些腳位的定義,
// data是個二維陣列,其中10代表有10個數字(從數字0、1、2、到9),
// 然後,每個數字有8個boolean值,
// 依序代表該不該點亮七段顯示器的A、B、C、D、E、F、G、DP。
// 這部份的資料,依序對應上面pins陣例裡的腳位順序,
// 這裡的對應關係,要按照先前的接線予以定義。
// t代表true,要點亮,
// f代表false,不要點亮。
#define t true
#define f false
boolean data[10][NUM] = {
{t, t, t, t, t, t, f, f}, // 0
{f, t, t, f, f, f, f, f}, // 1
{t, t, f, t, t, f, t, f}, // 2
{t, t, t, t, f, f, t, f}, // 3
{f, t, t, f, f, t, t, f}, // 4
{t, f, t, t, f, t, t, f}, // 5
{t, f, t, t, t, t, t, f}, // 6
{t, t, t, f, f, f, f, f}, // 7
{t, t, t, t, t, t, t, f}, // 8
{t, t, t, t, f, t, t, f}, // 9
};
void setup(){
for(int i = 0; i < NUM; i++){
pinMode(pins[i], OUTPUT);
}
}
// 把七段顯示器的顯示函式獨立出來。
// 輸入數字n(從0到9)
// 根據數字n,就可從data[n]找出七段顯示器的點亮、熄滅資料,
// 然後用迴圈,逐一設定8個腳位的HIGH或LOW,
// 也就等於點亮、熄滅那8個部分
void writeNumber(int n){
for(int i = 0; i < NUM; i++){
digitalWrite(pins[i], data[n][i] == t ? HIGH : LOW);
}
}
// 寫好writeNumber()後,loop()就簡單了。
// 迴圈從0到9,以七段顯示器顯示該數字,中間延遲1秒。
// 也就是說,會從0數到9,然後再從頭從0開始數。
void loop(){
for(int n = 0; n <= 9; n++){
writeNumber(n);
delay(1000);
}
}
以4511控制:
上頭直接以Arduino板的8個腳位控制七段顯示器,底下改以4511控制,以4個腳位。(若以74HC595,就能以3個腳位控制8個輸出。之前的霹靂車燈以2顆74HC595控制16個LED。)
注意,4511必須跟共陰極的七段顯示器搭配。
4511的腳位說明:
7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,從0(0x0000)到9(0x1001),若超過9,那麼7個輸出全部會是LOW,也就是都不亮。
3(lamp test),若為LOW,那麼輸出腳位全部為HIGH,不管輸入腳位的狀態。
4(ripple blanking),當lamp test為HIGH時,若此腳位為LOW,那麼輸出腳位全部為LOW,不管輸入腳位的狀態。
5(enable/store input),若為LOW,輸出腳位隨著輸入腳位而改變,若為HIGH,輸出腳位的狀態會被鎖住不變。
13(a)、12(b)、11(c)、10(d)、9(e)、15(f)、14(g),7個輸出腳位,控制七段顯示器。
8(VSS),接地。
16(VDD),可接+3~15V。
利用4511的ABCD四個腳位輸入,控制七段顯示器的abcdefg。
電路圖:
從Arduino板接5V與GND到麵包板。
4511的腳位接線:
16(VDD)接5V。
8(VSS)接地。
3(lamp test)接5V,本例不使用此功能。
4(ripple blanking)接5V,本例不使用此功能。
5(enable/store input)接地,本例不使用此功能。
13(a)、12(b)、11(c)、10(d)、9(e)、15(f)、14(g),7個輸出腳位,接到七段顯示器相對應的腳位。
7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,接到Arduino板的腳位2、3、4、5。
七段顯示器的腳位5(DP)接地,本例不使用小數點。(其實之前從0數到9時,也不需要使用小數點。)
共陰極七段顯示器的腳位3與8要接地。
下圖先連接4511與七段顯示器之間的接線。
然後是4511的7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,依序接到Arduino板的腳位2、3、4、5。。
接下來就是程式碼了,從0數到9。
// 以Arduino板的4個腳位2、3、4、5控制,
// 控制4511的輸入腳位7(A)、1(B)、2(C)、6(D)。
int pins[4] = {2, 3, 4, 5};
void setup(){
for(int i = 0; i < 4; i++){
pinMode(pins[i], OUTPUT);
}
}
// 以迴圈依序設定4個腳位。
// 參數n,其第0個bit,要輸出到4511的腳位7(input A),
// 它接到Arduino板的腳位2,也就是pins[0]。
// 而取得n的第i個bit的方式是,
// 先以>>運算子把n向右位移i個bit,然後與0x01進行作&運算。
// 其餘bit同理。
// 寫好writeDigit()後,loop()就簡單了。
// 以迴圈依序顯示0到9,中間延遲1秒。
void loop(){
for(int n = 0; n <= 9; n++){
writeDigit(n);
delay(1000);
}
}
從0數到9的影片在此。
時鐘:
接下來,要製作時鐘,可以顯示幾點、幾分,總共需要4個七段顯示器,以及4個4511。
電路圖:
延續前面的電路,加上3個4511,把短的線接一接。
16(VDD)接5V。
8(VSS)接地。
3(lamp test)接5V,本例不使用此功能。
4(ripple blanking)接5V,本例不使用此功能。
5(enable/store input)接地,本例不使用此功能。
從右到左的4511,分別將要控制時鐘的分鐘個位數、分鐘十位數、小時個位數、小時十位數。
注意,小時十位數(最左邊)的4511,其腳位12(b)接電阻後接地,這是因為,小時十位數的七段顯示器,只會出現0、1、2這三個數字,你可以往前看看ABCD與abcdefg的對應表,若七段顯示器只需顯示0、1、2時,其b腳位只能為HIGH,所以這裡就把4511的12(b)腳位接地不用。
然後加上3個七段顯示器,把短的線以及電阻接一接。(我220 ohm電阻不夠了,有些改成別的差不多的。)
七段顯示器的腳位5(DP)接地,本例不使用小數點。
共陰極七段顯示器的腳位3與8要接地。
注意,小時十位數(最左邊)的七段顯示器,其腳位6(b)接地,理由之前說過了。
然後,4511與七段顯示器之間的連接線。
4511的13(a)、12(b)、11(c)、10(d)、9(e)、15(f)、14(g),7個輸出腳位,接到七段顯示器相對應的腳位。小心慢慢接。
然後,4511與Arduino板的連接線。
分鐘個位數的4511,7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,依序接到Arduino板的腳位2、3、4、5。(這個之前應該就接好了。)
分鐘十位數的4511,7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,依序接到Arduino板的腳位6、7、8、9。
小時個位數的4511,7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,依序接到Arduino板的腳位10、11、12、13。
小時十位數的4511,7(input A)、1(input B)、2(input C)、6(input D),4個輸入腳位,依序接到Arduino板的腳位A0、A1、接地、接地。
注意,小時十位數的4511的2(input C)、6(input D),接地。這是因為,小時十位數的七段顯示器,只會出現0、1、2這三個數字,你可以往前看看ABCD與abcdefg的對應表,若4511只需輸入0、1、2時,其C、D輸入腳位一定是LOW,所以這裡此兩腳位接地不用。
接下來,先寫個測試程式,測試看看Arduino是否正確控制4511的輸入腳位,測試七段顯示器是否能正常顯示每個數字。
// 定義腳位
const int minute_0[4] = {2, 3, 4, 5}; // 分鐘個位數
const int minute_1[4] = {6, 7, 8, 9}; // 分鐘十位數
const int hour_0[4] = {10, 11, 12, 13}; // 小時個位數
const int hour_1[2] = {A0, A1}; // 小時十位數
// 將數字n,輸出到腳位pins,bit_count是腳位的數量
void writeDigit(const int n, const int *pins, const int bit_count){
for(int i = 0; i < bit_count; i++){
digitalWrite(pins[i], (n >> i) & 0x01);
}
}
// 在setup()裡初始化,讓四個七段顯示器都顯示數字0。
void setup(){
for(int i = 0; i < 4; i++){
pinMode(minute_0[i], OUTPUT);
pinMode(minute_1[i], OUTPUT);
pinMode(hour_0[i], OUTPUT);
}
pinMode(hour_1[0], OUTPUT);
pinMode(hour_1[1], OUTPUT);
writeDigit(0, minute_0, 4);
writeDigit(0, minute_1, 4);
writeDigit(0, hour_0, 4);
writeDigit(0, hour_1, 2);
}
// 從0數到9,其中小時十位數只能顯示0、1、2。
void loop(){
for(int i = 0; i <= 9; i++){
writeDigit(i, minute_0, 4);
writeDigit(i, minute_1, 4);
writeDigit(i, hour_0, 4);
writeDigit(i % 3, hour_1, 2);
delay(1000);
}
}
成功的話,右邊三個七段顯示器就會從0數到9,最左邊的會顯示0、1、2。
接下來,要製作時鐘,從0000、0001、一直到2359,然後回到0000。
程式碼:
const int minute_0[4] = {2, 3, 4, 5};
const int minute_1[4] = {6, 7, 8, 9};
const int hour_0[4] = {10, 11, 12, 13};
const int hour_1[2] = {A0, A1};
void writeDigit(const int n, const int *pins, const int bit_count);
void setTime(unsigned long h, unsigned long m, unsigned long s);
void setup(){
Serial.begin(115200);
for(int i = 0; i < 4; i++){
pinMode(minute_0[i], OUTPUT);
pinMode(minute_1[i], OUTPUT);
pinMode(hour_0[i], OUTPUT);
}
pinMode(hour_1[0], OUTPUT);
pinMode(hour_1[1], OUTPUT);
setTime(7, 32, 0); // 在程式裡寫死某時間,7時32分0秒
// 之後我們會從外界設定時間
}
void writeDigit(const int n, const int *pins, const int bit_count){
for(int i = 0; i < bit_count; i++){
digitalWrite(pins[i], (n >> i) & 0x01);
}
}
// 代表一天的millisecond,在數字後加上UL,代表是unsigned long
// 若不加上UL,會發生溢位overflow
// 24*60*60 = 86400,大於int或unsigned int(2 bytes)的範圍,
// 若不加上UL,24*60*60,正確應該是0b10101000110000000,
// 溢位後,變成0b0101000110000000,也就是20864。
#define MILLISECOND_OF_ONE_DAY (24UL * 60UL * 60UL * 1000UL)
// 這會是目前顯示在七段顯示器上的時間,單位為millisecond
unsigned long currentTime;
// 用來記住上次更新currentTime時,是在何時
unsigned long previousTimeMark;
// 設定顯示時間的函式,h小時、m分鐘、s秒
void setTime(unsigned long h, unsigned long m, unsigned long s){
currentTime = ((h * 60 + m) * 60 + s) * 1000;
previousTimeMark = millis();
updateTime(0);
}
// 負責更新顯示時間的函式,
// 參數timePassed代表,距離上次更新,經過了多少millisecond
void updateTime(const unsigned long timePassed){
unsigned long h;
unsigned long m;
unsigned long s;
// 加上經過的時間後,若大於一天,就減去。
currentTime += timePassed;
if(currentTime >= MILLISECOND_OF_ONE_DAY){
currentTime -= MILLISECOND_OF_ONE_DAY;
}
// currentTime記錄的是millisecond,
// 底下算出小時、分鐘、秒
s = currentTime / 1000;
m = s / 60;
s = s % 60;
h = m / 60;
m = m % 60;
// 顯示小時跟分鐘
writeDigit(m % 10, minute_0, 4);
writeDigit(m / 10, minute_1, 4);
writeDigit(h % 10, hour_0, 4);
writeDigit(h / 10, hour_1, 2);
}
void loop(){
// millis()會回傳,這支程式開始執行後,所經過的時間,單位是millisecond。
unsigned long now = millis();
// 減去previousTimeMark上次更新顯示時間的時間,
// 若大於1秒,就呼叫updateTime()更新,
// 傳入距離上次更新所經過的時間
if(now - previousTimeMark > 1000){
updateTime(now - previousTimeMark);
previousTimeMark = now;
}
}
成功後,就可以看到下圖了。
不過,上面的程式碼,在程式碼寫死起始時間,這可不行啊,底下修改後,透過序列埠,從外界(電腦)進行時間設定。
在setup()裡要記得加入Serial.begin(115200);。
int b[4];
int len = 0;
void loop(){
unsigned long now = millis();
if(now - previousTimeMark > 1000){
updateTime(now - previousTimeMark);
previousTimeMark = now;
}
int btemp = Serial.read();
if(btemp != -1){
if(0x30 <= btemp && btemp <= 0x39){
b[len] = btemp - 0x30;
len++;
if(len == 4){
setTime(b[0] * 10 + b[1], b[2] * 10 + b[3], 0);
len = 0;
}
}
else{
len = 0;
}
}
}
利用Arduino軟體開發環境的Tools-Serial Monitor,可以透過序列埠、傳送資料給Arduino板子,以腳位0(RX)接收。
呼叫Serial.read()讀取1個byte,放在btemp裡,若無資料,則btemp為-1,若有資料(傳來的會是ASCII碼、0x30是數字0、0x39是數字9),放進b陣列裡存起來,以len記錄收到了多少個byte。收到4個數字後,把前面兩個數字當做小時、後面兩個數字當做分鐘,進行時間設定。
若收到數字以外的資料,重置len為0,表示之前若有收到資料,通通捨棄。
輸入2302,代表要把時間設定為23時02分。
完成囉。
改進的地方,也可以加入設定時間的開關或按鈕,譬如說,某個按鈕按一下會增加一分鐘,另一個按鈕按一下會增加一小時,之類的。
改進的地方,右邊數來第二顆4511,跟Arduino板之間的接線,其實3條即可(因為它只需顯示0到5)。
改進的地方,這個時鐘只顯示小時與分鐘,沒有秒,可加入兩顆LED,每一秒閃爍一下。好像有那種一組裡有四個七段顯示器,並且中間有兩顆LED的,但我沒找到,而且那種一組四個七段顯示器的產品,要用掃描的方式驅動。
參考資料:
- Arduino官方範例Examples > Communication > ASCII Table,Examples > Control Structures > Switch (case) Statement, used with serial input。
- 4511,Doctronics的4511B BCD to 7-segment decoder driver。
- Cooper Maa的Lab7 使用七段顯示器製作倒數功能、Lab13 使用 74HC595 與七段顯示器製作倒數功能、Lab15 使用四位數七段顯示器製作計數器。
請問一下,我程式碼修改過了,但是沒辦法外界修改時間!!請問要怎麼去修改
ReplyDelete請再詳述問題。
Delete我是有照大大的程式碼去做:
ReplyDeleteconst int minute_0[4] = {2, 3, 4, 5};
const int minute_1[4] = {6, 7, 8, 9};
const int hour_0[4] = {10, 11, 12, 13};
const int hour_1[2] = {A0, A1};
void writeDigit(const int n, const int *pins, const int bit_count);
void setTime(unsigned long h, unsigned long m, unsigned long s);
void setup(){
Serial.begin(115200);
int b[4];
int len = 0;
for(int i = 0; i < 4; i++){
pinMode(minute_0[i], OUTPUT);
pinMode(minute_1[i], OUTPUT);
pinMode(hour_0[i], OUTPUT);
}
pinMode(hour_1[0], OUTPUT);
pinMode(hour_1[1], OUTPUT);
setTime(8, 35, 0); // 在程式裡寫死某時間,7時32分0秒
// 之後我們會從外界設定時間
int btemp = Serial.read();
if(btemp != -1){
if(0x30 <= btemp && btemp <= 0x39){
b[len] = btemp - 0x30;
len++;
if(len == 4){
setTime(b[0] * 10 + b[1], b[2] * 10 + b[3], 0);
len = 0;
}
}
else{
len = 0;
}
}
}
void writeDigit(const int n, const int *pins, const int bit_count){
for(int i = 0; i < bit_count; i++){
digitalWrite(pins[i], (n >> i) & 0x01);
}
}
// 代表一天的millisecond,在數字後加上UL,代表是unsigned long
// 若不加上UL,會發生溢位overflow
// 24*60*60 = 86400,大於int或unsigned int(2 bytes)的範圍,
// 若不加上UL,24*60*60,正確應該是0b10101000110000000,
// 溢位後,變成0b0101000110000000,也就是20864。
#define MILLISECOND_OF_ONE_DAY (24UL * 60UL * 60UL * 1000UL)
// 這會是目前顯示在七段顯示器上的時間,單位為millisecond
unsigned long currentTime;
// 用來記住上次更新currentTime時,是在何時
unsigned long previousTimeMark;
// 設定顯示時間的函式,h小時、m分鐘、s秒
void setTime(unsigned long h, unsigned long m, unsigned long s){
currentTime = ((h * 60 + m) * 60 + s) * 1000;
previousTimeMark = millis();
updateTime(0);
}
// 負責更新顯示時間的函式,
// 參數timePassed代表,距離上次更新,經過了多少millisecond
void updateTime(const unsigned long timePassed){
unsigned long h;
unsigned long m;
unsigned long s;
// 加上經過的時間後,若大於一天,就減去。
currentTime += timePassed;
if(currentTime >= MILLISECOND_OF_ONE_DAY){
currentTime -= MILLISECOND_OF_ONE_DAY;
}
// currentTime記錄的是millisecond,
// 底下算出小時、分鐘、秒
s = currentTime / 1000;
m = s / 60;
s = s % 60;
h = m / 60;
m = m % 60;
// 顯示小時跟分鐘
writeDigit(m % 10, minute_0, 4);
writeDigit(m / 10, minute_1, 4);
writeDigit(h % 10, hour_0, 4);
writeDigit(h / 10, hour_1, 2);
}
void loop(){
// millis()會回傳,這支程式開始執行後,所經過的時間,單位是millisecond。
unsigned long now = millis();
// 減去previousTimeMark上次更新顯示時間的時間,
// 若大於1秒,就呼叫updateTime()更新,
// 傳入距離上次更新所經過的時間
if(now - previousTimeMark > 1000){
updateTime(now - previousTimeMark);
previousTimeMark = now;
}
}
這是我看您的去修改,發現板子還是的數字是固定的,沒辦法用COM改想要的數字,只能用裡面的程式碼固定
嗯,沒改對吧, Serial.read()的部份應放在loop()裡。
Delete完整的程式碼,請到
https://github.com/yehnan/arduino_practices/tree/master/Clock
下載。
請問要把無災害天數告示牌的日期顯示變成7段顯示器,和每天加一天的數字功能要買那些材料
Delete大大,我試過了,發現還是一樣沒辦法去改...可以交一下怎麼修改嗎??
ReplyDelete> 可以交一下怎麼修改嗎??
Delete這篇文章的內容,就是使用四個七段顯示器製作時鐘,並透過序列埠設定時間。
若碰到問題,請說明。
請問一下我是剛進來的的新手 怎麼使用按鈕控制 7段顯示上數 之後在伺服馬達震盪反覆啊
ReplyDelete我只打出7段顯示上數 之後就不知道怎麼用按鈕和馬達
> 7段顯示上數
Delete什麼意思?
已經學會按鈕和馬達了嗎?若尚未,請參閱其他文章,
http://yehnan.blogspot.tw/2012/02/arduino_21.html
譬如:
Arduino練習:以開關切換LED明滅狀態
Arduino練習:seven-segment display七段顯示器與時鐘
Arduino練習:Simon Says請你跟我這樣做
Arduino練習:伺服馬達以Tower Pro SG90為例
也可參閱拙作《Arduino輕鬆入門:範例分析與實作設計》,
http://yehnan.blogspot.tw/2014/02/arduino_21.html
學會操控各個零件之後,接著就是程式的部份。
哪個產品呢?
ReplyDelete嗯,電壓電流都大,不是該由Arduino板子提供的程度。
ReplyDelete要另外準備電源,還有驅動器,例如電晶體、達靈頓、或七段顯示器的解碼器,
Arduino與七段顯示器之間插入驅動器,而驅動器要由外部電源提供電力,
最後記得共同接地。
葉老師請問您,我現在要驅動+9V才會亮的共陽七段(編號:BA-S2320SBAW),
ReplyDelete我使用ULN2003+74LS47來接七段,
請問這時候ARDUINO的腳位(2,3,4,5)是接ULN2003的1B~4B嗎?
然後ULN2003的1C~4C是接74LS47的ABCD嗎?
然後外部供電的+9V及GND該接哪些呢?
有點頭大,還請老師指導,謝謝您。
抱歉葉老師,外部電源接線的方式,大概清楚了。
ReplyDelete不過出現了一堆奇怪形狀的七段。
我猜大概是共陽七段跟你的範例不同的關係吧?
您的這段程式碼,我真的看不懂,
for(int i = 0; i < 4; i++){
digitalWrite(pins[i], (n >> i) & 0x01);
右移&oxo1,實在太深奧了。
請問改共陽,要如何修改呢?
線路大概是:
ReplyDeletearduino四個腳位接到74LS47的ABCD,
74LS47的a~g,接到ULN2003的1B~7B,
ULN2003的1C~7C,接到七段顯示器的a~-g,
七段顯示器的共陽極,接到9V~12V。
這個範例只有一個七段顯示器,
ReplyDeletewriteDigit負責控制那個七段顯示器,參數是int n,代表數字0~9。
我用4511,以4個腳位控制七段顯示器的8個腳位(加小數點),
int n是16位元,
如果傳入9的話,n會是0000 1001,
如果傳入6的話,n會是0000 0110,
所以只需要取出其中4個位元,
所以for迴圈的i從0到3,
假定n是9,
起初i是0,n向右移0個位置,然後與0x01作bitwise AND,取出來是1,設給腳位,
然後i是1,n向右移1個位置,然後與0x01作bitwise AND,取出來是0,設給腳位,
然後i是2,n向右移2個位置,然後與0x01作bitwise AND,取出來是0,設給腳位,
最後i是3,n向右移3個位置,然後與0x01作bitwise AND,取出來是1,設給腳位。
我大概搞清楚了。
ReplyDelete我用很粗淺的計概概念來理解,
這個for(int i = 0; i < 4; i++){
digitalWrite(pins[i], (n >> i) & 0x01);
的作用就是將n化為二進位,然後依序由右到左取第i位的字串值給對應腳位。
是這個意思吧?
真的非常感謝葉老師不厭其煩、逐步詳細的指點教導我這個陌生的網友。
您上課一定講解得更詳盡。
很希望能有機會能實際地接受您的教導,謝謝您。
> 是這個意思吧?
ReplyDeleteyes.
抱歉葉老師,再請教您一個問題:
ReplyDelete我想在一段時間內,讓15個不同的LED燈在不同時間點亮。
例如: 以下時間格式為 分:秒
0:01 亮1號燈
0:03.2 亮3號燈
0:04.3 亮2號燈
0:05.2 亮4號燈
0:05.7 亮1號燈
0:06.3 亮5號燈+亮3號燈
0:07.5 亮6號燈+亮7號燈
0:08.0 亮3號燈
.....
這樣的點燈動作共有數百個
請問有類似的範例可供參考嗎?
或者我該下怎樣的關鍵字去搜尋類似的題目呢?
再次謝謝老師的指導,感謝您。
如果有規則,就要寫程式描述出來。
ReplyDelete沒有的話,只能建表,例如
typedef struct{
int t;
int pin;
boolean on;
} Data;
Data data[] = {
{50, 1, HIGH};
{150, 3, HIGH};
{450, 2, HIGH};
};
int idx = 0;
類似這樣的東西吧,然後寫程式處理,例如
unsigned long time_old;
開始處理時,time_old = millis(); 記錄起始時間,
然後在處理函式裡,根據時間順序,點亮該亮起的LED。
void blink(){
unsigned long t_now = millis();
if(t_now + data[idx].t > time_old){
digitalWrite(data[idx].pin, data[idx].on);
}
}
上面程式不全,只有極少部份的功能,僅供參考。
要不然就要去找找,有沒有別人寫好的程式庫。
謝謝老師,這裡算是沒有規則的點燈。
ReplyDelete因此我搜尋該下哪些關鍵字呢?
arduino+資料表+?+?
也謝謝老師的範例,甘溫。
關鍵字............我也不知道耶。
ReplyDelete你圖片上的是共陽 不是共陰
ReplyDelete請問是哪一張圖?
Delete我看錯了 業老師 我問一下,如果加兩個按鈕,一個是時,一個是分
ReplyDelete意思是不用重程式改時間,用按鈕改時間?
嗯,偵測按鈕是否按下,得知想增加時還是分,然後傳入適當地參數給updateTime
Delete程式碼要怎麼打出來 我還是個學生
Delete用手打。
Delete我不是個學生。
......
Delete可以不加電阻,直接寫pull-up方式嗎?
ReplyDelete不懂。
Deletepull-up什麼?
這裡是用OUTPUT模式。
Arduino 的設計者考慮 GPIO pin 可能拿來做數位輸入(Digital Input),
Delete所以每支 pin 內部都已經內建了一個 20K歐姆的上拉(Pull-up)電阻,
你只要這樣:
pinMode(pin, INPUT_PULLUP);
這樣就可以啟動內建的上拉電阻, 省去外接一個上拉電阻的麻煩 :-)
此時, 如果要測試按鈕,
則只要拿一條杜邦線或任意的導線從 GND 拉出然後碰觸 pin,
這樣就等於按下按鈕, digialRead(pin) 就會讀到 LOW 的值.
轉自http://www.arduino.cn/thread-13186-1-1.html
Good, thanks.
Delete請問如何控制一個4位數七段
ReplyDelete一個數字閃爍 其他恆亮呢?
謝謝您!
我想達到的效果是這樣的...
Delete按鍵A,B 更改閃爍位置顯示的數字
按鍵C 更改閃爍位置
目前卡關在 如何只讓一個數字閃爍而其他的恆亮
再次謝謝您!
請自己動手寫寫看。
Delete使用Timer程式庫,http://yehnan.blogspot.tw/2012/03/arduino.html,
#include 小於Timer.h大於
Timer timer;
boolean b;
void blinkDigit(){
b = !b;
if(b){
顯示某個位數
}
else{
不顯示某個位數,也就是讓它全部熄滅
}
}
void setup(){
timer.every(300, blinkDigit);
}
void loop()}{
timer.update();
}
大概是這樣吧,沒真的跑過。
謝謝您的建議!
Delete之後想到的方法是利用timer.every計數
int cnt, HiTime, LoTime;
if(掃描到閃爍位置 && cnt>=Hitime){
閃爍位置不顯示
if(cnt>=LoTime){
cnt=0;
}
}
else{
閃爍位置顯示
}
另想請問如果stop後要重新啟動timer
只要直接呼叫every就可以了嗎?
謝謝!
也可以。
Delete對。
請問我要加快時鐘的頻率,我該在哪邊修改呢?
ReplyDelete改
Deleteif(now - previousTimeMark > 1000){
updateTime(now - previousTimeMark);
previousTimeMark = now;
}
例如改成
if(now - previousTimeMark > 100){
updateTime((now - previousTimeMark) * 1.5);
previousTimeMark = now;
}
試試看吧。
葉難 老師
ReplyDelete想請問如何將arduino量測到的分壓輸出在七段顯示器上
用analogRead會讀到0~1023吧,轉成相對應的電壓值,譬如3.21,
Delete取出每一個位數,然後分別顯示。
請問要如何改用四合一七段顯示器
ReplyDelete