วันอาทิตย์ที่ 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 ตัวนั้นเสียก่อน ผมยังไม่กล้าพอครับ

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

วันเสาร์ที่ 28 กรกฎาคม พ.ศ. 2555

เน็ต 3BB กับ Debian

ใช้ 3BB มาหลายเดือนแล้ว ใช้งานได้ดีไม่มีปัญหา แต่.....

อันที่จริงแล้วผมมีปัญหากับการเข้าถึงอินเตอร์เนตผ่าน 3BB ตั้งแต่วันแรก นั่นคือเข้าเว็บไม่ได้ แต่เมื่อตอนนั้นคิดว่าคงเป็นปัญหาเรื่อง DNS ก็เลยไปใช้ Google DNS คือ 8.8.4.4 และ 8.8.8.8 แทน ซึ่งก็ใช้ได้ดีมาตลอดจนกระทั่งเมื่อ 2 - 3 วันมานี้จู่ ๆ ก็เข้าเว็บบางเว็บไม่ได้!


บางเว็บที่เข้าได้คือ google.com และเว็บต่างประเทศบางเว็บ ส่วนเว็บที่เข้าไม่ได้ส่วนใหญ่เป็นเว็บในไทย ตั้งแต่ sanook.com ไปจนถึง 3bb.co.th เอง ยกเว้น pantip.com เอาไงดีล่ะเรา...

มีคนบอกว่าให้เปลี่ยนกลับมาใช้ DNS ของ 3BB ก็ลองเปลี่ยนกลับดู แล้วลองใช้ dig หรือ nslookup ตรวจสอบดูว่า DNS ทำงานได้หรือไม่ ก็ปรากฏว่า DNS ไม่ว่าจะเป็นของ Google หรือของ 3BB ก็ทำงานได้ดี คือแสดงเลขไอพีของเว็บนั้น ๆ ได้ทุกเว็บ ไม่มีปัญหาเลยสักเว็บเดียว แสดงว่าปัญหาไม่ใช่ DNS แล้ว

พอได้เลขไอพีมาก็ลอง ping ดู ปรากฏว่าไม่เวิร์ก ฝ่ายเทคนิคของ 3BB บอกว่า ping ไม่เวิร์กเพราะหลายเว็บเขาบล๊อก ping เราก็เลยใช้ ping ตรวจสอบไม่ได้ แต่พอดีทราบว่าเว็บของภาควิชาฯ ไม่ได้บล๊อก ping ก็เลยลอง ping ดู ก็ปรากฏว่าเจอ แต่ก็เข้าเว็บภาควิชาไม่ได้

เอ...หรือว่าเรามีปัญหาการสื่อสาร ลอง ftp เข้าไปที่เซิฟเวอร์ของภาควิชาสิ...ก็เข้าได้ ลองเข้าเว็บภาควิชาสิ...เข้าไม่ได้แฮะ

มันไปติดที่ไหนนะ? สงสัยก็เลยใช้ traceroute ติดตามการสื่อสารดูว่ามันไปติดที่ไหน ปรากฏว่ามันก็ออกไปจนถึง 3bb นั่นแหละ แล้วก็ติดแหงกอยู่ที่นั่น ว่าแต่ว่าทำไมล่ะ ทำไมบางเว็บเข้าได้บางเว็บเข้าไม่ได้ และยืนยันแล้วว่าไม่ใช่ปัญหา DNS ด้วย

คิดไปคิดมาเห็นในหน้าต่าง Interface Config ว่ามีตัวเลือกของ IPv6 คิดว่ายังไม่น่าจะได้ใช้ก็ Disable มันซะ ลองเข้าเว็บอีกที...ยังไม่เวิร์ก แต่สัญชาตญาณบอกว่ามันน่าจะเป็นเรื่อง IPv6 นี่แหละ

ในเมื่อ DNS ไม่ใช่ปัญหา การเชื่อมต่อไม่ใช่ปัญหา ftp ได้ ปัญหาอาจอยู่ที่เบราเซอร์ เลยลองค้นคีย์เวิร์ด Firefox กับ IPv6 ดูจึงได้พบว่ามีหลายคนในโลกเจอปัญหาเข้าเว็บบางเว็บไม่ได้เหมือนกัน และทางแก้คือ Disable IPv6 ใน Firefox ซะ เอาล่ะ ดูจะมีความหวังอยู่บ้าง

วิธีการคือ พิมพ์ about:config ลงในช่อง URL Firefox จะเตือนเราก่อนว่าการแก้ไขตรงนี้อาจทำให้ Firefox ทำงานผิดปกติได้ เราก็รับคำเตือนนั้นเสีย แล้วค้นหา Field ชื่อ network.dns.disableIPv6 โดยใช้ Filter ที่ต้องใช้ Filter เพราะ Field มันเยอะมาก และเราก็ไม่อยากพลั้งพลาดไปเปลี่ยนค่าสำคัญอื่น ๆ โดยไม่ตั้งใจ เมื่อค้นเจอ network.dns.disableIPv6 แล้วก็ตั้งค่าให้เป็น TRUE เสีย (เดิมเป็น FALSE)

