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

ตอนที่ 6 ตัวอย่างการเขียนโปรแกรมรับ-ส่งข้อมูล ผ่านทาง UART ด้วย QtserialPort

ตอนที่ 6 ตัวอย่างการเขียนโปรแกรมรับ-ส่งข้อมูล
ผ่านทาง UART ด้วย QtserialPort
078
ติดตั้ง QtSerialPort
- เปิดโปรแกรม LXTerminal
- พิมพ์คำสั่ง git clone -b old/5.1  git://gitorious.org/qt/qtserialport.git เพื่อโหลดซอร์สโค้ดของไลบรารี่
2014-09-01-105852 1280x1024 scrot
- เมื่อโหลดเสร็จจะได้ไดเรกทอรี่ของ qtserialport เพิ่มเข้ามา
- เปิดโปรแกรม Qt Creator พิมพ์คำสั่ง sudo qtcreator
- เปิดไฟล์ Project ใน qtserialport/qtserialport.pro
059
060
- ไปที่โหมด Project 
061
- คลิก Add Build
062
- คลิก Configure Project
063
- โปรแกรมจะเข้าไปที่หน้า Edit ให้กลับไปที่หน้า Project
064
- คลิก Add Build Step
065
- เลือก Make
066
- เพิ่ม Make arguments ว่า “install”
067
- ไปที่เมนู Build เลือก Rebuild All แล้วรอให้คอมไพล์จนเสร็จ
068
วิธีการปิด Serial Console ของบอร์ด Raspberry Pi
         บอร์ด Raspberry Pi เปิดใช้งาน Serial Port (ttyAMA0) เป็น Console สำหรับติดต่อกับตัวบอร์ด ซึ่งในการทดลองนี้จำเป็นจะต้องใช้ Serial Port เช่นกัน จำเป็นต้องปิดการใช้งาน Serial Console บนบอร์ดเสียก่อน ไม่ให้แย่งกันใช้ Serial Port ระหว่าง Shell ของ Linux กับ Application ที่เราเขียนขึ้น และอาจทำให้บอร์ด Error ได้
- เปิดโปรแกรม LXTerminal
- พิมพ์คำสั่ง sudo vi /etc/inittab เปิดไฟล์ inittab เพื่อแก้ไข
069
- กด Enter
070
- เลื่อนเคอร์เซอร์ลงไปบรรทัดที่มีข้อความ T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
071
- กดตัว i (insert เข้าสู่โหมดการพิมพ์แทรก) บน keyboard เพื่อเพิ่มตัวอักษร
- เพิ่มเครื่องหมาย # หน้าบรรทัด #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
072
- กดปุ่ม Esc เพื่อออกจากโหมดการพิมพ์ ตามด้วย :wq เพื่อบันทึก (write) และปิด (quit) แล้วกด Enter
073
- ปิด Bootup Info พิมพ์คำสั่ง sudo leafpad /boot/cmdline.txt
074
- แก้ข้อความจาก ttyAMA0 ให้เป็น tty1
075
- ไปที่เมนู File เลือก Save แล้วปิดโปรแกรม
076
- Reboot บอร์ด โดยพิมพ์คำสั่ง sudo reboot
077
ทดลองเขียนโปรแกรม รับ/ส่ง Data กับ Computer ผ่านทาง Serial Port ด้วย QtserialPort
- ต่อบอร์ด RaspberryPi กับ USB to Serial และเชื่อมต่อ USB to Serial กับคอมพิวเตอร์ดังรูป
078
- เปิดโปรแกรม LXTerminal แล้วเปิดโปรแกรม Qt Creator ด้วยคำสั่ง sudo qtcreator
- สร้าง Project ใหม่ชื่อ serial
- เปิดไฟล์ serial.pro แล้วเพิ่มโค้ด
CONFIG += serialport

079
- ออกแบบหน้าตาโปรแกรมให้มี Widget ดังนี้
  o Pushbutton 3 อัน โดยแสดงข้อความบน Button ดังนี้
       “Open”
       “Close”
       “Send”
คลิกขวาที่ PushButton ทีละอัน แล้วสร้าง Slot เลือก Signal = clicked ให้ครบทั้ง 3 อัน
080
  o Combo Box 1 อัน
  o Text Edit 1 อัน
  o Line Edit 1 อัน
