เรียนรู้และฝึกทดลองไปกับบอร์ดไมโครคอนโทรเลอร์ STM32 Nucleo จากค่าย STMicroelectronics (ตอนที่ 5 ทดลองใช้งานพอร์ต Serial บนบอร์ด Nucleo)

เรียนรู้และฝึกทดลองไปกับบอร์ดไมโครคอนโทรเลอร์ STM32 Nucleo

จากค่าย STMicroelectronics

(ตอนที่ 5 ทดลองใช้งานพอร์ต Serial บนบอร์ด Nucleo)

ในบทความนี้เป็นการทดลองใช้งานพอร์ต Serial บนบอร์ด Nucleo โดยให้ Nucleo ต่อกับเซ็นเซอร์ Ultrasonic และมอเตอร์ Servo 2 ตัว ให้ Nucleo อ่านค่าระยะของวัตถุ ส่งค่าที่อ่านได้ และรอรับคำสั่งควบคุมการหมุนมอเตอร์จาก PC 
           ในการทดลองนี้จะใช้ Serial 2 ซึ่งอยู่ที่ขาดิจิตอล D0 และ D1 หรือขา PA_2 และ PA_3 ของ MCU พอร์ต Serial 2 ต่อกับบอร์ด ST-Link ซึ่งเป็นทั้งบอร์ดโปรแกรม Debug และ USB to Serial เราจะให้ MCU สื่อสารกับ PC โดยให้ผ่านบอร์ด ST-Link

1. ติดตั้ง Driver 
           เมื่อต่อบอร์ด Nucleo เข้ากับ PC ผ่านสาย USB จะพบว่าในหน้าต่าง Device Manager จะเห็นอุปกรณ์ที่ยังไม่ได้ติดตั้ง Driver อยู่ 2 รายการคือ ST-Link สำหรับการ Debug และ USB To Serial

   ให้เข้าไปที่ http://developer.mbed.org/teams/st/wiki/ST-Link-Driver เพื่อดาวน์โหลด Driver ของบอร์ด ST-Link โดยคลิกที่หัวข้อ Download ST-Link Driver

จากนั้นติดตั้ง Driver โดยไปที่หน้าต่าง Device Manager โดยคลิกขวา ที่หัวข้อ ST-Link Debug เลือกหัวข้อ Update Driver Software …

  เลือกหัวข้อ Browse my computer for driver software เพื่อกำหนดที่อยู่ไฟล์ Driver เอง

 กดปุ่ม Browse เพื่อเลือกที่อยู่ไฟล์ Driver ที่ดาวน์โหลดมา จากนั้นกดปุ่ม Next

ทำเครื่องหมายหน้า หัวข้อ Always trust software form “STMicroelectronics” จากนั้นกดปุ่ม Install

เมื่อติดตั้ง Driver สำเร็จแล้ว จะเห็นหัวข้อ Driver “STMicroelectronics STLink dongle” ในหัวข้อ Driver Serial Bus device

 จากนั้นติดตั้ง Driver USB To Serial ของบอร์ด ST-Link โดยคลิกขวาที่หัวข้อ Unknown device เลือกหัวข้อ Update Driver Software

กดปุ่ม Browse เพื่อเลือกที่อยู่ไฟล์ Driver ที่ดาวน์โหลดมา จากนั้นกดปุ่ม Next

กดปุ่ม Browse เพื่อเลือกที่อยู่ไฟล์ Driver ที่ดาวน์โหลดมา จากนั้นกดปุ่ม Next

  เมื่อติดตั้ง Driver USB To Serial เสร็จ จะ COM Port ขึ้นมาใหม่ ในตัวอย่างนี้เป็น COM Port ที่ 29