ปรากฏว่าใช้ได้ครับ! เข้าเว็บทุกเว็บได้ตามปกติเลย เนื่องจากเคยได้ยินว่ามีหลายคนมีปัญหาคล้าย ๆ กันอย่างนี้จึงขอบันทึกไว้เพื่อเป็นประโยชน์ในภายหน้า

สรุปว่าปัญหาอย่างนี้ทำให้ประสบการณ์การใช้ Linux มากขึ้น ได้เรียนรู้มากขึ้น คำสั่งต่าง ๆ ทั้ง dig nslookup ping traceroute แม้กระทั่ง route table ซึ่งก่อนหน้านี้ไม่รู้จัก ไม่ใด้ใช้เลยก็ได้ค่อย ๆ ทำความรู้จักกับมันขึ้นมา ทำให้มีความเข้าใจระบบเครือข่ายมากขึ้น ก็คงเหมือนอย่างภาษิตโบราณเขาว่า มารบ่มี บารมีบ่เกิด กระมัง

วันเสาร์ที่ 19 พฤษภาคม พ.ศ. 2555

การใช้ Calc ตัดเกรดนักศึกษา

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

ผมยอนใจอ่อนสอนเองไม่ตำหนิว่าเป็นความผิดของนักเรียนหรอก แต่เอาเถอะ บันทึกไว้เสียหน่อยก็แล้วกันว่าจะสอนยอมภาคฤดูร้อนเป็นครั้งสุดท้ายแล้ว อย่างไรเสียแม้ว่าการสอนจะเป็นความรับผิดชอบของเรา แต่การเรียนก็เป็นความรับผิดชอบส่วนตนของนักศึกษา จะเรียนตกเรียนหล่นในเทอมปกติแล้วจะมาจับตัวเองเป็นตัวประกันในเทอมฤดูร้อนนั้นไม่ได้ และการสอนภาคฤดูร้อนก็ไม่ใช่หน้าที่รับผิดชอบของอาจารย์นะ (มหาวิทยาลัยกำหนดงานอาจารย์ในช่วงนี้ไว้ให้แล้วครับ - ไม่ใช่ว่าจะว่าง) งานของใครก็งานของมันนะครับนักเรียน รับผิดชอบงานในส่วนของตัวเองด้วย

บ่นพอแล้ว อยากจะแบ่งประสบการณ์การใช้ Calc ของ LibreOffice ในการตัดเกรดโดยกึ่งอัตโนมัติสู่กันฟังสักนิดหนึ่ง วิธีที่นำมาแบ่งปันนี้ได้รับแนวทางมาจาก วิธีการคำนวณคะแนนและเกรด

การตัดเกรดแบบกึ่งอัตโนมัติที่ว่านี้หมายถึงให้อาจารย์เป็นคนกำหนดช่วงคะแนนสำหรับแต่ละเกรดในตารางเองนะครับ จากนั้นให้ Calc รวมคะแนนของนักเรียนแต่ละคนและจำแนกตามช่วงคะแนนว่าเด็กแต่ละคน ๆ นั้นจะได้เกรดเท่าไร ซึ่งทำได้ดังนี้ครับ

ทำตารางคะแนนของนักเรียนขึ้นมาเสียก่อน จะมีคะแนนเท่าใด สอบเท่าใดก็ว่ากันไป แต่สุดท้ายให้รวมให้ได้ 100 คะแนนเต็ม ดังตัวอย่าง
จากนั้นทำตารางช่วงคะแนนสำหรับแต่ละเกรดไว้ที่ใดที่หนึ่ง อาจจะต่อท้ายตารางคะแนนหรือจะเอาไว้อีกแผ่นงาน (Sheet) หนึ่งเลยก็ได้ แต่สิ่งสำคัญคือเกรดต้องเรียงจากน้อยไปหามาก ให้คอลัมน์ซ้ายมือเป็นคะแนนต่ำสุดที่จะได้เกรดนั้น ๆ และคอลัมน์ขวาเป็นเกรดนั้น ๆ ดังรูป
ไปที่ เกรด แถวแรก (ในตัวอย่างคือเซล r2) ใช้ฟังก์ชัน vlookup เพื่อเทียบช่วงคะแนน
ซึ่งเราสามารถเขียนเป็นฟังก์ชันลงในเซล R2 โดยตรงก็ได้ดังนี้
=vlookup(i2,$S$2:$T$10,2,1)
  • i2 นั้นหมายถึงจะร้อยละของคะแนนจากเซล i2 เป็นตัวค้นหา 
  • $s$2:$T$9  หมายถึงตารางเกรด การที่มีเครื่องหมายดอลลาร์อยู่หน้า S และ 2 หมายถึงเราต้องการจะอ้างอิงตำแหน่งนี้แบบสัมบูรณ์ (Absolute) ไม่ใช่แบบสัมพัทธ์ (Relative) ซึ่งเป็นค่าปริยายของการอ้างถึงตำแหน่ง
  • 2 คือเลขคอลัมน์ในตารางเกรดที่จะใช้เป็นค่าส่งคืนของฟังก์ชัน vlookup เมื่อคะแนนใน i2 พบเกณฑ์ของตนเองในตาราง $s$2:$T$9 แล้วจะนำค่าในคอลัมน์นี้ (คือคอลัมน์ที่ 2) ของตารางส่งคืนค่ามาให้ Calc
  • 1 ในอาร์กิวเมนต์สุดท้ายเป็นการระบุว่าตารางเกรด $s$2:$T$9 ของเรานี้มีการเรียงค่าจะน้อยไปหามาก ข้อสุดท้ายนี้จำเป็นเนื่องจากคะแนนอาจมีหลากหลายค่า ไม่ตรงกันกับค่าในตาราง กระบวนการค้นหาจะไล่ค้นหาจากน้อยไปหามาก ก็คือหาจากข้างบนลงข้างล่างนั่นเองและจะคืนค่าที่น้อยกว่าที่ใกล้ที่สุดให้