081
ภาพรวมของหน้าตาโปรแกรม
- ไปที่ไฟล์ mainwindows.cpp
082
- เพิ่ม include ไฟล์ QSerialPort กับ QSerialPortInfo และประกาศตัวแปล QSerialPort serial;
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
QSerialPort serial;
083
- เพิ่มโค้ดลงในฟังก์ชั่น MainWindow::MainWindow(QWidget *parent):QMainWindow (parent),ui(new Ui::MainWindow) ดังนี้
084
         บรรทัดที่ 14 เมื่อโปรแกรมถูกเปิดขึ้นให้วนรอบอ่านข้อมูลของ Serial Port ทั้งหมดที่เชื่อมต่ออยู่กับ RaspberryPi
         บรรทัดที่ 16 นำเอาชื่อของ Serial Port มาเพิ่มเข้าไปใน Combo Box
- เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_clicked()ดังนี้
085
         บรรทัดที่ 29 นำเอารายชื่อ Serial Port ที่อยู่ใน Combo Box มาใช้งาน
         บรรทัดที่ 30 กำหนด Baud Rate = 9600 bps
         บรรทัดที่ 31 กำหนด Data Bits = 8 bits
         บรรทัดที่ 32 กำหนดให้ไม่ใช้งาน Parity Bit
         บรรทัดที่ 33 กำหนด Stop Bit = 1 bit
         บรรทัดที่ 34 กำหนดให้ไม่ใช้ Flow Control
         บรรทัดที่ 35 กำหนด Signal และ Slot เมื่อมีข้อมูลเข้ามาจากฟังก์ชั่น readyRead() ให้เข้าไปทำงานในฟังก์ชั่น readData()
         บรรทัดที่ 36 เปิดใช้งาน Serial Port แล้วตรวจสอบเงื่อนไข
         บรรทัดที่ 38 หากสามารถเปิดใช้งาน Serial Port สำเร็จ ให้เคลียร์ข้อความทั้งหมดใน Text Edit ด้วยฟังก์ชั่น clear();
         บรรทัดที่ 39 ให้แสดงข้อความ “Open Port Success” ใน Text Edit
         บรรทัดที่ 44 หากไม่สามารถเปิดใช้งาน Serial Port สำเร็จ ให้แสดงข้อความ “Unable to Open Comm Port” ใน Text Edit
- สร้างฟังก์ชั่น readData() โดยเขียน Code ดังนี้
086
          บรรทัดที่ 50 อ่านค่าที่ได้รับมาจาก Serial Port ด้วยฟังก์ชั่น readAll() มาเก็บในตัวแปร QByteArray ชื่อ data
          บรรทัดที่ 51 แปลงตัวแปร data จาก QByteArray ให้เป็น QString และนำไปข้อความ ไปแสดงต่อจากข้อความเดิม ใน Text Edit
- ประกาศชื่อฟังก์ชั่น readData() ใน mainwindows.h
  o ไปที่ไฟล์ mainwindows.h
087
  o เพิ่มชื่อฟังก์ชั่น void readData(); วางไว้ภายใต้ private slots;
088
- เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_2_clicked() ดังนี้
089
           บรรทัดที่ 56 ปิดการใช้งาน Serial Port
- เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_3_clicked() ดังนี้
090
           บรรทัดที่ 61 แปลงตัวอักษรใน Line Edit เป็น UTF8 และส่งออกไปทาง Serial Port
- ทดลอง Run โปรแกรม
  o เปิดโปรแกรม Putty บนเครื่องคอมพิวเตอร์ หากไม่มีสามารถ Download ได้ที่
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
091
  o หน้าแรกในหัวข้อ Session เลือก Connect Type เป็น Serial
  o จากนั้นเลือกหัวข้อ Connection > Serial แล้วกำหนดค่าต่างๆ
      ตั้ง Serial line to connect ให้ตรงกับชื่อ COM Port ของ USB to Serial
      ตั้ง Speed (baud)=9600
      Data bits=8
      Stop bits=1
      Parity=None
      Flow control=None
  o คลิกปุ่ม Open บน PuTTY
