วันพุธที่ 30 ธันวาคม พ.ศ. 2558

วิทยุ FM จาก AR1010 (PCB)

จากบันทึกก่อนหน้านี้เรื่องวงจรวิทยุ FM จาก AR1010 กับ Barebone Arduino ก็ทิ้งท้ายไว้ว่าจะไม่ทำโปรเจ็คอื่นถ้าโปรเจ็คนี้ไม่เสร็จ

แล้วก็ไม่ขึ้นโปรเจ็คอื่น ๆ อีกเลยนับจากนั้น...ทั้ง ๆ ที่อยากจะทำต่อให้เสร็จ อุปสรรคสำคัญคือระบบประกันคุณภาพอุดมศึกษากินเวลาไปหมด อย่าว่าแต่เวลาสำหรับงานอดิเรกแบบนี้เลยครับ แม้แต่เวลาสอนมันก็กิน! เรื่องนั้นช่างมันเถอะ บ่นไปหลายที่ ต่างกรรมต่างวาระ

ช่วงนี้ปีใหม่ เป็นช่วงเดียวที่มีเวลาส่วนตัวจริง ๆ ก็เลยขุดงานขึ้นมาทำให้เสร็จซะ สิ่งที่ทำในขั้นตอนนี้คือการออกแบบแผ่นวงจรพิมพ์ (PCB) ครับ งานธรรมดาพื้น ๆ สำหรับหลาย ๆ คน แต่เป็นงานที่ยังสนุกและท้าทายเสมอสำหรับผม เครื่องมือที่ใช้ก็คือ KiCad เจ้าเก่า

สิ่งที่ได้เรียนรู้ในรอบนี้ก็คือ

  • ก่อนออกแบบก็ไปอ่านคู่มือการออกแบบ PCB โดยสรุปมาก่อน ได้ความรู้มาพอสมควร เช่นเรื่องการแยกกิ่งของไฟเลี้ยงและกราวด์ของวงจรส่วนแอนาลอกออกจากส่วนดิจิตัล การใช้กราวด์เพลน ปัญหาเรื่องสัญญาณรบกวนต่าง ๆ
  • การใช้ via และ upper copper แทนการใส่ Link (เส้นลวด แต่ผมไม่รู้ว่าในวงการเขาเรียกว่าอะไร) แต่ก่อนทำไม่เป็น ตอนนี้ทำเสร็จแล้วยังมานึกว่า ไปใช้วิธีเพิ่ม R 0 โอห์มแล้วอัพเดต Netlist จะดีกว่าไหม...ไม่รู้เหมือนกัน เอาไว้ลองรอบหน้า
  • การอัพเดต Netlist ซึ่งมีประโยชน์มากเวลาเราต่อวงจรกับขั้วสายไฟซึ่งอันที่จริงเรามีอิสระที่จะกำหนดให้ขั้วไหนไปต่อกับ Net ไหนก็ได้ วิธีการก็ง่าย ๆ คือไปเขียนลายวงจร (Schematic) ใหม่ สร้าง Netlist ใหม่ แล้วก็ Reload Netlist ใหม่ก็เสร็จ ที่ต้องระวังก็คือตอนเลือก Option ก็เลือกให้สอดคล้องกับสิ่งที่เราทำ เช่นมีอุปกรณ์ใหม่ไหม ลบอุปกรณ์เก่าไปหรือเปล่า จะลบ Track และ/หรือ Pad ที่ไม่ใช้แล้วไหม ฯลฯ การอัพเดตนี่ก็ช่วยให้เดินลายทองแดง (Routing) ง่ายขึ้นไม่น้อย
  • การเปลี่ยนความกว้างของ Track คือเดิมผมก็คิดว่าจะกัดแผ่นวงจรเอง ถ้ากัดเอง Track ก็ต้องกว้างหน่อย ผมก็เลยตั้งค่าไว้ที่ 0.8 mm (ดูเหมือนเล็กแต่ใหญ่มาก เดินลายทองแดงยาก) แต่ดูศักยภาพและเวลาแล้วคงไม่เวิร์ก ก็เลยพิจารณาการสั่งทำ PCB ต้นแบบ ซึ่งบริษัทที่รับทำรองรับ Track เล็กสุดได้ถึง 10 mil (1 mil คือ 1/1000 นิ้ว) การเปลี่ยนนี้ผมก็อาจจะมักง่ายไปหน่อย คือผมไปเปลี่ยนที่ Global DRC เลย ไม่ต้องมี Track Width หลายค่า ใช้ค่าเดียวนี่แหละ
  • การทำ Ground Plane โดยใช้เครื่องมือ Zone แต่ก่อนเคยทำมาแล้ว แล้วก็ร้างไปจนลืม ต้องมาหาวิธีทำใหม่อีกรอบ
ผลงานในขั้นตอนนี้ก็เอามาดูกันหน่อย
เนื่องจากตั้งใจจะทำแผ่นวงจรหน้าเดียว ตอนทำวงจรส่วนดิจิตัลโดยเฉพาะส่วนของ 7-Segment LED เลยรู้สึกว่ายากเป็นพิเศษ

จริง ๆ ก็ไม่รู้เหมือนกันว่าทำไปทำไม ไม่ใช่งานวิจัย ไม่ใช่เรื่องที่ชำนาญขนาดจะไปสอนคนอื่นได้ ไม่ใช่ของที่ขายได้ (ตกรุ่นไปแล้ว) ไม่ใช่เรื่องที่จะไปเขียนลงนิตยสารได้ แต่ถ้าไม่ทำให้เสร็จก็คงไม่สบายใจ แต่ระหว่างที่ทำก็รู้สึกมีความสุขดี

ขั้นต่อไปก็คือสั่งทำ PCB และเอามาต่อวงจรลงแผ่นวงจรพิมพ์ให้มันเสร็จเสียที

วันเสาร์ที่ 14 กุมภาพันธ์ พ.ศ. 2558

วิทยุ FM จาก AR1010 (โปรโตบอร์ด)

