การใช้งาน 7 Segment กับ Arduino ตอนที่ 2 7 Segment 4 หลัก
1. รูปแสดง 7 Segment 4 Digit (ขอบคุณรูปภาพจาก tandyonline.co.uk)
การใช้งาน 7 Segment แบบหลายหลัก สามารถควบคุมได้แบบเดียวกับ 7 Segment แบบหลักดียว แต่มีขา Common เพิ่มขึ้นมา เพื่อควบคุมให้ 7 Segment หลักที่ต้องการติดขึ้นมา โดยอาศัยหลักการที่ว่า การแสดงผลตัวเลขในแต่ละหลักสลับกันไปแบบรวดเร็ว (ระดับ 50mS - 1mS) จะทำให้ดวงตาของเราไม่สามารถสังเกตุเห็นการสลับการแสดงผลได้ทัน ทำให้เรามองเห็นตัวเลขติดพร้อมๆกันในทุกๆหลัก ทั้งๆที่ในเสี้ยววินาทีนั้นมีตัวเลขติดแค่หลักเดียว
2. รูปแสดงหลักการแสดงผลตัวเลขของ 7 Segment หลายหลัก (ขอบคุณรูปภาพจาก antronics.co.uk)
3. รูปแสดงขาของ 7 Segment 4 Digit (ขอบคุณภาพจาก arduino.fisch.lu)
การสั่งให้ 7 Segment แสดงผลตัวเลขออกมาในแต่ละหลักจะใช้การควบคุมขา Common
- Common Anode - ขาคอมม่อนจะต้องได้รับลอจิก 1 ตัวเลขจึงจะแสดงผล
- Common Cathode - ขาคอมม่อนจะต้องได้รับลอจิก 0 ตัวเลขจึงจะแสดงผล
โดยที่การแสดงผลตัวเลขที่หลักใดๆก็ตาม หลักอื่นๆจะต้องไม่มีการแสดงผล หากมีการแสดงผลหลายๆหลักพร้อมกันจะทำให้การแสดงผลตัวเลขไม่สมบูรณ์ (มองไม่เป็นตัวเลข)
การต่อวงจรใช้งานกับ Arduino
ทั้งแบบ Common Anode และ Common Cathode ต่อใช้งานแบบเดียวกัน แต่จะแตกต่างกันในส่วนของโค้ดโปรแกรม
โค้ดโปรแกรม Arduino
เนื่องจากการจะเขียนโปรแกรมให้ภายในลูป (loop function) นั้นจัดการการแสดงผลตัวเลขไปพร้อมๆกับการประมวลผลอื่นๆจะทำให้ค่อนข้างที่จะเขียนโค้ดได้ยาก ดังนั้นเพื่อให้ง่ายต่อการเขียนโค้ด จึงต้องใช้อินเตอร์รัพท์ภายในเข้ามาเกี่ยวข้อง ซึ่งอินเตอร์รัพท์นี้จะช่วยแสดงผลตัวเลขได้ตลอดเวลา แม้ภายในฟังก์ชั่นหลัก (loop setup function) จะทำงานอย่างอื่น เช่น ติด delay() อยู่ก็ตาม การแสดงผลตัวเลขก็ยังดำเนินต่อไปแบบไม่มีปัญหา
เนื่องจากการใช้อินเตอร์รัพท์แบบภายในค่อนข้างยุ่งยากในการใช้งาน ดังนั้นจึงต้องใช้ไลบารี่ TimerOne เข้ามาเกี่ยวข้อง เพื่อความง่ายในการใช้งาน
สามารก๊อบโค้ดด้านล่างอัพลงบอร์ด Arduino แล้วดูผลการทำงานได้เลย
#include "TimerOne.h"
int D1 = 8;
int D2 = 9;
int D3 = 10;
int D4 = 11;
int CommonAK = 1; // Common Anode set to 1, Common Cathode set to 2
int num[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F };
int OnDigi = 0;
int NumberDisplay = 0;
bool ColonShow = false;
void setup() {
// put your setup code here, to run once:
Begin7Segment4Digi();
NumberDisplay = 2558;
}
void loop() {
}
void Begin7Segment4Digi() {
DDRD = 0xFF;
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
pinMode(D4, OUTPUT);
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
Timer1.initialize(1000); // 1000 = 1mS
Timer1.attachInterrupt(NextDigi);
}
void NextDigi() {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
int ShowOn = 0;
OnDigi = (OnDigi==4 ? 1 : OnDigi+1);
if (OnDigi==1) {
if (NumberDisplay<10)
ShowOn = NumberDisplay;
else
ShowOn = NumberDisplay%10;
} else if (OnDigi==2) {
if (NumberDisplay<10)
ShowOn = 0;
if (NumberDisplay<100)
ShowOn = NumberDisplay/10;
if (NumberDisplay<1000)
ShowOn = (NumberDisplay/10)%10;
if (NumberDisplay<10000)
ShowOn = (NumberDisplay/10)%10;
} else if (OnDigi==3) {
ShowOn = (NumberDisplay / 100) % 10;
} else if (OnDigi==4) {
ShowOn = NumberDisplay / 1000;
}
if (CommonAK==1)
PORTD = ~((num[ShowOn])|(ColonShow&&OnDigi==3 ? 0x80 : 0));
else
PORTD = ((num[ShowOn])|(ColonShow&&OnDigi==3 ? 0x80 : 0));
if (OnDigi==1) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? HIGH : LOW));
} else if (OnDigi==2) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
} else if (OnDigi==3) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
} else if (OnDigi==4) {
digitalWrite(D1, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
}
}
จากโค้ด หากต้องการเปลี่ยนตัวเลขเป็นตัวเลขใดๆที่แสดงผลในหน้าจอ เพียงแค่เซ็ตตัวแปร NumberDisplay เป็นตัวเลขที่ต้องการ (ไม่เกิน 4 หลัก) ก็จะทำให้ตัวเลขที่แสดงผลเปลี่ยนไป
- Common Anode - เซ็ตให้ CommonAK = 1
- Common Cathode- เซ็ตให้ CommonAK = 2
หากต้องการให้เครื่องหมายโคล่อน (:) ติด หรือดับ สามารถควบคุมได้โดยเซ็ตให้ตัวแปร ColonShow เป็น true หรือ false
1. รูปแสดง 7 Segment 4 Digit (ขอบคุณรูปภาพจาก tandyonline.co.uk)
การใช้งาน 7 Segment แบบหลายหลัก สามารถควบคุมได้แบบเดียวกับ 7 Segment แบบหลักดียว แต่มีขา Common เพิ่มขึ้นมา เพื่อควบคุมให้ 7 Segment หลักที่ต้องการติดขึ้นมา โดยอาศัยหลักการที่ว่า การแสดงผลตัวเลขในแต่ละหลักสลับกันไปแบบรวดเร็ว (ระดับ 50mS - 1mS) จะทำให้ดวงตาของเราไม่สามารถสังเกตุเห็นการสลับการแสดงผลได้ทัน ทำให้เรามองเห็นตัวเลขติดพร้อมๆกันในทุกๆหลัก ทั้งๆที่ในเสี้ยววินาทีนั้นมีตัวเลขติดแค่หลักเดียว
2. รูปแสดงหลักการแสดงผลตัวเลขของ 7 Segment หลายหลัก (ขอบคุณรูปภาพจาก antronics.co.uk)
3. รูปแสดงขาของ 7 Segment 4 Digit (ขอบคุณภาพจาก arduino.fisch.lu)
การสั่งให้ 7 Segment แสดงผลตัวเลขออกมาในแต่ละหลักจะใช้การควบคุมขา Common
- Common Anode - ขาคอมม่อนจะต้องได้รับลอจิก 1 ตัวเลขจึงจะแสดงผล
- Common Cathode - ขาคอมม่อนจะต้องได้รับลอจิก 0 ตัวเลขจึงจะแสดงผล
โดยที่การแสดงผลตัวเลขที่หลักใดๆก็ตาม หลักอื่นๆจะต้องไม่มีการแสดงผล หากมีการแสดงผลหลายๆหลักพร้อมกันจะทำให้การแสดงผลตัวเลขไม่สมบูรณ์ (มองไม่เป็นตัวเลข)
การต่อวงจรใช้งานกับ Arduino
ทั้งแบบ Common Anode และ Common Cathode ต่อใช้งานแบบเดียวกัน แต่จะแตกต่างกันในส่วนของโค้ดโปรแกรม
โค้ดโปรแกรม Arduino
เนื่องจากการจะเขียนโปรแกรมให้ภายในลูป (loop function) นั้นจัดการการแสดงผลตัวเลขไปพร้อมๆกับการประมวลผลอื่นๆจะทำให้ค่อนข้างที่จะเขียนโค้ดได้ยาก ดังนั้นเพื่อให้ง่ายต่อการเขียนโค้ด จึงต้องใช้อินเตอร์รัพท์ภายในเข้ามาเกี่ยวข้อง ซึ่งอินเตอร์รัพท์นี้จะช่วยแสดงผลตัวเลขได้ตลอดเวลา แม้ภายในฟังก์ชั่นหลัก (loop setup function) จะทำงานอย่างอื่น เช่น ติด delay() อยู่ก็ตาม การแสดงผลตัวเลขก็ยังดำเนินต่อไปแบบไม่มีปัญหา
เนื่องจากการใช้อินเตอร์รัพท์แบบภายในค่อนข้างยุ่งยากในการใช้งาน ดังนั้นจึงต้องใช้ไลบารี่ TimerOne เข้ามาเกี่ยวข้อง เพื่อความง่ายในการใช้งาน
สามารก๊อบโค้ดด้านล่างอัพลงบอร์ด Arduino แล้วดูผลการทำงานได้เลย
#include "TimerOne.h"
int D1 = 8;
int D2 = 9;
int D3 = 10;
int D4 = 11;
int CommonAK = 1; // Common Anode set to 1, Common Cathode set to 2
int num[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F };
int OnDigi = 0;
int NumberDisplay = 0;
bool ColonShow = false;
void setup() {
// put your setup code here, to run once:
Begin7Segment4Digi();
NumberDisplay = 2558;
}
void loop() {
}
void Begin7Segment4Digi() {
DDRD = 0xFF;
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
pinMode(D4, OUTPUT);
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
Timer1.initialize(1000); // 1000 = 1mS
Timer1.attachInterrupt(NextDigi);
}
void NextDigi() {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
int ShowOn = 0;
OnDigi = (OnDigi==4 ? 1 : OnDigi+1);
if (OnDigi==1) {
if (NumberDisplay<10)
ShowOn = NumberDisplay;
else
ShowOn = NumberDisplay%10;
} else if (OnDigi==2) {
if (NumberDisplay<10)
ShowOn = 0;
if (NumberDisplay<100)
ShowOn = NumberDisplay/10;
if (NumberDisplay<1000)
ShowOn = (NumberDisplay/10)%10;
if (NumberDisplay<10000)
ShowOn = (NumberDisplay/10)%10;
} else if (OnDigi==3) {
ShowOn = (NumberDisplay / 100) % 10;
} else if (OnDigi==4) {
ShowOn = NumberDisplay / 1000;
}
if (CommonAK==1)
PORTD = ~((num[ShowOn])|(ColonShow&&OnDigi==3 ? 0x80 : 0));
else
PORTD = ((num[ShowOn])|(ColonShow&&OnDigi==3 ? 0x80 : 0));
if (OnDigi==1) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? HIGH : LOW));
} else if (OnDigi==2) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
} else if (OnDigi==3) {
digitalWrite(D1, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D2, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
} else if (OnDigi==4) {
digitalWrite(D1, (CommonAK==1 ? HIGH : LOW));
digitalWrite(D2, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D3, (CommonAK==1 ? LOW : HIGH));
digitalWrite(D4, (CommonAK==1 ? LOW : HIGH));
}
}
จากโค้ด หากต้องการเปลี่ยนตัวเลขเป็นตัวเลขใดๆที่แสดงผลในหน้าจอ เพียงแค่เซ็ตตัวแปร NumberDisplay เป็นตัวเลขที่ต้องการ (ไม่เกิน 4 หลัก) ก็จะทำให้ตัวเลขที่แสดงผลเปลี่ยนไป
- Common Anode - เซ็ตให้ CommonAK = 1
- Common Cathode- เซ็ตให้ CommonAK = 2
หากต้องการให้เครื่องหมายโคล่อน (:) ติด หรือดับ สามารถควบคุมได้โดยเซ็ตให้ตัวแปร ColonShow เป็น true หรือ false
ไม่มีความคิดเห็น:
แสดงความคิดเห็น