092
  o คลิกปุ่ม Open ในโปรแกรมที่เราสร้างขึ้นบนบอร์ด Raspberry Pi
  o ทดสอบพิมพ์ข้อความ ThaiEasyElec ใน Line Edit และกดปุ่ม Send ข้อความใน Line Edit จะถูกส่งไปแสดงในโปรแกรม Putty ผ่านทาง Serial Port
  o ทดสอบพิมพ์ข้อความ www.ThaiEasyElec.com ในโปรแกรม Putty ข้อความจะถูกนำไปแสดงใน Text Edit ผ่านทาง Serial Port
093

ตอนที่ 5 แนะนำให้รู้จักไลบรารี่ WiringPi, วิธีการติดตั้ง พร้อมตัวอย่างการเขียนโปรแกรมควบคุมฮาร์ดแวร์ด้วยไลบรารี่ WiringPi

ตอนที่ 5 แนะนำให้รู้จักไลบรารี่ WiringPi, วิธีการติดตั้ง
พร้อมตัวอย่างการเขียนโปรแกรมควบคุมฮาร์ดแวร์ด้วยไลบรารี่ WiringPi
 036
การเขียนโปรแกรมควบคุมฮาร์ดแวร์ด้วยไลบรารี่ WiringPi 

       WiringPi คือ กลุ่มของไลบรารี่ที่พัฒนาโดย http://wiringpi.com สำหรับเข้าถึงการใช้งาน GPIO ของชิพ BCM2835 ที่เป็นชิพประมวลผลหลักของบอร์ด Raspberry Pi ซึ่งสามารถใช้งานได้จากภาษา C/C++ และภาษาอื่นๆ อีกหลากหลายภาษาที่ WiringPi ออกแบบชุดคำสั่งให้มีลักษณะคล้ายกับการใช้งานภาษา Wiring ทำให้ผู้ที่เคยใช้งานบอร์ด Arduino รู้สึกคุ้นเคยกับรูปแบบชุดคำสั่งและทำให้การควบคุมฮาร์ดแวร์ของบอร์ด Raspberry Pi สามารถทำได้ง่ายขึ้น

วิธีติดตั้ง WiringPi ของบอร์ด Raspberry Pi
- เชื่อมต่อบอร์ด Raspberry Pi กับ Internet
- เปิดโปรแกรม LXTerminal
- ในขั้นตอนการใช้คำสั่ง update และ upgrade จะใช้เวลาในการค่อนข้างนาน หากเคย update และ upgrade ไปแล้ว อาจทดลองใช้คำสั่ง git clone git://git.drogon.net/wiringPi ในหัวข้อถัดไปดูก่อน แล้วหากไม่ Error ก็สามารถข้ามขั้นตอนนี้ไปได้
       o พิมพ์คำสั่ง sudo apt-get update แล้วรอจนอัพเดทเสร็จ
        018
       o พิมพ์คำสั่ง sudo apt-get upgrade แล้วรอจนอัพเกรดเสร็จ
       019
- พิมพ์คำสั่ง sudo apt-get install git-core เพื่อติดตั้ง Git Core
020
- พิมพ์คำสั่ง sudo apt-get install libi2c-dev เพื่อติดตั้งไลบรารี่ของ I2C
021
- พิมพ์คำสั่ง git clone git://git.drogon.net/wiringPi เพื่อสร้างลิงค์ WiringPi จาก Git
022
- พิมพ์คำสั่ง cd wiringPi กด Enter
023
- พิมพ์คำสั่ง git pull origin เพื่อดึงซอร์สโค้ดมาจากต้นทาง
024
- พิมพ์คำสั่ง ./build เพื่อคอมไพล์ WiringPi
025
- ทดสอบการติดตั้ง WiringPi พิมพ์คำสั่ง gpio –v จะปรากฏข้อความดังภาพ
026
- พิมพ์คำสั่ง gpio readall จะปรากฏตาราง GPIO ดังภาพ
027
ติดตั้ง C library for Broadcom BCM2835
- พิมพ์คำสั่ง cd กลับไปที่ Home Directory
- พิมพ์คำสั่ง sudo wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.36.tar.gz เพื่อดาวน์โหลดไฟล์ไลบรารี่จากลิงค์
028
- พิมพ์คำสั่ง tar xvfz bcm2835-1.36.tar.gz เพื่อแตกไฟล์ที่บีบอัดมา
029
- พิมพ์คำสั่ง cd bcm2835-1.36 เปลี่ยนไดเรกทอรี่เข้าไปที่ bcm2835-1.36
030
- พิมพ์คำสั่ง ./configure เพื่อโหลดค่าคอนฟิก
031
- พิมพ์คำสั่ง make เพื่อสร้างไฟล์ติดตั้ง
032
- พิมพ์คำสั่ง make check เพื่อตรวจสอบไฟล์
033
- พิมพ์คำสั่ง sudo make install เพื่อติดตั้ง
034
WiringPi Pin
           เนื่องจาก Pin บนคอนเน็คเตอร์สำหรับใช้งาน GPIO ของ RaspberryPi แต่ละ Pin ค่อนข้างจะอยู่กระจายกันทำให้มีโอกาสสับสนได้ง่ายในการใช้งาน WiringPi จึงได้กำหนดชื่อของ Pin ขึ้นมาใหม่ทำให้ผู้ใช้เรียกใช้ในการเขียนโปรแกรมได้ง่ายขึ้น สามารถดูความแตกต่างได้ดังภาพ
