แสดงบทความที่มีป้ายกำกับ Arduino แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Arduino แสดงบทความทั้งหมด

วันอังคารที่ 16 พฤศจิกายน พ.ศ. 2564

ลองใช้ Stk500 MkII

Stk500 MkII เป็น avrisp สำหรับ AVR Board ใช้ได้หลากหลายโดยเราจะโปรแกรมผ่านพอร์ต isp แต่เมื่อลองใช้ครั้งแรกบน ARM ของ OrangePi One ก็มีปัญหา error ดังนี้ 

yothinin@orangepione:~/avr_c/avr-gcc/ex$ avrdude -p m328p -c avrispmkii  -U flash:w:blink13.hex:i -F -P usb_device

avrdude: stk500v2_command(): command failed
avrdude: stk500v2_program_enable(): bad AVRISPmkII connection status: Target not detected
avrdude: initialization failed, rc=-1
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x3088d6
avrdude: Expected signature for ATmega328P is 1E 95 0F
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.

avrdude done.  Thank you.

พยายามค้นหาข้อมูลในเน็ตอยู่นานก็ยังไม่ได้คำตอบ เลยเข้าไปดูรายละเอียดของอุปกรณ์ที่เว็บของ AVRISP ก็มีสถานะดังนี้


Red    อุปกรณ์ปลายทางไม่มีไฟเลี้ยง

สาเหตุก็คือ ตัวบอร์ด Uno ไม่มีไฟเลี้ยงนั่นเอง เพราะเคยชินกับ UsbAsp กับบอร์ดทดลอง ที่ไฟเลี้ยงมาจาก UsbAsp ก็สามารถอัพโหลดโปรแกรมได้ แต่สำหรับ Stk500 MkII นั้นจ่ายไฟเลี้ยงไปไม่เพียงพอ

เมื่อหาอะแดปเตอร์มาเสียบให้กับ Uno ก็สามารถอัพโหลดโปรแกรมได้

ตัวอย่างโปรแกรม

ตัวอย่างโปรแกรมให้ไฟ LED กระพริบ โดยเลือกใช้ Buil in LED ที่อยู่ในบอร์ด Uno โดยจะเรียกว่า pin13 หรือ PB5 หรือ 0b000100000 หรือเขียนสั้นลงเป็น 0b100000

blink13.c

#include <avr/io.h>

#define F_CPU 16000000
#define BLINK_DELAY_MS 250

#include <util/delay.h>

int main (void)
{
  // Arduino digital pin 13 (pin 5 of PORTB) for output
  DDRB |= 0B100000; // PORTB5

  while(1) {
    // turn LED on
    PORTB |= 0B100000; // PORTB5
    _delay_ms(BLINK_DELAY_MS);

    // turn LED off
    PORTB &= ~ 0B100000; // PORTB5
    _delay_ms(BLINK_DELAY_MS);
  }
}

คอมไพล์

avr-gcc -Wall -g -Os -mmcu=atmega328p -o blink13.bin blink13.c


เปลี่ยนไฟล์ให้เป็น hex

avr-objcopy -j .text -j .data -O ihex blink13.bin blink13.hex

อัพโหลดโปรแกรม

avrdude -p m328p -c stk500v2 -U flash:w:blink13.hex:i -F -P usb_device -B100 -v

พารามิเตอร์ -B 100 กำหนดให้อัพโหลดแบบ Very Low Frequency เพื่อให้อัพโหลดช้าลง (ใช้สำหรับบอร์ดบางรุ่นที่รับโค้ดไม่ทัน) และ -v แสดงรายละเอียดการอัพโหลด สามารถใส่ -vvv ได้


วันพุธที่ 27 เมษายน พ.ศ. 2559

ใช้งาน ATTINY85 Controller ขนาดเล็ก

แรกเริ่มเดิมทีของคนที่เรียนรู้การเขียนโปรแกรม Arduino มักจะเริ่มต้นที่ Arduino UNO R3 ก่อน ตอนแรกก็มองว่าเป็นบอร์ดขนาดเล็กไม่ใหญ่โตอะไรมากนัก พอเรียนรู้มากยิ่งขึ้นก็เริ่มใช้งาน Arduino Pro Mini หรือ Nana ก็ทึ่งขนาดของบอร์ด

