บทความการพัฒนาโปรแกรมบน Raspberry Pi ด้วย Qt ตอนที่ 4

บทความการพัฒนาโปรแกรมบน Raspberry Pi ด้วย Qt
ตอนที่ 4 แนะนำการควบคุม GPIO บนบอร์ด Raspberry Pi ผ่าน Shell 

โดยเนื้อหาหลักๆ จะประกอบด้วยหัวข้อดังนี้

        Shell คือ โปรแกรมที่เป็นส่วนเชื่อมต่อระหว่าง Application กับ Kernel โดย User สามารถสั่งงาน Kernel ได้ผ่านทาง Shell นอกจากนี้ Shell ยังมีคุณสมบัติของ Shell Progamming Language ทำให้นำคำสั่งต่างๆ ของ Shell มาเขียนเป็นโปรแกรมได้เรียกว่า Shell Script

001

(Ref: เอกสารการใช้ Shell Script เบื้องต้น ftp://ftp.psu.ac.th/pub/bash-howto/Shell%20Script.pdf)

การต่อวงจร LED เข้ากับบอร์ด Raspberry Pi

002
003

ทดลองสั่ง On/Off LED ด้วย Shell

– เปิดโปรแกรม LXTerminal
– กำหนดสิทธิ์ให้เป็น Superuser พิมพ์คำสั่ง sudo su

004

– จากวงจรต่อ LED ที่ Pin 4 เปิดใช้งานโดยสร้างไฟล์ควบคุม GPIO Pin 4 ขึ้นมาด้วยคำสั่ง

echo 4 > /sys/class/gpio/export

005

– กำหนด Direction ของ Pin 4 ให้เป็น Output ด้วยคำสั่ง

echo out > /sys/class/gpio/gpio4/direction

006

– สั่งให้ Pin4 จ่าย Output เป็น High ให้ LED ติดด้วยคำสั่ง

echo 1 > /sys/class/gpio/gpio4/value

007

– สั่งให้ Pin4 จ่าย Output เป็น Low ให้ LED ดับด้วยคำสั่ง

echo 0 > /sys/class/gpio/gpio4/value

008

– เลิกใช้งานโดยลบไฟล์ควบคุม GPIO Pin 4 ด้วยคำสั่ง

echo 4 > /sys/class/gpio/unexport

009

เขียนโปรแกรมควบคุม LED ด้วย Qt

       จากการทดลองควบคุม LED ผ่าน Shell จะเห็นว่าการสั่งงานมีลักษณะคล้ายกับการเปิดไฟล์ขึ้นมาแล้วใส่ค่าต่างๆ เข้าไปเพื่อให้ไฟล์ควบคุมไปทำงานเพื่อควบคุม Hardware ในการทดลองนี้ก็จะใช้หลักการทำงานคล้ายกับ Shell โดยการอ่านหรือเขียนไฟล์แทนการพิมพ์ผ่าน Shell
การเขียน Code ภาษา C
        ฟังก์ชั่นที่สำคัญที่ใช้ในการทดลองนี้ คือ fopen fwrite fread fclose ซึ่งอยู่ใน Standard Library เรียกใช้โดย #include<stdion.h>
ฟังก์ชั่น fopen 
FILE *fopen(const char *filename, const char *mode);
const char *filename = Path ที่อยู่ของไฟล์ที่ต้องการเปิด
const char *mode = โหมดในการใช้งานไฟล์ซึ่งมีดังนี้
         “r” เปิดไฟล์เพื่ออ่านอย่างเดียวโดยไฟล์นั้นต้องมีอยู่แล้ว
         “w” เปิดแบบสร้างไฟล์ใหม่ หากมีไฟล์เดิมอยู่จะลบเนื้อหาภายในไฟล์ทิ้งเหมือนสร้างใหม่
         “a” เปิดไฟล์เพื่อเขียนข้อมูลลงในท้ายไฟล์ต่อจากเดิมที่มีอยู่แล้ว หากไม่มีไฟล์เดิมอยู่จะ สร้างขึ้นมาใหม่
         “r+” เปิดไฟล์เพื่ออัพเดท สามารถเขียนและอ่านได้ โดยไฟล์ต้องมีอยู่แล้ว
         “w+” เปิดแบบสร้างไฟล์ใหม่เพื่ออัพเดท สามารถเขียนและอ่านได้ หากมีไฟล์เดิมอยู่จะลบเนื้อหาภายในไฟล์ทิ้งเหมือนสร้างใหม่
         “a+” เปิดไฟล์เพื่ออัพเดท สามารถอ่านโดยเลื่อนตำแหน่งในไฟล์ได้ และเมื่อเขียนข้อมูลจะบันทึกลงในท้ายไฟล์ต่อจากเดิมที่มีอยู่ หากไม่มีไฟล์เดิมอยู่จะสร้างขึ้นมาใหม่
ฟังก์ชั่น fwrite
size_t fwrite(const void * ptr, size_t size, size_t count, FILE * stream);
         const void * ptr = ตำแหน่งที่เก็บข้อมูลที่ต้องการเขียน
         size_t size = ขนาดของแต่ละไบต์ที่ต้องการเขียน
         size_t count = จำนวนของไบต์ที่ต้องการเขียน
         FILE * stream = ตำแหน่ง Object ของไฟล์ที่ต้องการเขียน
ฟังก์ชั่น fread
size_t fread(void * ptr, size_t size, size_t count, FILE * stream);
         const void * ptr = ตำแหน่งที่เก็บข้อมูลที่ได้จากการอ่าน
         size_t size = ขนาดของแต่ละไบต์ที่ต้องการอ่าน
         size_t count = จำนวนของไบต์ที่ต้องการอ่าน
         FILE * stream = ตำแหน่ง Object ของไฟล์ที่ต้องการอ่าน

ฟังก์ชั่น fclose

int fclose ( FILE * stream );

         FILE * stream = ตำแหน่ง Object ของไฟล์ที่ต้องการปิด

ตัวอย่างการเขียนโปรแกรมควบคุม GPIO 
– เปิดโปรแกรม Qt Creator
– สร้างหน้าตา User Interface ดังนี้

010

– คลิกขวาที่ PushButton ทั้งสอง แล้วสร้าง Slot เลือก Signal = clicked

011

– ไปที่ไฟล์ mainwindows.cpp เพิ่ม #include <stdion.h>

012

– กำหนดตัวแปร FILE *file

013

– เพิ่มโค้ดลงในฟังก์ชั่น MainWindow::MainWindow(QWidget *parent):QMainWindow(pa rent),ui(new Ui::MainWindow)

014

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

        บรรทัดที่ 12 เปิดไฟล์ export แบบ “w” เพื่อเขียนไฟล์
        บรรทัดที่ 13 ตรวจเช็คว่าสามารถเปิดไฟล์สำเร็จหรือไม่
        บรรทัดที่ 15 หากไม่สำเร็จให้แสดงข้อความออกทาง qDebug
        บรรทัดที่ 17 หากเปิดไฟล์สำเร็จ
        บรรทัดที่ 19 เขียนค่า “4” ลงไปในไฟล์ export
        บรรทัดที่ 20 ปิดไฟล์
        บรรทัดที่ 22 เปิดไฟล์ direction
        บรรทัดที่ 27 เขียนค่า “out” กำหนดให้เป็นเอาท์พุตลงในไฟล์ dicrection
        บรรทัดที่ 28 ปิดไฟล์

– เพิ่มโค้ดลงในฟังก์ชั่น MainWindow::~MainWindow()

015

เมื่อปิดโปรแกรมจะเข้ามาทำงานภายในฟังก์ชั่นนี้ก่อนจึงนำโค้ดในส่วนของการเขียนไฟล์ unexport เพื่อลบไดเรกทอรี่ของ GPIO Pin 4 ก่อนที่จะปิดโปรแกรม

         บรรทัดที่ 36 เปิดไฟล์ unexport
         บรรทัดที่ 43 เขียนค่า “4” ลงไปในไฟล์ unexport
         บรรทัดที่ 44 ปิดไฟล์ unexport
– เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_clicked()

016

เมื่อคลิกที่ปุ่ม LED On ในโปรแกรมจะเข้ามาทำงานที่ฟังก์ชั่นนี้ โค้ดในส่วนนี้ก็คือการเปิดไฟล์ value เพื่อเขียนค่าไปกำหนดให้ GPIO Pin 4 ส่ง Output เป็น High

         บรรทัดที่ 51 เปิดไฟล์ value
         บรรทัดที่ 58 เขียนค่า “1” ลงไปในไฟล์ value เพื่อจ่าย Output เป็น High
         บรรทัดที่ 59 ปิดไฟล์ value

– เพิ่มโค้ดลงในฟังก์ชั่น void MainWindow::on_pushButton_2_clicked()

017

เมื่อคลิกที่ปุ่ม LED Off ในโปรแกรมจะเข้ามาทำงานที่ฟังก์ชั่นนี้ โค้ดในส่วนนี้ก็คือการเปิดไฟล์ value เพื่อเขียนค่าไปกำหนดให้ GPIO Pin 4 ส่ง Output เป็น Low

        บรรทัดที่ 65 เปิดไฟล์ value
        บรรทัดที่ 72 เขียน “0” ลงไปในไฟล์ value เพื่อจ่าย Output เป็น Low
        บรรทัดที่ 73 ปิดไฟล์ value 
– ทดลอง Run โปรแกรม