035
ทดสอบใช้งาน WiringPi จาก Code ตัวอย่าง Blink.c
- ต่อวงจร Raspberry Pi กับ LED ดังรูป
036
- เปิดโปรแกรม LXTerminal 
- พิมพ์คำสั่ง cd กลับไปที่ Home Directory
- พิมพ์คำสั่ง cd wiringPi/examples เปลี่ยนไปยังไดเรกทอรี่ examples ภายใต้ wiringPi
037
- พิมพ์คำสั่ง gcc -Wall -o blink blink.c –lwiringPi เพื่อคอมไพล์ตัวอย่างโปรแกรม blink.c
038
- พิมพ์คำสั่ง sudo ./blink เพื่อรันโปรแกรม
039
- จะพบว่า LED ที่ต่อไว้ที่ GPIO0 กระพริบทุกๆ 500 ms
- หากต้องการหยุดการทำงานของโปรแกรมให้กด Ctrl + z
เขียนโปรแกรมควบคุม LED ด้วย Qt
         ในส่วนนี้จะเป็นการเขียนควบคุม On/Off LED เหมือนเนื้อหาที่ผ่านมาแต่จะนำเอาไลบรารี่ WiringPi เข้ามาใช้งานซึ่งทำให้การเขียนโปรแกรมควบคุม GPIO ทำได้ง่ายขึ้น
ขั้นตอนการทดลอง
- ต่อวงจร Raspberry Pi กับ LED ดังรูป
040
- เปิดโปรแกรม LXTerminal แล้วเปิดโปรแกรม Qt Creator พิมพ์คำสั่ง sudo qtcreator
- สร้าง Project ใหม่ชื่อ GPIO ให้ลองตั้งค่าต่างๆ โดยย้อนไปดูตัวอย่างในส่วนที่ผ่านมา
041
- เปิดไฟล์ gpio.pro
042
- เพิ่มไลบรารี่และ Include path โดยเพิ่มโค้ดลงไปในไฟล์ gpio.pro ดังนี้
LIBS += -L/usr/local/lib -lwiringPi -lwiringPiDev
INCLUDEPATH += /usr/local/include
 043
- เปิดไฟล์ mainwindows.ui
044
- สร้างปุ่มแบบ PushButton จำนวน 2 ปุ่ม ชื่อ LED On และ LED Off
045
- คลิกขวาที่ปุ่มทั้งสองแล้วเลือก Go to slot เลือก Signal เป็น clicked
046
- เปิดไฟล์ mainwindows.cpp
047
- เพิ่ม #include <wiringPi.h> และประกาศตัวแปร int led = 0 (LED ต่ออยู่ที่ GPIO0)
048
- เพิ่มโค้ดลงในฟังก์ชั่น MainWindow::MainWindow(QWidget *parent):QMainWindow (parent),ui(new Ui::MainWindow) ดังนี้
049
        บรรทัดที่ 11 ตั้งค่าเริ่มต้นให้ใช้โครงสร้าง Pin ในรูปแบบของ WiringPi 
        บรรทัดที่ 12 กำหนดโหมดทิศทางให้กับ GPIO0 เป็น Output
- เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_clicked()
050
        บรรทัดที่ 22 กำหนด Output เป็น High ที่ GPIO0
- เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_2_clicked()
051
        บรรทัดที่ 27 กำหนด Output เป็น Low ที่ GPIO0
- ทดลอง Run โปรแกรม
เขียนโปรแกรมรับ Digital Input จาก Switch ด้วย Qt
ในการทดลองนี้จะใช้ Qtimer ซึ่งเป็น Timer ของ Qt มาวนรอบอ่านค่า อินพุตจาก GPIO7
และแสดงผลผ่านทางกรอบ Line Edit บนหน้าต่างโปรแกรม
ขั้นตอนการทดลอง
- ต่อวงจร Raspberry Pi กับ Switch แบบกดติดปล่อยดับดังรูป
052
- เปิดโปรแกรม LXTerminal แล้วเปิดโปรแกรม Qt Creator ด้วยคำสั่ง sudo qtcreator
- สร้าง Project ใหม่ชื่อ input
- เปิดไฟล์ input.pro แล้วเพิ่มไลบรารี่และ Include path โดยเพิ่มโค้ดลงไปในไฟล์ input.pro ดังนี้
LIBS += -L/usr/local/lib -lwiringPi -lwiringPiDev
INCLUDEPATH += /usr/local/include
- เปิดไฟล์ mainwindows.ui สร้าง Line Edit แล้วปรับแต่งหน้าตาโปรแกรมตามความเหมาะสม
053
- เปิดไฟล์ mainwindow.cpp เพิ่ม #include <qtimer.h> #include <wiringPi.h> และประกาศตัวแปร int intput_pin=7 ให้รับ Digital Input จาก GPIO7
- เพิ่มโค้ดลงไปในฟังก์ชั่น MainWindow::MainWindow(QWidget *parent):QMainWindow (parent),ui(new Ui::MainWindow) ดังนี้
054
      บรรทัดที่ 13 ตั้งค่าเริ่มต้นให้ใช้โครงสร้าง Pin ในรูปแบบของ WiringPi
      บรรทัดที่ 14 กำหนด Direction ให้กับ GPIO0 เป็น Input
      บรรทัดที่ 16 สืบทอดคลาส Qtimer โดยตั้งชื่อว่า timer
      บรรทัดที่ 17 สร้าง Signal และ Slot ให้ timer เมื่อครบเวลาตามกำหนดในฟังก์ชั่น timeout() จะเกิด Signal ให้เข้าไปทำงาน Slot ที่ได้สร้างฟังก์ชั่น interval() มารองรับ ผลคือ เมื่อครบเวลาตามกำหนดจะมีการกระโดดเข้ามาทำงานในฟังก์ชั่น interval() ทุกครั้ง
      บรรทัดที่ 18 เริ่มให้ timer ทำงานและกำหนดเวลาไว้ที่ 100 ms
- สร้างฟังก์ชั่น แล้วกำหนดการทำงาน interval ดังนี้
055
      บรรทัด ที่ 26 อ่านค่าอินพุต GPIO7 จากวงจรที่เราต่อแบบ Pull Up ในสถานะที่ยังไม่มีการกดสวิตช์จึงมีไฟ 3.3V หรือ Logic 1 (High) เข้ามาที่ GPIO7 ตลอดเวลา และเมื่อเรากดสวิตช์จะทำให้กระแสไหลผ่านตัวต้านทานลงกราวด์ที่ GPIO7 จึงเป็น 0V หรือ Logic 0 (Low)
      บรรทัดที่ 27 หากมีการกดสวิตช์จะขึ้นข้อความบน Line Edit ว่า “Input Low”
      บรรทัดที่ 29 หากไม่มีการกดสวิตช์จะขึ้นข้อความบน Line Edit ว่า “Input High”
- ประกาศชื่อฟังก์ชั่น interval() ไว้ใน mainwindows.h
      o เปิดไฟล์ mainwindows.h
056
      o เพิ่มโค้ดในไฟล์ mainwindows.h ดังนี้
057
- ทดลอง Run โปรแกรม