ต่อมาก็เรียนรู้ขึ้นไปอีกว่า งานบางงานใช้ I/O น้อยเพียง 1-2 Input หรือ 1-2 Output ก็ไม่จำเป็นต้องใช้บอร์ดขนาดใหญ่ทำให้งานเล็กลงไปอีก ก็มองบอร์ดที่เล็กลงไปเรื่อยๆ

สำหรับ ATTINY85 ก็เป็นคอนโทรลเลอร์อีกตัวหนึ่งใช้ Chip ของ Atmel เป็นไอซีขนาด 8 ขา มี 6 I/O ถือว่ามีให้มาพอสมควร และสามารถนำไปใช้งานควบคุมได้หลายอย่าง เช่น การควบคุมมอเตอร์ สร้างหุ่นยนต์ขนาดเล็ก ฯลฯ

รูปแสดงขาใช้งานของ ATtiny


วันเสาร์ที่ 12 มีนาคม พ.ศ. 2559

ENC28J60, Ethernet Shield V1.0 ของ Deek-Robot

สั่ง Ehternet Shield จาก ArduilAll.com มาชิ้นหนึ่ง ด้วยความเร่งรีบ ก็ดาวน์โหลดไลบรารีมาใช้งานเลย ตามตัวอย่างก็ใช้งานได้เป็นอย่างดี แต่ไม่มีส่วนของ DHCP ที่จะรับให้กับตัวบอร์ด จึงไปค้นหาจากเน็ตก็เจอ EtherCard มาใช้เพราะมีตัวอย่าง testDHCP แต่ใช้ไม่ได้ ทำอย่างไรก็แล้ว ไม่สามารถจะรับไอพีจากเราท์เตอร์ได้ ลง-ลบ ไดร์เวอร์หลายก็ไม่ได้

ENC28J60 กับบอร์ด Arduino NANO มีขนาดพอๆ กับแป้นพิมพ์


สุดท้ายลองเข้าไปอ่านในเว็บ Tweaking4All.com เดิมคลิกลิงค์ตามเว็บที่สั่งของก็ไม่ได้ เลยไม่สนใจ

Ethernet Shield V1.0 for arduino compatible Nano 3.0



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

esp8266-12e ใช้งาน GPIO9

โมดูล ESP8266-12e เป็นโมดูลที่พัฒนามาจากรุ่น 12 โดยจะมีขาใช้งานเพิ่มขึ้นอีก 6 ขา และมี GPIO เพิ่มอีก 2 ขา คือ GPIO9 และ GPIO10 ตามหลักการสามารถนำมาใช้งานได้ แต่เท่าที่ลองแล้วพบว่า ผู้เขียนยังไม่สามารถนำเอาขา GPIO10 มาใช้งานได้เลย ซึ่งจะหาทางศึกษาการนำมาใช้งานต่อไป

ตัวอย่างการต่ออุปกรณ์เพื่อทดสอบใช้งานขา GPIO9 โดยบอร์ดจะใช้ไฟเลี้ยงจากข้างนอก


วันศุกร์ที่ 19 กุมภาพันธ์ พ.ศ. 2559

LinkIt-Smart-7688 คอนโทรเลอร์ที่น่าสนใจในเวลานี้

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

ถ้าเครื่องดีๆ หน่อยก็อยู่ที่ 8 พันบาทขึ้นไป และมักจะจบที่ 1x,xxx อย่างแน่นอน แต่ประเด็นไม่ได้อยู่ที่ราคาเพียงอย่างเดียว แต่อยู่ที่ข้อมูลรายการที่สแกนเข้าออก เพราะปัจจุบันข้อมูลต่างๆ ยังอยู่ในเครื่องรอให้ผู้ใช้งานเชื่อมต่อเข้าไปเพื่อดึงข้อมูลออกมาอีกครั้งหนึ่ง

ส่วนเครื่องสแกนที่ส่งข้อมูลแบบ Real Time หรือส่งข้อมูลทันทีนั้นมีเหมือนกันแต่ราคาก็สูงขึ้นไปอีก ทำให้เกิดแนวคิดที่จะแก้ไขปัญหา 2 ประการ คือ