2. อัพเดท Firmware บอร์ด ST-Link 
           เมื่อต่อบอร์ด ST-Link เข้ากับ PC แล้ว ไม่ขึ้นอุปกรณ์ทั้ง 2 รายการข้างต้น ผู้ใช้ต้องทำการอัพเดท Firmware ก่อน ผ่านโปรแกรม STM32 ST-Link Utility 
           โปรแกรม ST-Link Utility สามารถดาวน์โหลดได้ที่ http://www.st.com/web/en/catalog/tools/PF258168

  หลังจากที่ดาวน์โหลด โปรแกรมและติดตั้งเรียบร้อยแล้ว ให้ PC ต่ออินเตอร์เน็ตอยู่ จากนั้นให้เปิดโปรแกรมและคลิกที่ ST-Link >> Firmware update

 คลิกที่ Device Connect จากนั้นโปรแกรมจะตรวจสอบเวอร์ชั่น Firmware ของบอร์ด ST-Link จากนั้นกดปุ่ม Yes >> เพื่ออัพเดท Firmware

  หลังจากติดตั้ง Driver และอัพเดท Firmware ของบอร์ด ST-Link ไปแล้ว จากนั้นทดลองต่อวงจรดังภาพ จากวงจรจะเห็นได้ว่า ขาสัญญาณ PWM ที่ใช้ควบคุมมอเตอร์ Servo ทั้งสองที่ขา D3 และ D5 ขาสัญญาณ A5 ต่อที่ขา Trig ของเซ็นเซอร์ Ultrasonic และขา Echo ต่อที่ขา D4
           ทั้ง Ultrasonic และมอเตอร์ Servo ใช้ไฟ +5V จากบอร์ด Nucleo

เมื่อต่อวงจรบนบอร์ดทดลองเข้ากับ Nucleo ได้ดังภาพ

3. ติดตั้ง Library Ultrasonic และทดลองใช้งาน 
           ในเบื้องต้นเราจะทำการทดสอบเซ็นเซอร์ Ultrasonic ก่อน โดยให้เข้าไปที่หน้า Developer site ของ mbed ที่http://developer.mbed.org/ ที่ช่องค้นหาด้านบนพิมพ์คำว่า Ultrasonic จะเห็นได้ว่าเวปจะแสดงผลการค้นหา หัวข้อที่เกี่ยวข้องกับเซ็นเซอร์ Ultrasonic ขึ้นมา เช่น Library โปรแกรมตัวอย่าง หรือปัญหาการใช้งาน คลิกเลือก หัวชื่อ Nucleo_ UltrasonicHelloWorld

 ในหน้าเว็บ Compiler ของ mbed แสดงหน้าต่าง Import program คลิกที่ Import

หลังจากที่อิมพอร์ตโปรแกรมเข้ามาแล้ว จะเห็นว่าที่ไฟล์ main.cpp เป็นโปรแกรมทดสอบเซ็นเซอร์ Ultrasonic ค่าที่อ่านได้ส่งไป PC ผ่านพอร์ต Serial จะเห็นได้ว่ายังมีการกำหนดขาต่อเซ็นเซอร์ไม่ถูกตามที่ได้ต่อวงจรไว้

แก้ไขเป็นขา A5 และ A4

 จากนั้นกดปุ่ม Compile All

 เมื่อโหลดโปรแกรมที่ Compile เข้ามาแล้ว จากนั้นทดลองเปิดโปรแกรม Serial monitor ขึ้นมา ในการทดลองนี้ใช้โปรแกรม X-CTU จะเห็นว่าบอร์ดส่งข้อมูลที่วัดได้จากเซ็นเซอร์มาที่ PC แล้ว

จากนั้นแก้โค้ดโปรแกรมใน main.cpp ดังนี้

#include "mbed.h"
#include "ultrasonic.h"
 
PwmOut servo_0(D3);
PwmOut servo_1(D5);
 
Serial pc(SERIAL_TX, SERIAL_RX);
 
void dist(int distance)
{
    pc.printf("Distance changed to %dmm\r\n", distance);
}
 
ultrasonic mu(A5,A4, .1, 1, &dist);
 
int main()
{
    servo_0.period_ms(20);
    servo_0.pulsewidth_ms(1.5);
    servo_1.period_ms(20);
    servo_1.pulsewidth_ms(1.5);
 
    mu.startUpdates();//start mesuring the distance
 
 
    while(1) {
 
        if(pc.readable()) {
            char c = pc.getc();
            switch (c) {
                case 'U' :
                    servo_0.write(0.03f);
                    break;
                case 'D' :
                    servo_0.write(0.1f);
                    break;
                case 'R' :
                    servo_1.write(0.03f);
                    break;
                case 'L' :
                     servo_1.write(0.1f);
                    break;
                default:
                    pc.printf("i don't know!!");
            }//end switch
        }//end if
        else {
            mu.checkDistance();
         } //end else
    } //end while
} //end main

  จากโค้ดโปรแกรมจะเห็นได้ว่า