เมื่อได้เกรดในเซล r2 แล้วก็สามารถคัดลอกสูตรในเซลนี้ไปยังแถวอื่น ๆ ได้
จะขออธิบายการทำงานของฟังก์ชันนี้โดยใช้ตัวอย่างคะแนนในเซล i3 มีค่าเท่ากับ 57.50
  • เกณฑ์ค้นหา (อาร์กิวเมนต์ที่ 1) คือ 57.50
  • ตารางที่ค้นหา (อาร์กิวเมนต์ที่ 2) คือ s2:t9 ถ้าไม่อ้างตำแหน่งแบบสัมบูรณ์ในเซล r2 เมื่อคัดลอกสูตรมาที่ r3 ตารางจะกลายเป็น r3:t10 ซึ่งไม่ถูกต้อง
  • ค่าที่จะเป็นเกรดอยู่ในคอลัมน์ที่ 2 ของตาราง เลข 2 นี้ก็คืออาร์กิวเมนต์ที่ 3 ของฟังก์ชัน
  • ค่าที่จะค้นคือ 57.5 การค้นจะไล่จากบนลงล่าง 
    • ค้นแถวแรกเจอ 0 และ 57.5 มากกว่า 0 vlookup จะเก็บค่า F ไว้
    • ค้นแถวที่สองเจอ 45 และ 57.5 มากกว่า 45 vlookup จะเก็บค่า D ไว้
    • ค้นแถวที่สามเจอ 50 และ 57.5 มากกว่า 50 vlookup จะเก็บค่า D+ ไว้
    • ค้นแถวที่สี่เจอ 55 และ 57.5 มากกว่า 55 vlookup จะเก็บค่า C ไว้
    • ค้นแถวที่ห้าเจอ 60 แต่ 57.5 น้อยกว่า 60 vlookup ก็เลยบอกว่าหาไม่เจอแล้ว เอาค่าล่าสุดไปก่อนก็แล้วกัน เราก็จะได้เกรด C คืนกลับมาในเซล r3
อันที่จริงจากการลองผิดลองถูกเอง ผมได้ทดลองใช้ฟังก์ชัน if ซ้อน if ถึง 7 ชั้นด้วยกัน ซึ่งก็สามารถใช้งานได้แต่จะผิดพลาดได้ง่ายมาก เลยยังไม่ค่อยพอใจเท่าไร หลังจากนั้นจึงได้พบกับตัวอย่างของ vlookup ในภายหลัง แม้ว่าจะมีหลายคนทำเป็นวิดีโอและเว็บแล้ว ผมก็อยากจะบันทึกเก็บไว้เป็นอีกเสียงหนึ่ง เผื่อว่ามีใครหาคำว่า "ใช้ calc ตัดเกรด" จะได้หาข้อมูลเจอได้เร็วและไม่ต้องเสียเวลาไปเหมือนผมอีก
 
หมายเหตุ
  1. เซลในตัวอย่างกระโดดจาก i ไป r เพราะผมมีบางเซลที่ซ่อนไว้ไม่เกี่ยวกับงานนี้ครับ
  2. ในโปรแกรมจำพวกกระดานคำนวณ (Spreadsheet) อื่น ๆ ก็ทำได้เช่นเดียวกันนะครับ วิธีก็น่าจะคล้าย ๆ กันนั่นแหละ เดี๋ยวจะมาหาว่าผมเชียร์ LibreOffice จนออกนอกหน้า