Iterative Arrays: วงจรวิ่งไล่ LED แบบเรียงลำดับ
น้องใหม่หลายคนพังโค้ดตัวเองเละเทะด้วยการเขียน digitalWrite(2, HIGH); delay(100); digitalWrite(2, LOW); digitalWrite(3, HIGH)... ยาวเป็นร้อยบรรทัด แค่จะให้ LED 10 ดวงวิ่งไล่กันเป็นเส้นตรง! วงจรวิ่งไล่ LED แบบเรียงลำดับ นี่แหละที่จะปฏิวัติโครงสร้างโปรแกรมให้สะอาดตาขึ้น! ด้วยการโยนหมายเลขพิน (Pin) ของ Arduino เข้าไปเก็บใน อาร์เรย์จำนวนเต็มหนึ่งมิติ (One-Dimensional Integer Array) แล้วใช้ลูป for ตัวเดียวจัดการซะ มันจะบีบโค้ดยุ่งเหยิง 100 บรรทัด ให้เหลือแค่ 4 บรรทัดที่เรียบร้อยสมเป็น C++ ตัวจริง!
เปิดโปงโครงสร้างลูป for แบบ C++
อาร์เรย์ทางกายภาพนี่ทำงานเหมือนตู้เก็บเอกสารที่จัดเรียงหมายเลขพินให้เราเอง
int pinArray[] = {2, 3, 4, 5, 6, 7};(ดัชนีที่ 0 คือ พิน 2 นะจ๊ะ!)- ลูป
forทำงานเหมือนเครื่องยนต์เพิ่มค่าทางคณิตศาสตร์:for (int i = 0; i < 6; i++) - เครื่องยนต์สุดโหดนี้จะเอา
iยัดเข้าไปในอาร์เรย์ตรงๆ:digitalWrite(pinArray[i], HIGH); - มันจะจุดไฟ "ON" รอ
100msปิดไฟ "OFF" แล้วกระโดดไปจัดการพินถัดไปทันที!
int ledPins[] = { 2, 3, 4, 5, 6, 7 }; // อาร์เรย์เมทริกซ์ฮาร์ดแวร์!
int pinCount = 6;
int timer = 80; // ความเร็วในการวิ่งของแสงไล่!
void setup() {
// ตั้งโหมดพินแบบประหยัดแรงงาน ด้วยการวนลูปผ่านอาร์เรย์!
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(ledPins[thisPin], OUTPUT);
}
}
void loop() {
// เมทริกซ์การทำงานแบบไป-กลับ สไตล์ Knight Rider!
// สแกนไปข้างหน้าให้หมด!
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], HIGH); // จุดไฟ!
delay(timer); // แสดงผลเฟรม!
digitalWrite(ledPins[thisPin], LOW); // ดับไฟ!
}
// สแกนย้อนกลับให้หมด!
// เริ่มที่ดัชนี 4 (เพราะดัชนี 5 คือขอบสุดท้าย!)
for (int thisPin = pinCount - 2; thisPin > 0; thisPin--) {
digitalWrite(ledPins[thisPin], HIGH);
delay(timer);
digitalWrite(ledPins[thisPin], LOW);
}
}
กำจัดอันตราย "เงาปรากฎ" แบบ Cylon
ถ้าน้องต่อ LED สีแดง 6 ดวงโดยไม่มีตัวต้านทาน 220 โอห์ม ข้างใน ตัวเก็บประจุขนาดจิ๋วในแผง Arduino จะคายประจุไม่ทัน!
- นี่ทำให้เกิด "Ghosting" คือ LED ที่อยู่ข้างๆ จะเรืองแสงจางๆ ควบคุมไม่ได้!
- ที่แย่กว่านั้น การต่อ LED ตรงไปที่
GNDในขณะที่สัญญาณวิ่งเร็ว จะดึงกระแสเกิน100mAพร้อมกัน ทำให้เรกูเลเตอร์แรงดันของ ATmega328P รวนได้! - น้อง ต้อง บัดกรีหรือใช้เบรดบอร์ดต่อ ตัวต้านทาน 220 โอห์ม 6 ตัว แยกกันให้แต่ละ LED ทุกดวงจากพินเอาต์พุตของมันให้เรียบร้อย! ห้ามช็อตนะตัวนี้!
การตั้งค่าฮาร์ดแวร์สำหรับอาร์เรย์เอาต์พุต
- Arduino Uno/Nano (จัดการการวนลูปของอาร์เรย์แบบต่อเนื่องได้อยู่แล้ว)
- LED ขนาด 5mm จำนวน 6 ดวง (เหมือนกัน) (สีแดงหรือน้ำเงินจะให้เอฟเฟกต์แสงวิ่งแบบ Cylon ที่เท่สุดๆ)
- ตัวต้านทาน (Resistor) 220 โอห์ม จำนวน 6 ตัว (คุมกระแสให้อยู่ในเกณฑ์ปลอดภัยสำหรับตัวไมโครคอนโทรลเลอร์! ห้ามช็อตนะตัวนี้)
- โพเทนชิออมิเตอร์แบบอนาล็อก (ตัวเลือกเสริม) (ถ้าน้องต่อปุ่มหมุนเข้ากับขา
A0น้องจะสามารถแมปค่าจากanalogReadไปเป็นตัวแปรtimerได้พอดีเป๊ะ ทำให้เราสามารถปรับความเร็วของแสงวิ่งได้แบบเรียลไทม์ด้วยการหมุนปุ่ม! จัดไปวัยรุ่น)
ตัวอย่างโค้ด (เปิดปิด LED ตามลำดับแบบพื้นฐาน):
/* A simple program to sequentially turn on and turn off 10 LEDs */
int LED3 = 11;
int LED4 = 10;
int LED5 = 9;
int LED6 = 8;
int LED7 = 7;
int LED8 = 6;
int LED9 = 5;
int LED10 = 4;
int LED11 = 3;
int LED12 = 2;
void setup() {
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
pinMode(LED6, OUTPUT);
pinMode(LED7, OUTPUT);
pinMode(LED8, OUTPUT);
pinMode(LED9, OUTPUT);
pinMode(LED10, OUTPUT);
pinMode(LED11, OUTPUT);
pinMode(LED12, OUTPUT);
}
void loop() {
digitalWrite(LED3, HIGH); // turn on LED3
delay(100); // wait for 200ms
digitalWrite(LED4, HIGH); // turn on LED4
delay(100); // wait for 200ms
digitalWrite(LED5, HIGH); // turn on LED5
delay(100); // wait for 200ms
digitalWrite(LED6, HIGH); // turn on LED6
delay(100); // wait for 200ms
digitalWrite(LED7, HIGH); // turn on LED7
delay(100); // wait for 200ms
digitalWrite(LED8, HIGH); // turn on LED8
delay(100); // wait for 200ms
digitalWrite(LED9, HIGH); // turn on LED9
delay(100); // wait for 200ms
digitalWrite(LED10, HIGH); // turn on LED10
delay(100); // wait for 200ms
digitalWrite(LED11, HIGH); // turn on LED11
delay(100); // wait for 200ms
digitalWrite(LED12, HIGH); // turn on LED12
delay(100); // wait for 200ms
digitalWrite(LED3, LOW); // turn off LED3
delay(100); // wait for 300ms
digitalWrite(LED4, LOW); // turn off LED4
delay(100); // wait for 300ms
digitalWrite(LED5, LOW); // turn off LED5
delay(100); // wait for 300ms
digitalWrite(LED6, LOW); // turn off LED6
delay(100); // wait for 300ms
digitalWrite(LED7, LOW); // turn off LED7
delay(100); // wait for 300ms
digitalWrite(LED8, LOW); // turn off LED8
delay(100); // wait for 300ms
digitalWrite(LED9, LOW); // turn off LED9
delay(100); // wait for 300ms
digitalWrite(LED10, LOW); // turn off LED10
delay(100); // wait for 300ms
digitalWrite(LED11, LOW); // turn off LED11
delay(100); // wait for 300ms
digitalWrite(LED12, LOW); // turn off LED8
delay(100); // wait for 300ms before running program all over again
}