วันอังคารที่ 14 กรกฎาคม พ.ศ. 2558

ทำไม Serial.print() ไม่ทำงานในส่วนของ setup()

หลายวันมานี้ทดลองเขียนโปรแกรม เขียนคำสั่งอยู่แต่ Arduino UNO R3 จนแทบจะลืม Leonardo และคราวนี้ลองหยิบจับมาทดสอบเขียนโปรแกรมดูบ้าง งานแรกก็เจอปัญหาเสียแล้ว

คำสั่ง Serial.print() ในส่วนของ setup() ไม่ทำงาน แต่ในส่วนของ loop() กลับทำงานได้ปกติ ก็งงอยู่พักใหญ่ไปค้นหาในอินเตอร์เน็ตก็มีคนเป็นเหมือนกัน แล้วได้คำตอบว่า

Leonardo เป็นบอร์ดที่ใช้ Chip Atmega32U4 ไม่เหมือน UNO R3 ดังนั้นจึงต้องสั่งให้โปรแกรมรอให้ Serial พร้อมทำงานก่อน
ลองดูตัวอย่างแรกก่อน
โปรแกรมในส่วนของ setup() จะมีคำสั่งพิมพ์เลข 10 ถอยหลังไปจนถึง 1 แล้วพิมพ์คำว่า Begin ระหว่างคำสั่งจะรอ 1 วินาที แต่เมื่อรันคำสั่งแล้วพบว่า กว่าจะเปิด Serial Monitor ได้โปรแกรมก็รันไปถึงการสั่งพิมพ์ เลข 6 แล้ว ดูเหมือนระบบจะทำงานเร็วขึ้น (?)

เริ่มพิมพ์ที่เลข 6


ตัวอย่างที่สอง
หลังจากนั้นเพิ่มคำสั่ง while (!Serial){} ไว้หลังบรรทัด Serial.begin(9600); แล้วเมื่อเปิด Serial Monitor โปรแกรมจะทำงานปกติ เริ่มตั้งแต่คำสั่งพิมพ์เลข 10 ไปเรื่อยๆ

เริ่มพิมพ์ที่ 10 เพราะมีคำสั่งตรวจสอบให้รอจนกว่า Serial จะพร้อมทำงาน

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

วันพุธที่ 17 มิถุนายน พ.ศ. 2558

Controller: เริ่มต้นจากศูนย์

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

ถึงแม้ว่าจะเขียนโปรแกรมด้วย Visual FoxPro เป็นหลักมาจะครบ 20 ปี แล้วซึ่งโดยหลักการแล้ว VFP เป็นโปรแรกมที่ใช้สำหรับสร้างระบบงานเก็บข้อมูล แต่ก็สามารถเชื่อมต่อควบคุมอุปกรณ์ผ่าน Serial และ Pararell Port ได้ โดยใช้ Win32API เป็นตัวช่วย เรียกได้ว่า VB ทำได้อย่างไร VFP ทำได้ 95% (เผื่อไว้สักเล็กน้อยเพราะบางเรื่องก็จนปัญญาจริงๆ หรือซับซ้อนมากเกินไป)

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

ล่าสุดเมื่อเดือนสองเดือนก่อน กลับมารื้อฟื้นงานคอนโทรลเลอร์อีกครั้ง ในเรื่องการสร้างนาฬิกาและป้ายบอกพิกัดบนรถโดยสาร และนี่แหละที่เป็นต้นเหตุให้ได้เรียนรู้เรื่องไมโครคอนโทรลเลอร์อีกครั้งหนึ่ง

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

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

ปัญหาการสลับเครื่องพิมพ์ด้วยการคลิก Set As Default Printer นั้นมีปัญหาหนึ่งที่เกิดขึ้นบ่อยครั้ง คือ ผู้ใช้เผลอไปคลิก Offline ทำให้พิมพ์งานไม่ออก และเดือดร้อนโทรหาไอทีซัพพอร์ตเป็นประจำ กว่าจะแก้ไขได้ก็ใช้เวลาไปหลายนาที (ถึงแม้จะไม่ได้เกิดขึ้นทุกวัน แต่ปัญหามักจะเกิดเช้ามืดหรือกลางคืน ซึ่งเป็นเวลาไม่ปกติ)

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