#include "mbed.h"
#include "ultrasonic.h"
 
PwmOut servo_0(D3);
PwmOut servo_1(D5);
 
Serial pc(SERIAL_TX, SERIAL_RX);

   กำหนดขาสัญญาณ PWM ที่ขา D3 และ D5 และใช้งานพอร์ต Serial 2 ที่ขา D0, D1

void dist(int distance)
{
    pc.printf("Distance changed to %dmm\r\n", distance);
}
 
ultrasonic mu(A5,A4, .1, 1, &dist);

     ประกาศฟังก์ชั่น dist คือฟังก์ชั่นที่หน้าที่รับค่า และส่งไปข้อความผ่าน Serial ออกไป จากนั้นใช้งาน ultrasonic สร้าง object ขึ้นมาใหม่ชื่อ mu กำหนดงานที่ขา A5,A4 มีการอัพเดตทุก 0.1 วินาที กำหนด Time out ที่ 1 วินาที ส่งค่าที่อ่านได้ไปดังฟังชั่น dist  

int main()
{
    servo_0.period_ms(20);
    servo_0.pulsewidth_ms(1.5);
    servo_1.period_ms(20);
    servo_1.pulsewidth_ms(1.5);
 
    mu.startUpdates();//start mesuring the distance

  ในฟังก์ชั่น main กำหนดค่าให้กับขาสัญญาณ PWM ทั้ง 2 ขา คือ 1 คาบที่ 20 ms ให้เริ่มต้นสัญญาณ High ที่ 1.5 ms

while(1) {
 
        if(pc.readable()) {
            char c = pc.getc();
            switch (c) {
                case 'U' :
                    servo_0.write(0.03f);
                    break;
                case 'D' :
                    servo_0.write(0.1f);
                    break;
                case 'R' :
                    servo_1.write(0.03f);
                    break;
                case 'L' :
                     servo_1.write(0.1f);
                    break;
                default:
                    pc.printf("i don't know!!");
            }//end switch
        }//end if
        else {
            mu.checkDistance();
         } //end else
    } //end while

     ใน while(1) วนตรวจสอบมีข้อมูลส่งมาจาก PC หรือไม่ ถ้ามีให้อ่านและเก็บไว้ในตัวแปร char c จากนั้นตรวจสอบตัวแปร c 
                 ถ้าเป็น ‘U’ ให้ปรับค่า Duty cycle ที่ 0.03 หรือ 0.3 % ของ 20 ms หรือประมาณ 0.06 ms ให้กับ Servo ที่แขนทำให้หมุนขึ้น 
                 ถ้าเป็น ‘D’ ให้ปรับค่า Duty cycle ที่ 0.1 หรือ 10 % ของ 20 ms หรือประมาณ 2 ms ให้กับ Servo ที่แขนทำให้หมุนลง
                 ถ้าเป็น ‘R’ ให้ปรับค่า Duty cycle ที่ 0.03 หรือ 0.3 % ของ 20 ms หรือประมาณ 0.06 ms ให้กับ Servo ที่ฐานทำให้หมุนไปทางขวา
                 ถ้าเป็น ‘L’ ให้ปรับค่า Duty cycle ที่ 0.1 หรือ 10 % ของ 20 ms หรือประมาณ 2 ms ให้กับ Servo ที่ฐานทำให้หมุนไปทางซ้าย
                 ถ้าไม่ตรงกับตัวอักษรทั้ง 4 ให้ส่งข้อความ “i don’t know!!” และถ้าไม่มีการส่งข้อมูลเข้ามาให้ส่งข้อมูลระยะที่อ่านได้กลับไป
           หลังจากที่โหลดโปรแกมที่บอร์ด Nucleo แล้วทดลองโปรแกรมโดยเปิดโปรแกรม X-CTU และส่งตัวอักษร U,D,R และ L ดูการหมุนของ Servo ตามที่กำหนดไว้ในโปรแกรมหรือไม่