ผมได้โมดูลเครื่องรับวิทยุ FM AR1010 มานานแล้ว (ไม่น้อยกว่า 3 - 5 ปี) จำไม่ได้ด้วยซ้ำว่าซื้อจากไหน แต่ก็ไม่มีโอกาสเอามาต่อวงจรให้เสร็จสักที ที่สำคัญคือโมดูลนี้หา Datasheet ยาก แม้แต่จากเว็บของ SparkFun เองก็ระบุว่าต้องติดต่อไปจึงจะให้ จนเดี๋ยวนี้โมดูลนี้เขาเลิกขายกันไปแล้ว คิดว่าสาเหตุหลัก ๆ ที่ทำให้ไม่ได้ลงมือทำซักทีก็คงจะเป็นเรื่องเวลา
ตอนนี้เวลามีแล้ว รื้อ ๆ ค้น ๆ ในกล่องเจอเจ้าโมดูลนี้ก็เลยคิดว่าจะลองทำดู ไหน ๆ ก็อุตส่าห์ซื้อมาแล้ว แม้ว่าการเอาไปทำโปรเจ็คแล้วคงไม่มีมูลค่าเพิ่มอะไร เพราะวิทยุ FM เดี๋ยวนี้ถูกมาก แต่ถ้าทิ้งไว้ก็จะเสียของไปเปล่า ๆ อย่างน้อยถ้าออกแบบเองอยากได้อะไรก็คงจะทำได้ (ล่ะมั้ง)

สุดท้ายก็เลยทำแบบง่าย ๆ คือให้มีคุณสมบัติดังนี้
  • แสดงตัวเลขความถี่ของสถานีทาง 7-Segment 4 ตัว
  • มีปุ่มควบคุม 2 ปุ่มคือเลื่อนสถานีขึ้นและลง โดยข้อจำกัดของโมดูลเลยทำให้เลื่อนได้ทีละ 0.1 MHz เรื่องนี้มีข้อเสียคือจะจูนหาสถานีเช่น 92.25 MHz ไม่ได้
  • เจ้าปุ่ม 2 ปุ่มนั้นถ้ากดค้างเกิน 0.5 วินาทีจะกลายเป็นการค้นหาสถานีอัตโนมัติในทิศทางเลื่อนขึ้นหรือเลื่อนลงแล้วแต่ว่าปุ่มที่กดเป็นปุ่มไหน
  • ให้สัญญาณเสียงสเตริโอปรับระดับเสียงได้ด้วยโวลุ่มตัวเดียว
เนื่องจากอยากทำให้เสร็จเร็ว ๆ เลยหาไลบรารีจากคนอื่นมาใช้ (สารภาพตรง ๆ ว่าถ้าต้องเขียนเองคงไม่เสร็จ) ไลบรารีที่ใช้มีดังนี้
  • ควบคุมการแสดงผล LED 7-Segments ด้วย SevSeg โดย Dean Reading
  • ควบคุมการทำงานของ AR1010 ด้วย AR1010lib โดย Adam Jansch
  • ตรวจการกดปุ่มว่าเป็นการกดค้างหรือกดปล่อย ได้ไอเดียจาก Arduino Forum
บล๊อกไดอะแกรมการทำงานก็เรียบ ๆ ดังรูป
จากคำอธิบายในไลบรารีที่ใช้ประกอบกับแนวทางการทำงาน ก็ต่อวงจรบนโปรโตบอร์ด ใช้เวลาช่วงเย็นหลังเลิกงานง่วนอยู่สัก 2 - 3 วันก็เสร็จ เสาอากาศไม่ได้ต่อไว้ยาวเลยรับได้แค่บางสถานีเท่านั้น แต่เสียงดีใช้ได้ทีเดียว


พอวงจรบนโปรโตบอร์ดทำงานได้ ก็เลยเอามาเขียนลายวงจร โปรแกรมที่ใช้คือ KiCad ซึ่งก็ไม่ได้ใช้มานาน ต้องขุดความทรงจำกันพอสมควร แต่จะทิ้งไว้ก็จะกลายเป็นโปรเจ็คไม่เสร็จก็จะไม่ดี ก็เลยพยายามทั้งสร้างไลบรารีอุปกรณ์ใหม่ หัดใช้บัส ฯลฯ ก็ได้ลายวงจรมาดังรูป
ในเมื่อยังไม่ได้ทำแผ่นวงจรพิมพ์ ตอนนี้ก็ทิ้งวงจรไว้บนโปรโตบอร์ดไปก่อน ทำเป็นเงื่อนไขไว้ว่าถ้าไม่ทำแผ่นวงจรพิมพ์ให้เสร็จก็จะเอาโปรโตบอร์ดไปทำอย่างอื่นไม่ได้ จะได้บังคับใจให้ทำให้เสร็จให้ได้ และถ้าเสร็จเมื่อใดก็จะเอามาบันทึกไว้ที่นี่เช่นเคย

วันอาทิตย์ที่ 4 สิงหาคม พ.ศ. 2556

ทำสต๊อปโมชั่นกับ MS-09RS Rick Dom (ไม่มีวิธีทำ)

ความฝันอย่างหนึ่งสมัยเรียนมัธยมต้นก็คือการได้เข้าร่วมทีมสเปเชียลเอฟเฟคระดับโลกอย่าง ILM เรื่องนี้ต้องขอบคุณสำนักพิมพ์ซีเอ็ดยูเคชันสำหรับวารสารรู้รอบตัว ที่นำเสนอเรื่องราวของการสร้างสเปเชียลเอฟเฟคในภาพยนตร์ให้ได้อ่าน

แม้ ความฝันจะถูกลืมไปชั่วระยะหนึ่ง และชีวิตก็หักเหสู่งานสอนแบบกู่ไม่กลับแล้ว นาน ๆ ทีก็นึกถึงความฝันเล็ก ๆ น้อย ๆ เหล่านั้นพอให้อบอุ่นใจบ้าง ช่วงนี้ (29/07 - 02/08) นักศึกษากำลังสอบกลางภาค ผมก็ไม่มีชั่วโมงสอนนอกจากงานธุรการประจำวัน ตอนกลางคืนก็เลยมีเวลาต่อ MS-09RS Rick Dom จนเสร็จ (จนได้) ทีนี้กล่องที่ซื้อมามันมี 2 ตัว อีกตัวหนึ่งคือ RX-78-3 Gundam ซึ่งต่อเสร็จไปแล้ว (เมื่อนานมาแล้ว) ก็เลยเอามาเล่นเป็นเด็ก ๆ ไปเลย

เล่นไปเล่นมานึกได้ว่ามัน มีเทคนิคที่เรียกว่าสต๊อปโมชั่น (Stop Motion) ที่สามารถทำให้หุ่นพวกนี้มันเคลื่อนไหวได้นี่นะ เทคนิคสต๊อปโมชั่นที่ว่านี้ก็คือ ตั้งกล้องให้อยู่กับที่ ขยับท่าทางให้หุ่นทีละนิด ๆ แล้วก็บันทึกภาพของหุ่นทีละเฟรม ๆ หลังจากนั้นก็นำภาพแต่ละเฟรมมาต่อกันเป็นภาพเคลื่อนไหว