แนวคิดง่ายๆ นี้ได้รับคำตอบจากพนักงานในร้าน ThaiEasyElec บอกว่า "งานแบบนี้คอนโทรลเลอร์อะไรก็ทำได้ไม่ซับซ้อน pic ก็ยังไหว แต่ถ้าจะให้ดีก็ Arduino เพราะมีบอร์ดมีคนนิยมใช้งานเยอะ และมีไลบรารีต่างๆ เยอะแยะ..."

สุดท้ายก็จบด้วยการซื้อ Spark Pro Micro 5V เพราะเห็นว่ามีขนาดเล็ก เหมาะสำหรับเอาไปลงก่อนที่ไม่ใหญ่มากนัก และมี Port USB ให้เรียบร้อย ที่จะเชื่อมต่อไปยังเครื่องคอมพิวเตอร์

หลังจากนั้นอีก 1 วัน ก็ทดลองสร้างต้นแบบ และลองสร้างดูโดยใช้ LED เป็นตัวแสดงสถานะลำดับที่ 1-2-3 จากนั้นก็เขียนโปรแกรมอ่านค่าจาก Serial Port จาก Visual FoxPro 6.0 ก็สามารถอ่านและใช้งานได้ การทดลองครั้งนี้ LED ขาดไปสองตัว เพราะเผลอต่อตรงไม่มี R คั่นไว้สักนิด

จากนั้นก็เริ่มศึกษามากยิ่งขึ้นก็อยากได้บอร์ดของ Arduino แท้ๆ สักบอร์ดหนึ่ง ในหนังสือทั่วไปก็นิยมบอร์ด Arduino UNO R3 แต่ที่ร้านของหมดอีกหลายวันถึงจะได้ เลยตัดสินใจซื้อบอร์ด Arduino Leonardo พร้อมกับ LCD 16x2 เพื่อแสดงผลแทนการใช้ LCD และซื้อแบบ I2C เพราะใช้ขาสัญญานน้อยกว่าแบบ Pararell

กลับมาถึงก็เริ่มลงมือทดสอบ LCD แต่ทำอย่างไรก็ไม่ขึ้นข้อความมีแค่ไฟแบ็คไลท์สว่างอย่างเดียว เขียนโปรแกรมตามตัวอย่างแล้ว ต่อสายแบบตัวอย่างในเว็บก็ไม่ได้สักที วันรุ่งขึ้นพยายามอีกรอบก็ไม่สำเร็จ เลยส่ง e-mail ไปสอบถามพนักงานซัพพอร์ทได้รับคำตอบกลับมาภายในไม่ถึงครึ่งชั่วโมงว่า บอร์ด Leonardo มีขา SDA และ SLC แยกต่างหาก ให้ลองใช้งานขานั้นโดยตรง และก็ใช้ได้ จึงเริ่มต้นเขียนโปรแกรมส่งข้อมูลไปให้ LCD อีกครั้งหนึ่ง เพื่อเอามาแทน LED

หลังจากที่บอร์ดสามารถอ่านอินพุทจากสวิทช์ และเอาท์พุทไปที่ LCD ได้แล้ว ก็ถึงเวลาปรับปรุงโปรแกรมที่จะรับข้อมูลในเครื่องคอมพิวเตอร์ ปัญหาของ VFP คือ ไม่สามารถใช้งานได้อย่างสมบูรณ์ใน Windows 8 ซึ่งเป็นปัญหาใหญ่ในการเรียกใช้งาน Win32API ทำให้คิดถึงภาษา C ขึ้นมาทันที โดยมองข้าม VB ไปเพราะรูปแบบการเขียนโปรแกรมไม่ค่อยถูกใจผู้เขียนสักเท่าใดนัก

C# น่าจะเป็นทางเลือกที่ดีเพราะมีตัวอย่าง และเขียนได้ง่ายกว่าภาษา C++ โดย C# จะมี .Net Framework เป็นตัวจัดการให้

โปรแกรมแรกที่เขียนคือ Console Application เพื่อลองอ่าน Serial Port ก็ผ่านไปด้วยดี จึงอาจหาญสร้าง Windows Application Form (ตอนแรกกะจะไป WPF Application มันเสียเลยแต่ก็ยั้้งๆ ไว้เพราะคงต้องใช้เวลาศึกษาอีกเยอะ)

