ภาพรวม
เริ่มแรกเลยนะน้อง ตอนนั้นพี่ๆ ได้มาซึ่งนิกซี่ท่อ (Nixie Tubes) สุดคลาสสิกจากยุคโซเวียตอย่าง IN-12, IN-14 และ IN-18 แบบแทบจะใช้ไม่หมด งานแรกที่คิดคือจะทำเป็นชิลด์ (Shield) สำหรับ Arduino ง่ายๆ เพื่อเอาไว้แสดงผลเลขสวยๆ แบบนี้แหละ Arduino ก็มีอยู่แล้ว งานเลยดูเหมือนจะเล็ก (ตอนนั้นคิดงั้นนะ) แต่ตอนนั้นพวกพี่ก็ยังไม่รู้อะไรเลยเกี่ยวกับการจัดการกับหลอดไฟแบบนี้
Extreme 170V Cathodes: Arduino นิกซี่ทับคล็อก
นาฬิกาทั่วไปใช้ไฟ LED 5V ธรรมดาๆ แต่ นิกซี่ทับคล็อก (Nixie Tubes Clock) เนี่ย ใช้เทคโนโลยีจากยุคสงครามเย็นของโซเวียตในทศวรรษ 1960 ที่อันตรายสุดๆ! ภายในนิกซี่ท่อ (อย่าง IN-14 ที่เป็นตำนาน) มีแก๊สนีออนเรืองแสงและขดลวดโลหะที่ถูกดัดให้เป็นรูปตัวเลข 0-9 พอดีเลย อยากให้เลขไหนสว่างเป็นสีส้มเร่าร้อน Arduino จะส่งสัญญาณ 5V ธรรมดาไม่ได้นะ มันต้องสั่งงานวงจรที่สร้าง แรงดันไฟฟ้ากระแสตรง 170V สูงปรี๊ด เพื่อจุดหลอดไฟ ซึ่งต้องใช้ชิปถอดรหัสแรงดันสูงอย่าง K155ID1 / 74141 (BCD-to-Decimal decoder) มาช่วยจัดการ!
ไม่นานพวกพี่ก็เจอวงจรสำหรับเลี้ยงหลอดพวกนี้ในเน็ต:
ใช่แล้วว! มันติดสว่างเลย! ตอนเห็นครั้งแรกนี่ตะลึงแทบช็อค เหมือนเห็นปาฏิหาริย์เล็กๆ เลยรู้สึกทันทีว่า "ใช่เลย เรามาถูกทางแล้ว" งานนี้ต้องจัดเซสชั่นถ่ายรูปทันที:
การจัดการกับไฟ DC แรงดันสูง (The Boost Converter)
หลักการคร่าวๆ ก็คือ น้องจะเสียบอะแดปเตอร์ 12V DC ธรรมดาเข้าไปในชิลด์ Arduino ตัวใหญ่โตนี่แหละ
- แรงดัน 12V ส่วนนึงจะไปเลี้ยงตัวโปรเซสเซอร์ของ Arduino Uno อย่างปลอดภัย
- แต่บนชิลด์เนี่ย มีวงจร สเต็ปอัพบูสต์คอนเวอร์เตอร์ (High-Voltage Step-Up Boost Switcher) สุดน่ากลัวในตัว! มันจะปั่นไฟจาก 12V ให้พุ่งขึ้นไปอยู่ที่
170 โวลต์ DCพอดี - กับดักแคโทด (The Cathode Trap): เราเชื่อมขั้วบวก (Anode) ที่มีไฟ 170V เข้ากับตัวหลอดแก้วโดยตรง!
- แต่นะ ถ้าน้องส่งไฟ 170V กลับเข้าไปที่ขา
D5เล็กๆ ของ Arduino ล่ะก็ ตัวชิประเบิดเป็นไฟแน่นอน! - วิธีที่ปลอดภัยคือ Arduino จะใช้ ชิปถอดรหัส K155ID1 แยกต่างหาก ชิปเล็กๆ พวกนี้ทนแรงดัน 170V ที่ขาออกได้! Arduino แค่ส่งรหัสไบนารี 4 บิต (
0b0101สำหรับเลข '5') ที่แรงดัน 5V ไปให้ชิป K155ID1 จากนั้นชิปนี้ก็จะเชื่อมแคโทดหมายเลข 5เข้ากับกราวด์ ทำให้วงจรไฟ 170V ครบวงจรและจุดให้เลข 5 สว่างขึ้นมา!
วันต่อมา พวกพี่ก็เริ่มคุยกันเรื่องแนวคิดของโปรเจกต์นี้: เพื่อให้ง่ายและประหยัดขึ้น ตอนแรกตัดสินใจจะใช้หลักการแสดงผลแบบไดนามิก (dynamic display) แต่สุดท้ายก็เปลี่ยนใจมาใช้โหมดแสดงผลแบบสแตติก (static display) แทน แม้ว่าสำหรับหลอด IN-14 จะมองไม่ค่อยเห็นความแตกต่าง แต่สำหรับหลอด IN-18 แล้วมันเห็นชัดเจนเลย – ในโหมดไดนามิก มันจะไม่สว่างเท่า และหลายหลอดจะเกิดเอฟเฟกต์ที่เรียกว่า "จุดสีน้ำเงิน" (blue spots effect):
โหมดแสดงผลแบบไดนามิกคือโหมดที่ในแต่ละช่วงเวลาไม่ได้เปิดหลอดทุกหลอดพร้อมกัน แต่จะเปิดทีละหลอด (หรือบางทีอาจเป็นแบบอื่น เช่น เปิดพร้อมกันแค่สองหลอด)
ตอนที่เราคุยกันเรื่องอนาคตของเจ้าเครื่องนี้ พอตัดสินใจแล้วว่าจะเพิ่มความสามารถแสดงข้อมูลจากคอมพิวเตอร์ลงบนหลอดนิกซี มันจะเปิดโอกาสให้พวกมือใหม่หัดเล่นสร้างอุปกรณ์ของตัวเองขึ้นมาได้ เช่น แสดงจำนวนข้อความที่ยังไม่อ่าน หรือจำนวนรอบในเกมอย่าง Fallout
จากนั้นก็เริ่มต้นเลือกฮาร์ดแวร์ที่สามารถสวิตช์แคโทด (ตัวเลข) ในหลอดได้ ตัวเลือกมันชัดเจนอยู่แล้ว - ต้องใช้ชิฟต์เรจิสเตอร์แบบ SPI เพื่อประหยัดขาของ MCU แต่เพราะแรงดันเลี้ยงหลอดมันสูงมาก - สูงถึง 200 โวลต์ ตัวเลือกเลยมีไม่กี่ตัว: HV513, HV5812, HV5122 หลังจากลองสร้างอุปกรณ์ด้วยชิปแต่ละตัวแล้ว เราตัดสินใจใช้ HV5812 (ในรุ่นใหม่ของ Shields อย่าง NCS314 V2.X และ NCS312 V1.X จะใช้ IC HV5122) ชิปตัวนี้สะดวกดีเพราะมันควบคุมหลอดได้สองหลอดพร้อมกัน เนื่องจากเป็นเรจิสเตอร์ 20 บิต
เพื่อควบคุมหลอด 6 หลอด เราต้องใช้วงจรแบบนี้สามชุดเชื่อมต่อกันแบบอนุกรม วิธีนี้ทำให้เราส่งแพ็กเก็ตข้อมูลผ่าน SPI ครั้งเดียวได้เลย แล้วไม่ต้องกังวลกับการอัปเดตข้อมูลบนหลอด เหมือนที่ต้องทำถ้าใช้อัลกอริทึมแสดงผลแบบไดนามิก ง่ายๆ ก็คือ ตราบใดที่เราไม่ต้องการเปลี่ยนข้อมูลบนหลอด MCU ก็ไปทำอย่างอื่นได้เลย แม้แต่จะนอนหลับ!
อยากจะพูดถึงการส่งข้อมูลผ่าน SPI สักหน่อย Arduino สามารถส่งข้อมูลได้ครั้งละ 8 บิต แต่เราต้องการ 60 บิต จำนวนเต็มที่ใกล้เคียงและหารด้วย 8 ลงตัวที่มากกว่าคือ 64 ดังนั้นเราต้องใช้เทคนิคบิตแมจิกนิดหน่อย - สร้างตัวแปรใหญ่ๆ ประเภท unsigned long long ขนาด 64 บิตสำหรับแต่ละเรจิสเตอร์ แล้วส่งทีละ 8 บิต ทั้งหมด 8 ครั้ง โดยแต่ละครั้งก็จะขยับบิตทั้งหมดในตัวแปรไปทางขวา:
SPI.transfer(var64);
SPI.transfer(var64>>48);
SPI.transfer(var64>>40);
SPI.transfer(var64>>32);
SPI.transfer(var64>>24);
SPI.transfer(var64>>16);
SPI.transfer(var64>>8);
SPI.transfer(iTmp);
การดึงเวลาแบบซิงค์ (DS3231 + กำจัด Cathode Poisoning)
ฮาร์ดแวร์ของนิกซีไม่รู้หรอกว่าตอนนี้กี่โมงแล้ว วงจรเลยต้องพึ่งพา ชิป DS3231 RCT แบบ I2C สำหรับติดตามเวลา UNIX แบบเป๊ะๆ
- ซอฟต์แวร์ C++ ต้องไปดึงเวลามาให้ได้ เช่น
14:38:05 - จากนั้นก็แยกตัวเลขออกมาเป็นหลักๆ ด้วยคณิตศาสตร์ แล้วส่งไปแสดงบนหลอดนิกซีทั้ง 6 หลอด!
- ปัญหาฮาร์ดแวร์ระดับหายนะ: Cathode Poisoning!
- ถ้าหลอดนิกซีหลอดแรกแสดงเลข
1(จากเวลา14:00) ติดต่อกันเป็นเวลา 20 ชั่วโมง โลหะภายในหลอดจะเสื่อมสภาพทางเคมี ("เป็นพิษ") ทำให้ตัวเลขอื่นๆ ที่ไม่ค่อยได้ใช้แสดงผลไม่ได้ถาวร! - วิธีแก้ด้วยซอฟต์แวร์ C++ (โค้ดสล็อตแมชชีน):
// ทุกๆ 10 นาที ให้รันวงจรกำจัดพิษครั้งใหญ่!
if (minute % 10 == 0 && second == 0) {
for (int i=0; i < 50; i++) {
// บังคับให้หลอดทุกหลอดหมุนตัวเลข 0, 1, 2, 3.. 9 อย่างรวดเร็ว!
// วิธีนี้จะช่วยเผาไหม้สนิมออกจากเส้นลวดตัวเลขทั้ง 10 ภายในหลอด!
fireNixieSlotMachineSweep();
delay(50);
}
}
เป้าหมายที่ตั้งไว้และทำสำเร็จแล้ว:
- การแสดงผลแบบสแตติกโดยใช้ชิฟต์เรจิสเตอร์
- โหมดสล็อตแมชชีน (ป้องกัน Cathode Poisoning)
- มีฟังก์ชันมาตรฐานสำหรับนาฬิกา เช่น แสดงนาฬิกา, วันที่, เวลา, ปุ่มตั้งปลุก
- RTC (Real Time Clock) พร้อมแบตเตอรี่ CR1220 (บอร์ดรุ่นใหม่ V1.2-2.X ใช้ชิปวัดเวลาความแม่นยำสูง RTC DS3231)
- วัดอุณหภูมิด้วย DS18B20 [เซลเซียสหรือฟาเรนไฮต์]
- ควบคุมผ่านพอร์ตอินฟราเรด TSOP4836 (ทำงานกับ Mega เท่านั้น) เราใช้รีโมท Sony RM-X151 แต่น่าจะใช้รีโมทอื่นที่ความถี่ 36kHz ได้เหมือนกัน
ฟีเจอร์ที่ยังทำออกมาไม่สมบูรณ์
- เซ็นเซอร์วัดแสง
อุปกรณ์แรงดันสูงแบบคลาสสิก (Legacy Voltage Equipment)
- Arduino Uno/Nano (ความเร็วมาตรฐานก็เพียงพอแล้วจ้า)
- หลอดนิกซี IN-14 หรือ IN-12 แบบของแท้ (ฮาร์ดแวร์วินเทจ นำเข้าจากยุโรปตะวันออกโดยเฉพาะ)
- NCS314 Nixie Shield หรือชุดถอดรหัส K155ID1 แบบมาตรฐาน
- โมดูลนาฬิกาจริง DS3231 แบบ I2C
- (คำเตือนระดับอันตราย: แรงดัน 170 โวลต์ DC นะน้อง! ถ้าเผลอไปแตะลายวงจรตอนเสียบ USB เมื่อไหร่ รับรองช็อตตัวโก่งแน่ๆ ต้องระวังให้มากๆ)