สำหรับ สมัยก่อนเรื่องแบบนี้คงเป็นเรื่องวุ่นวายไม่ใช่น้อย แต่ในยุคคอมพิวเตอร์ + โอเพนซอร์ส เรื่องการต่อเฟรมภาพให้กลายเป็นภาพยนตร์สามารถทำได้ง่าย ๆ สำหรับผมเองใช้โปรแกรม OpenShot ดำเนินการเรื่องนี้
การเคลื่อนไหวยังดูตะกุกตะกักน่าผิดหวังอยู่ เนื่องจาก Frame rate ต่ำมาก โดยปกติหนังเงียบเก่า ๆ จะมี Frame rate ไม่น้อยกว่า 14 FPS หรือ 14 ภาพภายใน 1 วินาที! ส่วนสต๊อปโมชั่นที่ทำอยู่นี้ภาพละ 4 วินาที น้อยกว่ากัน 56 เท่า ถ้าจะทำให้ได้ 14 FPS และให้เคลื่อนไหวอยู่สัก 1 นาที ก็จะหมายถึงต้องบันทึกภาพของหุ่นที่จับให้เคลื่อนไหวทีละน้อย ๆ รวม 840 ภาพ! เรื่องยากก็คือขยับหุ่นทีละน้อยนี่แหละครับ ซึ่งก็น่าทดลองดูว่าจะเป็นยังไง

แต่ผมก็ทำใจไว้แล้วละว่าอาจต้องรออีกหลายปี

วันอังคารที่ 16 เมษายน พ.ศ. 2556

การแสดง Mesh Plot สามมิติด้วย QtiPlot

ที่มาที่ไป
ในช่วงสามสี่เดือนที่ผ่านมามีภาระกิจเกี่ยวกับงานวิจัยอยู่ (กับเขาบ้าง -- และถูกขัดจังหวะตลอด) กล่าวโดยสังเขปงานวิจัยชิ้นนี้จะทำการวิเคราะห์สัญญาณเสียงแคนโดยใช้ Time-Frequency Analysis แบบ Modal Distribution การวิเคราะห์ทั้งหมดผมทำโดยใช้ Octave ผลการวิเคราะห์จะได้เมตริกซ์ M ซึ่งก็คือเมตริกซ์ Modal Distribution ที่แถวคือแกนความถี่และหลักคือแกนเวลา

ปัญหาของการใช้ Octave ก็คือผลการวิเคราะห์ซึ่งสามารถแสดงผลได้โดยใช้ Mesh Plot ด้วยคำสั่ง
>mesh(M);
จะใช้เวลาในการสร้างรูปนานมาก เนื่องจากเมตริกซ์ M โดยปกติแล้วจะมีขนาดใหญ่ นอกจากนี้แม้ว่าเราจะอดทนพอที่จะรอจนกว่า Octave จะพล๊อตให้เราเสร็จ พอเราจะวิเคราะห์เมชเราก็มักจะหมุนเมชไปมาเสมอ ๆ ซึ่งคำสั่ง mesh ของ Octave จะตอบสนองช้ามากจนไม่สามารถจะวิเคราะห์อะไรได้

ผมก็เลยลองค้นดูว่าใน Debian Repository จะมีอะไรให้ใช้บ้าง พบ QtiPlot ที่คิดว่าน่าจะใช้ได้ครับ การติดตั้งผมใช้ Synaptic ในการติดตั้งจึงจะไม่ลงรายละเอียด

QtiPlot ทำอะไรได้บ้าง? น่าจะหลายอย่างอยู่ แต่ที่ผมได้ทดลองใช้ด้วยตนเองก็คือ
  • พล๊อตกราฟ 2 มิติได้ โดยเราจะต้องเตรียมข้อมูลให้อยู่ในรูปตาราง เราสามารถกำหนดได้ว่าข้อมูลหลักไหนบ้างที่จะอยู่ในแกน x และข้อมูลหลักไหนบ้างที่จะอยู่ในแกน y
  • พล๊อตกราฟ 3 มิติได้ โดยเราจะต้องเตรียมข้อมูลให้อยู่ในรูปของเมตริกซ์ กล่าวคือให้แถวหมายถึงแกน x ให้หลักหมายถึงแกน y และข้อมูลในเซลต่าง ๆ ก็คือแกน z
  • กำหนดสี เส้น ฉลาก ชื่อแกน แบบอักษร ฯลฯ ได้
  • ส่งออกกราฟได้หลายรูปแบบ ที่ผมใช้ก็มี EPS และ PNG ครับ
ฟังคุณสมบัติมาพอสมควร ลองมาดูวิธีใช้ดูบ้างนะครับ

การพล๊อตกราฟ 2 มิติด้วยข้อมูลจาก Octave
QtiPlot รับข้อมูลในรูปแบบของไฟล์ข้อความด้วย เราจึงใช้วิธีบันทึก (Save) ข้อมูลเมตริกซ์จาก Octave ในรูปของไฟล์ข้อความครับ
  1. สมมติว่าเรามีข้อมูลที่จะอยู่ในแกน x ชื่อว่า V และข้อมูลที่จะอยู่ในแกน y ชื่อว่า I เราจะจัดให้ V และ I เป็นคอลัมน์เวคเตอร์ที่มีความยาวเท่ากัน จากนั้นเก็บข้อมูลทั้งสองนี้ลงในเมตริกซ์ตัวหนึ่ง สมมติให้ชื่อเป็น Data 
  2. จากนั้นเราก็บันทึก Data ลงในแฟ้มชื่อ Data.txt โดยใช้คำสั่ง save ของ Octave ซึ่งเราจะใช้คำสั่ง Octave ดังนี้ครับ