ใช้เวลาเขียน ศึกษา แก้ไขปัญหา ปรับปรุงอยู่ 2-3 วันก็เป็นที่เรียบร้อยครบถ้วนตามที่ต้องการ คือ


  1. Auto start รันโปรแกรมหลังจากที่เปิดเครื่อง 
  2. ตรวจสอบ Port โดยแสดงรายชื่อ Com Port พร้อมทั้งแสดงรายละเอียดด้วย ผู้ใช้งานจะได้รู้ว่า Port ที่เลือกนั้นใช่บอร์ด Arduino หรือไม่
  3. แสดงเครื่องพิมพ์ที่มีอยู่ในระบบเพื่อเลือกกำหนดว่าเครื่องพิมพ์อันไหนจะแสดงชื่ออะไรในจอ LCD เพื่อให้ดูได้ง่าย เช่น Epson L120 --> REPORT (เมื่อเลือก Epson L120 เป็น Default Printer ให้แสดงชื่อ REPORT ออกที่จอ LCD)
  4. เก็บคอนฟิกค่าที่ตั้งไว้ ตรวจสอบเมื่อเริ่มต้นโปรแกรม ถ้าคอนฟิกเรียบร้อยให้ย่อโปรแกรมลง (Minimized เดิมคิดจะให้ซ่อนโปรแกรมไปเลยแต่ก็คิดว่าอาจจะต้องคลิกเรียกโปรแกรมมาใช้งานภายหลัง) แต่ถ้าคอนฟิกไม่ถูกต้อง หรือ ไม่ได้เสียบอุปกรณ์ให้แสดงหน้าจอเพื่อให้เลือกคอนฟิกโปรแกรมและอุปกรณ์ใหม่
สำหรับโปรแกรมนี้ยังขาดการตรวจสอบอยู่อย่างหนึ่งคือ ขณะที่ใช้งานไปหากผู้ใช้ถอดสาย USB ออก ให้แสดงหน้าจอโปรแกรมพร้อมให้ตรวจสอบ แก้ไขให้เรียบร้อย (จะเพิ่มเติมภายหลัง)

ปัญหาสำคัญที่แก้ไม่ตก คือ โปรแกรม Anti-Virus มองว่าโปรแกรมที่รันอยู่นั้นเป็น Virus เพราะโปรแกรมถูกรันใน Registy/.../Run

ทั้งหมดนี้คือ การเริ่มต้นจากศูนย์ เริ่มจากไม่รู้อะไรมากเลย อาศัยถามพนักงานขาย หาอ่านใน google ทั้งการเขียน Arduino C และ C# ซึ่งเป็นเรื่องที่สนุกสนาน ท้าทายความสามารถในการเรียนรู้เป็นอย่างยิ่ง จึงนำมาเล่าสู่กันฟังในที่นี้ และจะคอยอัพเดทอยู่เรื่อยๆ ครับ

ต้นแบบที่ใช้โปรแกรม VFP อ่านข้อมูลจาก Serial Port

ตัวอย่างโดยใช้ Pro Micro 5V ของ SparkFun

ใช้ LED แสดงสถานะที่เลือก

สวิทช์ Selector เลือกตำแหน่งให้ Input แก่ขาที่กำหนดไว้

ลายวงจรจะทำแผ่นปริ้นท์สำหรับชุดอุปกรณ์

ภาพต้นแบบขณะทดลองเขียนโปรแกรม

โปรแกรมแรกที่เขียนด้วย C# 

โปรแกรมที่ปรับปรุงให้แสดงรายละเอียด Com Port 

โปรแกรมที่เสร็จแล้ว ภาพนี้ ComPort ขึ้นสีแดงเพราะไม่ได้เชื่อมต่อ


Gtk4 ตอนที่ 6 Defining a Child object

Defining a Child object A Very Simple Editor ในบทความที่ผ่านมาเราสร้างโปรแกรมอ่านไฟล์ชนิดข้อความ และในบทความนี้ก็จะมาปรับแต่งโปรแกรมกันสักหน...