> % Prepare testing data
> V = [0:0.1:1';
> I = 0.0005*exp(V/0.2);
> % Prepare data for QtiPlot 
> Data = [V I];
> save -ascii Data.txt Data
เท่านี้ก็เตรียมข้อมูลเสร็จแล้ว ที่ฝั่ง QtoPlot เราก็ Import ข้อมูลเข้าได้ทางเมนู File -> Import -> Import Ascii ได้เลย ในหน้าต่างที่ใช้ Import ข้อมูลก็จะมีตัวเลือกต่าง ๆ ให้ เช่นการกำหนดแถว หลัก Ending ฯลฯ ดังรูปครับ
QtiPlot สามารถนำเข้าข้อมูลได้หลายรูปแบบ
ในการนำเข้าข้อมูลผู้ใช้สามารถกำหนดตัวเลือกการนำเข้าต่าง ๆ ได้
เมื่อนำเข้าข้อมูลแล้วข้อมูลจะอยู่ในรูปของตาราง (Table) ซึ่งเราเลือกได้อย่างอิสระว่าจะให้คอลัมน์ใดเป็นแกน x คอลัมน์ใดเป็นแกน y โดยการคลิ๊กขวาที่หัวของคอลัมน์ครับ
ผู้ใช้สามารถกำหนดได้ว่าคอลัมน์ใดจะเป็นแกนใด รวมทั้งกำหนดค่าอื่น ๆ เช่นฉลากและชื่อแกนได้ด้วย
เราใช้เมนู Plot ทำการพล๊อตกราฟได้ทันที รูปแบบของการพล๊อตก็รวมรูปแบบยอดนิยมเกือบทั้งหมด ทั้ง Line Scatter และ Pie แต่ทั้งนี้การจะพล๊อตกราฟได้นั้นจะต้องเลือกคอลัมน์ y ที่จะพล๊อตเสียก่อน ในการพล๊อตเราสามารถกำหนดองค์ประกอบของการพล๊อตได้ทุกอย่าง ตั้งแต่ชื่อของพล๊อต (Title) ฉลากข้อมูล (Legand) ชื่อแกนและช่วงแกน (Axis) ภาพข้างล่างนี้จะเป็นตัวอย่างการพล๊อตข้อมูลที่ผมเตรียมไว้ครับ
ซึ่งกราฟที่พล๊อตสามารถส่งออกเป็นไฟล์กราฟิกได้หลายรูปแบบโดยใช้เมนู File -> Export Graph ครับ

แต่ถ้า QtiPlot จะทำได้แค่นี้ ผมใช้ Octave เอง หรือไม่ก็ tikz ดีกว่า อย่างที่กล่าวไว้ข้างต้นครับ ผมต้องหาเครื่องมือเพื่อทำ Mesh Plot ของข้อมูลขนาดใหญ่มาก ซึ่งจะเล่าให้ฟังในหัวข้อถัดไป

การพล๊อดกราฟ 3 มิติด้วยข้อมูลจาก Octave
วิธีการก็คล้ายกันครับ ผมจะแสดงตัวอย่างข้อมูล บันทึกข้อมูลที่จะพล๊อตลงในไฟล์ข้อความ และนำเข้าไฟล์ข้อความเข้าไปใน Qtiplot แล้วก็พล๊อตข้อมูลเป็นกราฟ 3 มิติ

ลองดูตัวอย่างการเตรียมข้อมูลนะครับ
> % Prepare the test data
> x = 1:10;
> y = 1:10;
> [xx,yy] = meshgrid(x,y);
> Data = sin(xx.+yy)./sqrt((xx.^2)+(yy.^2));
> % Prepare data for QtiPlot
> save -ascii Data.txt Data
การนำข้อมุลเข้าสู่ QtiPlot จะทำเช่นเดียวกันกับข้อมูล 2 มิติครับ แต่ต้องแปลงตาราง (Table) ให้เป็นเมตริกซ์ (Matrix) เสียก่อนโดยใช้เมนู Table -> Convert to Matrix -> Direct เราจะได้หน้าต่างเมตริกซ์ของข้อมูลชุดนี้มา เมื่อเราอยู่ในหน้าต่างเมตริกซ์ เมนูบาร์จะเปลี่ยนเป็นเมนูของเมตริกซ์ เราจะพล๊อตกราฟได้ตอนนี้โดยเลือกเมนู 3D Plot -> 3D Wire Surface ก็จะได้กราฟ 3 มิติสำหรับแสดงผลเมตริกซ์ครับ แน่นอนว่าเราสามารถตั้งสเกลแกนต่าง ๆ ได้ ตั้งชื่อแกนและชื่อพล๊อตได้ ปรับสีได้
พล๊อตข้อมูล Data ในแบบ 3 มิติ
ก็ถือเป็นการแนะนำโปรแกรมสำหรับพล๊อต 3 มิติสำหรับข้อมูลจำนวนมากนะครับ ถ้าข้อมูลไม่มากใช้ Octave นั่นแหละสะดวกดี สำหรับผม ๆ ใช้ QtiPlot สำหรับการแสดงผลการวิเคราะห์สัญญาณเสียงแคนครับ ขนาดของข้อมูลคือ 427x601 จุดครับ ผมเอาพล๊อตของข้อมุลบางส่วนมาให้ดูด้วย
ผลการวิเคราะห์เสียงแคน เลือกมาหลอดเดียวนะครับไม่ใช่ทั้งเต้า

วันพฤหัสบดีที่ 18 ตุลาคม พ.ศ. 2555

สังเคราะห์เสียงฆ้องบน Android ด้วย libpd ตอนที่ 1

หลังจากหัดเขียนโปรแกรมบน Android และทดลองเขียนโปรแกรมฆ้องวงขึ้นมา ก็รู้สึกถึงข้อจำกัดของการใช้เสียงฆ้องที่บันทึกไว้ล่วงหน้าซึ่งก็คือ
  1. มีข้อจำกัดด้านคุณภาพของการบันทึกเสียงและ
  2. ไม่สามารถปรับค่าความถี่และอัตราลดทอนของเสียงได้
แต่การสังเคราะห์เสียงโดยใช้ภาษา Java โดยตรงดูจะไม่ใช่ทางเลือกที่ดีนัก ยิ่งไม่ใช่ทางเลือกที่ดีสำหรับคนที่ไม่เชี่ยวชาญ Java อย่างผม หลังจากที่เสาะหากรรมวิธีเหมาะ ๆ ได้สักพักก็เจอเครื่องมือด้านการสังเคราะห์เสียงจำนวนหนึ่งคือ
ผมได้ทดลองใช้ Chuck กับ Python เพื่อสังเคราะห์เสียงบน Linux ดูแล้วก็ใช้งานได้สะดวกดี แต่ Chuck ไม่มีเครื่องมือที่จะเชื่อมต่อกับ Java และ Android (หรือมีแต่ผมหาไม่เจอ) ส่วน Csound นั้นผมไม่เคยใช้ ค้นดูก็ไม่เจอเครื่องมือที่จะเชื่อมต่อกับ Java และ Android เช่นกัน

สำหรับ puredata นั้นเดิมผมเคยยอมแพ้มันมาแล้วหนหนึ่งด้วยเหตุว่าเขียนแพตช์ (Patch) ของ puredata ไปแล้วก็เอาไปใช้ในโปรแกรมอื่นเหมือน Chuck ไม่ได้...จนกระทั่งผมได้พบกับ libpd จึงได้ทราบว่าผมคิดผิด

อันที่จริง puredata สามารถสื่อสารกับภาษาโปรแกรมอื่น ๆ ได้ผ่านทาง libpd ขั้นตอนการพัฒนาโปรแกรมโดยใช้ libpd จะเป็นดังนี้
  1. ผู้พัฒนาจะสร้างแพตช์ puredata ขึ้นมาก่อน โดยกำหนดชื่อตัวแปรควบคุมไว้แทนอินเลต
  2. เปิดแพตช์ที่สร้างขึ้นจากคำสั่ง openPatch
  3. ส่ง Bang Float Message ผ่านคำสั่ง sendBang sendFloat และ sendMessage ไปยังแพตช์เป้าหมายตามลำดับ
เนื่องจากมีขั้นตอนที่เกี่ยวข้องแยกเป็น 2 ส่วนใหญ่ ๆ ที่ไม่เกี่ยวข้องกันก็คือส่วนการสังเคราะห์เสียงด้วย pd เป็นส่วนหนึ่ง และการตั้งค่าและเรียกใช้ libpd ในแอนดรอยด์เป็นอีกส่วนหนึ่ง ในตอนนี้จึงขอบันทึกไว้เฉพาะส่วนการสังเคราะห์เสียงก่อน

การสังเคราะห์เสียงฆ้องด้วย pd
จากการวิเคราะห์เสียงฆ้องในเบื้องต้นพบว่าคุณลักษณะพื้นฐานที่โดดเด่นของเสียงฆ้องคือองค์ประกอบ Exponentially Decayed Sinusoid ซึ่งสามารถสร้างได้โดยแพตช์ดังแสดงในรูป
andgong.pd
อินเลตของแพตช์นี้จะเป็นค่าความถี่ของลูกฆ้อง เมื่อมี float เข้ามาทางอินเลต bang จะถูกกระตุ้นและจะสร้างอาเรย์ของตัวแปรเวลา t ขึ้นมา ตัวแปรเวลานี้จะคูณเข้ากับอัตราการลดทอนของเสียงฆ้องซึ่งในที่นี้เป็น -2 เมื่อข้อมูลนี้ผ่านออบเจ็กต์ [exp~] ก็จะเป็นฟังก์ชัน
amath f(t)=e^{-2t} endamath
ส่วนตัวเลขความถี่ที่ป้อนเข้ามาแต่แรกก็จะไปกระตุ้น [osc~] เพื่อให้สร้างสัญญาณไซนูซอยด์ออกมา เมื่อนำมาคูณกับเอกโพเนนเชียลในตอนแรกและคูณกับ 0.3 ก่อนส่งออกทางเอาต์เลตจะทำให้ได้ฟังก์ชัน
amath g(t) = 0.3 e^{-2t} cos(2\pi f t) endamath
จะเป็นเสียงฆ้องลูกทวนหรือว่าลูกยอดก็แล้วแต่ว่าความถี่ที่ป้อนเข้าทางอินเลตนั้นเป็นเท่าใด

แต่ [timearray] ไม่ใช่ออบเจกต์มาตรฐานของ pd แต่เป็นออบเจกต์ที่ผมสร้างขึ้นมาเองเพื่อสร้างตัวแปร t ที่วิ่งจาก 0 ถึง 5000 ในเวลา 5 วินาที (ขั้นละ 1 มิลลิวินาที) ทุกครั้งที่มีการกระตุ้นออบเจกต์ด้วย [bang( ซึ่งกลไกของ [timearray] แสดงดังรูปต่อไปนี้
timearray.pd
เมื่อมี [bang( เข้ามาทางอินเลต ข้อความ 0 จะถูกกระตุ้นเพื่อส่งให้ [line~] กระโดดจากค่าใด ๆ ก็ตามขณะนั้นไปที่ [0( ทันที หลังจากนั้น 1 มิลลิวินาที [bang( ที่ถูกหน่วงเวลาไว้ก็จะกระตุ้นข้อความ [5 5000( เพื่อส่งให้ [line~] ทำให้เอาต์พุตของ [line~] เปลี่ยนแปลงจาก 0 ไปเป็น 5 ภายในเวลา 5000 มิลลิวินาที นั่นหมายความว่าเอาต์เลตของแพตช์นี้ก็คือค่าเวลาเป็นวินาทีขั้นละ 1 มิลลิวินาทีเป็นเวลา 5 วินาทีนั่นเอง

เนื่องจาก libpd อนุญาตให้มีแพตช์ Instance เดียว เราก็เลยต้องสร้างลูกฆ้องทั้ง 16 ลูกในแพตช์โดยให้ฆ้องแต่ละลูกถูกกระตุ้นโดยตัวแปร h01 - h16 ด้วยตัวเลขค่าความถี่
gongwong.pd
แม้ว่าจะตีฆ้องทีละลูกหรืออย่างมาก 2 ลูก เพื่อให้การเชื่อมต่อสัญญาณกับ [dac~] ไม่ติดขัดเพราะเชื่อมกับอินพุตมากเกินไปเราเลยใช้ [+~] รวมสัญญาณจากฆ้องแต่ละลูกเข้าด้วยกัน แต่ Hot Inlet คืออินเลตทางซ้ายเท่านั้น เราเลยต้องให้ตัวแปรความถี่ลูกฆ้องลูกที่ 2 - 16 กระตุ้น [bang( เพื่อกระตุ้น Hot Inlet ของ [+~] ตัวแรกด้วย นอกจากนี้ก่อนจะส่งสัญญาณเสียงออกมาทาง [dac~] เราจะป้องกันองค์ประกอบไฟตรง (DC Component) โดยใช้ตัวกรองความถี่สูงผ่าน [hip~] โดยตั้งค่าความถี่ตัดไว้ที่ 1 เฮิร์ทซ และป้องกันการทำงานผิดพลาดของ libpd โดยการขริบสัญญาณขาออกไว้ให้ไม่เกิน +/- 1

เราสามารถทดสอบแพตช์ gongwong.pd ใน puredata ได้โดยการเปลี่ยน [r h01] ถึง [r h16] ให้เป็นข้อความ [xxx01( - [xxx16( รวม 16 ข้อความเมื่อ xxx01 - xxx16 คือค่าความถี่เสียงที่เราต้องการ และทดลองฟังเสียงโดยการคลิ๊กที่ข้อความแต่ละข้อความนั้น ๆ

เมื่อเราเตรียมแพตช์ของเราเรียบร้อยแล้ว ในตอนต่อไปเราจะมาดูว่าจะสามารถเรียกใช้แพตช์นี้ผ่าน libpd เพื่อเขียนโปรแกรมสำหรับแอนดรอยด์ได้อย่างไร

วันพฤหัสบดีที่ 13 กันยายน พ.ศ. 2555

การติดตั้ง Arduino Sketch ลงในไมโครคอนโทรลเลอร์


ผมสนุกสนานกับการพัฒนาโครงงานเล็ก ๆ น้อย ๆ โดยใช้ Arduino มาระยะหนึ่ง สิ่งที่รบกวนจิตใจมาตลอดก็คือเมื่อจะพัฒนาโครงงานใหม่ ผมจะต้องรื้อโครงงานเก่าเพื่อนำบอร์ด Arduino ออกมาใช้ใหม่เสมอ

จนกระทั่งมีนักศึกษาทักว่าถ้าต้องติดตั้งบอร์ด Arduino ลงไปในโครงงานทุกคราวไปมันจะไม่สิ้นเปลืองไปหน่อยหรือ? คิดในมุมกลับก็คือถ้ามันไม่มีวิธีที่ประหยัดกว่านี้ การพัฒนาชิ้นงานด้วย Arduino ก็ไม่น่าจะได้รับความนิยมกว้างขวางขนาดนี้หรอก เออแฮะ! นั่นก็จริง

เมื่อคิดได้ดังนั้นแล้วก็เลยทำการค้นคว้าข้อมูลอินเตอร์เนตดู จึงพบว่าโครงการ Arduino มีความสามารถที่จะโปรแกรม Sketch ลงไปในไอซีไมโครคอนโทรลเลอร์เพื่อนำไปใช้แบบเดี่ยว ๆ (Standalone) ได้ด้วย ทำให้หลังจากที่เราพัฒนา Sketch บนบอร์ดทดลอง Arduino และทดลองวงจรแล้วเราสามารถติดตั้ง Sketch นั้นกับไอซีไมโครคอนโทรลเลอร์เปล่า ๆ ก็ได้ (เข้าใจผิดมาตั้งนาน) จากนั้นจึงติดตั้งไมโครคอนโทรลเลอร์นั้นลงในวงจรได้เลยโดยที่ไม่ต้องเสียสละบอร์ด Arduino ของเราลงไปในทุกโครงการ ในการนี้เราจำเป็นจะต้องมีอุปกรณ์หลัก 2 สิ่งคือ
  1. บอร์ด Arduino รุ่นใดก็ได้เพื่อใช้เป็นตัวโปรแกรม (Programmer) และ
  2. ไอซีไมโครคอนโทรเลอร์ตระกูล AVR ที่จะใช้แทนบอร์ด Arduino
ไอซีไมโครคอนโทรลเลอร์ที่จะใช้จะต้องสอดคล้องกับบอร์ดที่เราจะเอาไอซีไปใช้แทนด้วย รายการชื่อบอร์ดและไอซีไมโครคอนโทรลเลอร์ที่เข้าคู่กันน่าจะหาได้จากเว็บไซต์ของ Arduino เอง แต่ผมมีข้อเสนอแนะว่าใช้ไอซีพื้น ๆ กับบอร์ดพื้น ๆ นี่แหละ ดีที่สุดเพราะมันจะเป็นไอซีและบอร์ดที่มีคนลองมาแล้วว่าใช้ได้แน่นอนไม่มีปัญหา รายการที่ผมพอทราบว่าใช้การได้ก็มีดังนี้ครับ
  • Diecimila (ET-EASY168, POP-168) ใช้ Atmega168
  • Arduino Mega (ET-EASYMEGA1280) ใช้ Atmega1280
  • Arduino NG w/ Atmega168 ใช้ Atmega168
  • Arduino NG w/ Atmega8 ใช้ Atmega8 <=== ผมใช้ตัวนี้เพราะหาไอซี Atmega8 ได้
กระบวนการนี้มีขั้นตอนสำคัญ 2 ส่วนคือ
  1. ทำให้บอร์ด Arduino ของเรากลายเป็นตัวโปรแกรม
  2. ติดตั้ง Arduino Sketch ของโครงงานของเราลงในไอซี AVR ตัวนั้น ๆ
ที่ผมทดลองทำดูเองนั้น ผมมีบอร์ด ET-EASYMEGA1280 อยู่ตัวหนึ่งและมีไอซี Atmega8 อยู่ตัวหนึ่ง

ทำให้บอร์ด Arduino เป็นตัวโปรแกรม
ในโปรแกรม Arduino IDE รุ่นล่าสุด (1.0.1) จะมี Sketch ตัวอย่างชื่อ ArduinoISP.ino ติดตั้งมาแล้ว โดยอยู่ที่เมนูน File -> Examples -> ArduinoISP Sketch นี้จะทำหน้าทึ่ทำให้บอร์ด Arduino ของเราทำตัวเป็นตัวโปรแกรม
  • ให้เปิด Sketch ArduinoISP ขึ้นมา
  • ให้เลือกบอร์ดจากเมนู Tools -> Board ให้ตรงกับบอร์ดที่เราจะใช้เป็นตัวโปรแกรม ผมจะใช้ ET-EASYMEGA1280 ก็เลือกบอร์ดให้เป็น Arduino Mega
  • สั่งอัพโหลด Sketch
Arduino IDE จะคอมไพล์ Sketch และอัพโหลด ArduinoISP ขึ้นไปที่บอร์ด Arduino เมื่อเสร็จสิ้นบอร์ด Arduino ของเราก็จะกลายเป็นตัวโปรแกรมแล้ว
 

ใช้บอร์ด Arduino เป็น ISP Programmer
หลังจากอัพโหลดเสร็จ บอร์ดของเราก็จะเป็น ISP Programmer แล้ว เราสามารถติดตั้ง Sketch ของเราลงบนไอซีไมโครคอนโทรลเลอร์ได้แล้ว การเชื่อมต่อไอซีกับบอร์ด Arduino ของเราก็ให้ดูตามซอร์สโค้ดของ ArduinoISP คือกรณีของผมซึ่งใช้ ET-EASYMEGA1280 ก็ให้ต่อ
  • ขา 53 ของบอร์ดเข้ากับขา Reset ของไอซี (ขา 1)
  • ขา 51 ของบอร์ดเข้ากับขา MOSI ของไอซี (ขา 17)
  • ขา 50 ของบอร์ดเข้ากับขา MISO ของไอซี (ขา 18)
  • ขา 53 ของบอร์ดเข้ากับขา SCK ของไอซี (ขา 19)
ต่อตัวต้านทานสัก 1 k ระหว่างขา Reset กับ Vcc นอกจากนี้อย่าลืมจ่าย Vcc และ Gnd ให้กับ AVcc และ AGnd ด้วย สุดท้ายใช้คริสตัล 16 MHz และตัวเก็บประจุขนาด 18 pF คู่หนึ่งเพื่อสร้างสัญญาณนาฬิกาให้กับไอซี เราสามารถใช้ Vcc และ Gnd ของบอร์ด Arduino จ่ายให้กับไอซี Atmega8 ได้


สมมติว่าเราจะทดลองติดตั้ง Sketch ชื่อ Blink จากตัวอย่างในโปรแกรม Arduino IDE ลงใน Atmega8 ก็ให้เปิด Sketch ตัวอย่างนั้นขึ้นมา
  • เลือกบอร์ดเป็น Arduino NG w/Atmega8 เพราะมีไอซึ Atmega8 อยู่
  • สั่ง File -> Upload using Programer หรือกด Crtl+Shift+U
Arduino IDE จะคอมไพล์และอัพโหลด Sketch ขึ้นไปบน Atmega8 ที่ต่อไว้ผ่าน ET-EASYMEGA1280 ของเรา

เพิ่มเติม
ข้อมูลจากเว็บ Arduino เองและจากแหล่งอื่น ๆ เช่น http://www.ayarafun.com/2009/04/upload-arduino-with-avrdude-gui/ ระบุตรงกันว่าสามารถอัพโหลดโปรแกรมได้โดยไม่ต้องมีบูตโหลดเดอร์ (Bootloader) ก็ได้

แต่จากการทดลองที่ทำเองมันทำไม่ได้ผล ผมทดลอง 2 แบบครับคือ
  • ติดตั้งบูตโหลดเดอร์ลงใน Atmega8 ก่อน แล้วค่อยอัพโหลดโปรแกรม Blink ขึ้นไป Atmega8 ทำงานได้ตามที่คาดหวัง
  • ไม่ติดตั้งบูตโหลดเดอร์ลงใน Atmega8 อัพโหลดโปรแกรม Blink ขึ้นไปเลย Atmega8 ทำงานผิดปกติ คือไฟกระพริบแต่ว่าด้วยความถี่ต่ำกว่าที่เขียนโปรแกรมมาก
ยังไม่ทราบแน่ชัดว่าเป็นเพราะอะไร แต่ตอนนี้ต้องรีบทำงาน ก็เลยใช้วิธีติดตั้งบูตโหลดเดอร์ลงไปให้มันทำงานได้เสียก่อน เรื่องอื่นค่อยว่ากัน

วิธีการติดตั้งบูตโหลดเดอร์
หลังจากที่ติดตั้งโปรแกรม ArduinoISP บนบอร์ด ET-EASYMEGA1280 แล้ว ต่อวงจรเพื่อติดตั้งบูตโหลดเดอร์เหมือนกับการอัพโหลดโปรแกรมเข้า Atmega8 ตามรูปข้างบนนั่นแหละ

หลังจากเลือกบอร์ดให้เป็น Arduino NG w/ Atmega8 (เพราะผมใช้ Atmega8) จากเมนู Tools -> Board แล้วก็เลือกตัวโปรแกรมเมอร์ให้เป็น Arduino as ISP จากเมนู Tools -> Programmer

เมื่อเสร็จก็สั่งติดตั้งบูตโหลดเดอร์ลงใน Atmega8 ด้วย Tools -> Burn Bootloader ก็เสร็จเรียบร้อยครับ หลังจากนี้จะติดตั้งโปรแกรมอะไรก็ทำได้เลย


แหล่งข้อมูล
http://arduino.cc/en/Tutorial/ArduinoISP
http://arduino.cc/en/Hacking/PinMapping
http://arduino.cc/en/Tutorial/ArduinoToBreadboard

วันพุธที่ 22 สิงหาคม พ.ศ. 2555

ดูภาพหน้าจอของ Android Tablet บน PC

เมื่อตอนผมหัดเขียนโปรแกรมบนแอนดรอยด์นั้นก็ตัดสินใจซื้อ Tablet ราคาถูกมาเครื่องหนึ่ง เป็นยี่ห้อง Air Pad รุ่น DS820A ที่เลือกยี่ห้อนี้เพราะมันไม่แพงและมีตัวแทนจำหน่ายรับผิดชอบชัดเจน

Tablet เครื่องนี้มีข้อโดดเด่นอยู่อย่างหนึ่งคือมีช่องต่อพ่วงอุปกรณ์ครบ มี USB ใหญ่ USB เล็ก HDMI 3.5 mm Audio Jack SD Card ขาด VGA ก็จะใช้เป็นคอมพิวเตอร์เครื่องหนึ่งได้แล้ว

แต่คงเพราะเป็น Tablet จึงมีปุ่มควบคุมอยู่น้อย มีปุ่ม Volume ปุ่มเรียกเมนู และปุ่ม ESC แค่นี้ ที่เหลือต้องควบคุมผ่านหน้าจอระบบสัมผัสทั้งหมด

อะไรจะเกิดขึ้นถ้ามีอุบัติเหตุทำให้การตั้งค่าความสว่างหน้าจอเป็นศูนย์!??

จอมันก็มืดสิครับ ผมเคยเจอปัญหานี้หนหนึ่งเมื่อสักสองวันก่อนนี่เอง คือไปลงโปรแกรมประหยัดแบตเตอรีแล้วอ่าน UI ไม่เข้าใจไปตั้งค่าให้ประหยัดพลังงานโดยปิดหน้าจอ มืดสนิทไปหมด เราก็นึกว่าเครื่องดับเลย Reset มันซะ ปรากฏว่าเครื่องก็ Restart ตามปกตีมี Splash Screen มาตามลำดับ ๆ พอจบลำดับจอก็มืดเหมือนเดิม เพราะโปรแกรมประหยัดแบตเตอรีมันคุมไว้ ทำไงดีล่ะทีนี้

ก็เลยคิดว่ามันน่าจะมีการควบคุม Android Tablet ผ่าน PC ได้สักทางล่ะน่า หลังจากค้นหาอยู่ไม่นาน (Thank you Google!) ก็พบหน้าเว็บนี้ครับ How to Remote View and Control Your Android Phone ซึ่งอธิบายว่าเราสามารถดูภาพหน้าจอของ Android Tablet ได้โดยใช้เครื่องมือ 3 อย่างคือ
  1. โปรแกรม ADB ซึ่งได้จาก Android SDK อยู่ในไดเรคทอรีย่อย platform-tools
  2. สาย USB
  3. โปรแกรม Androidscreencast ซึ่งเป็นโปรแกรมภาษาจาวา
ขั้นตอนก็ขอเรียบเรียงเป็น 2 ส่วนนะครับ คือส่วนเตรียมการและส่วนใช้งาน ส่วนเตรียมการคือทำหนเดียวแล้วไม่ต้องทำอีก ส่วนใช้งานก็คือทำทุกครั้งที่ใช้งาน

ส่วนเตรียมการ
  • ติดตั้ง JAVA JRE เวอร์ชัน 5 ขึ้นไป ถ้ายังไม่มี (แต่น่าจะมีกันหมดแล้วล่ะมั้ง) เอาไว้รันโปรแกรม Androidscreencast
  • ติดตั้ง Android SDK รุ่นล่าสุด เพื่อจะได้ใช้ ADB ได้
  • ติดตั้งโปรแกรม Androidscreencast โดยการดาวน์โหลดโปรแกรมมาแล้วเก็บไว้ที่ใดสักที่หนึ่งที่ไม่เกะกะ ตรงไหนก็ได้ครับผมเก็บไว้ใน platform-tools นั่นแหละ ไม่ต้อง Setup ไม่ต้อง Install
สำหรับ Debian และ Ubuntu อาจารย์รุจชัยเคยมาบรรยายที่ KKLUG ว่าจะต้องผูกให้ระบบรู้จักกับ Tablet เสียก่อนโดย
สร้างแฟ้มข้อความ (Text File) ชื่อ 52-android.rules ไว้ใน /etc/udev/rules.d/ (แน่นอนว่าต้องผ่าน su นะครับ) โดยในแฟ้มจะมีข้อความว่า
SUBSYSTEM=="usb",SYSFS{idVendor}=="xxxx",ATTRS{idProduct}="yyyy",MODE="666"
ทั้งนี้ xxxx คือ Vendor ID และ yyyy คือ Product ID ที่สามารถทราบได้โดยใช้คำสั่ง
lsusb
ซึ่งจะแสดงรายการอุปกรณ์ที่ต่อพ่วงกับ PC ของเราทาง USB ดังนี้
Bus zzz Device zzz: ID xxxx:yyyy Product Name
เมื่อสร้างแฟ้มข้อความ 52-android.rules แล้วตรวจให้แน่ใจว่าโหมดของแฟ้มคือ 644 หลังจากนั้นเพื่อให้การเปลี่ยนแปลงเกิดผลทันทีก็สั่งให้บริการ ABD เริ่มต้นใหม่โดย
> ./adb kill-server
> ./adb start-server
มาถึงจุดนี้ก็ถือว่าพร้อมใช้งาน ADB ผ่านพอร์ด USB แล้ว

ส่วนใช้งาน
  • ต่อ Android Tablet เข้ากับพอร์ด USB ของ PC ตอนนี้ Tablet อาจจะถามว่าจะเปิดที่เก็บข้อมูลไหม ไม่ต้องตอบครับ Exit ออกมาเลย ถ้าเปิดที่เก็บข้อมูล PC จะมองเห็น Tablet เราเป็น USB Flashdrive ตัวหนึ่งเท่านั้น ถ้าทำต่อมาจากขั้นเตรียมการก็ข้ามขั้นนี้ไปเลย
  • เรียกใช้โปรแกรม ADB ซึ่งใน Debian ของผมจะใช้ Command Line
> ./adb devices
ถ้าเชื่อมต่อได้ก็จะมีข้อความขึ้นมาที่ Prompt ดังนี้
* daemon not running. starting it now on port xxxx *
* daemon started successfully *
List of devices attached
xxxxxxxxxxxxxxxx device
  • เรียกใช้โปรแกรม androidscreencast.jnlp
> jawaws androidscreencast.jnlp
เราจะเห็นหน้าจอของ Tablet ของเราอยู่ในหน้าต่างของโปรแกรม androidscreencast.jnlp นี่แหละครับ  จะบันทึกเป็นวิดีโอก็ได้ ในระบบของผมเขาจะบันทึกให้เป็นแฟ้ม MOV ดังตัวอย่างข้างล่างนี้ครับ

หรือจะบันทึกภาพหน้าจอก็ใช้เครื่องมือบันทึกภาพหน้าจอของ Gnome ก็ได้

เมื่อเราเห็นหน้าจอของ Tablet ของเราทางจอคอมพิวเตอร์ (ตอนนี้จอ Tablet มันดำอยู่) ก็พอจะหาทางควบคุมความสว่างได้ แต่ขอบอกให้ชัด ๆ ก่อนว่าไม่ใช่ว่าควบคุม Tablet จาก PC แต่ให้ PC แสดงหน้าจอของ Tablet เฉย ๆ เรายังต้องใช้ Touch Screen ของ Tablet ในการควบคุมอยู่ดี

ในเว็บแจ้งว่าหากต้องการควบคุม Tablet ผ่าน PC แบบเต็มตัวจะต้อง Root Tablet ตัวนั้นเสียก่อน ผมยังไม่กล้าพอครับ

สุดท้ายรอดตาย ปรับความสว่างหน้าจอให้พ้นความืดมาได้ แต่ดูจะเป็นวิธีแก้แบบยุ่งยากไปหน่อย อันที่จริงผมก็คิดนะว่ามันน่าจะมีวิธีแก้ที่ง่ายกว่านี้ เช่นมีปุ่มพิเศษกดแก้ไขได้เลย หรือไม่ก็อย่าให้มีการตั้งค่าหน้าจอให้ความสว่างเป็นศูนย์ไปตั้งแต่แรกน่าจะดีกว่านี้ ท่านใดทราบวิธีแก้แบบอื่น ๆ ผมยินดีรับคำแนะนำครับ