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

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

จากค่าย STMicroelectronics

(ตอนที่ 4 ทดลองใช้งานขา PWM บนบอร์ด Nucleo)

ในบทความนี้เป็นการทดลองใช้งานขา PWM (Pulse Width Modulation) บนบอร์ด Nucleo โดยให้ขาสัญญาณ D3 และ D5 เป็นค่า PWM ในโปรแกรมกำหนดให้อ่านค่าแรงดันสัญญาณที่ขา ADC จากตัวต้านทานปรับค่าได้ทั้งสองจากนั้นนำข้อมูลที่ได้ไปปรับมุมการหมุนของมอเตอร์ Servo ที่รับสัญญาณจากขา PWM ทั้งสอง

 สัญญาณ PWM คือสัญญาณที่มีการปรับความกว้างของพัลซ์ ค่าคาบเวลาช่วง HIGH ของสัญญาณ 1 ลูกคลื่น มีหน่วยเป็นเปอร์เซ็นต์ เรียกว่า ค่าดิวตี้ไซเคิล (Duty Cycle) เช่น 1 ลูกคลื่นของสัญญาณกว้าง 20 ms ช่วง HIGH กว้าง 10 ms ค่า Duty Cycle คิดเป็น 50% สัญญาณ PWM ถูกนำไปประยุกต์ใช้ควบคุมอุปกรณ์อื่นมากมาย เช่น ควบคุมมอเตอร์ Servo ความสว่างของ LED โทนเสียงต่างๆ ในลำโพง Buzzer ควบคุม Inverter เป็นต้น โดยในตัวอย่างนี้นำขาสัญญาณ PWM ของ Nucleo ไปควบคุมมอเตอร์ Servo โดยกำหนดความกว้างของสัญญาณที่ 20 ms เมื่อกำหนดให้ให้ช่วง HIGH กว้าง 0.5 ms Servo จะหมุนที่ 0 องศา เมื่อขยายความกว้างของสัญญาณมากขึ้น Servo จะหมุนเพิ่มองศาไปเรื่อยๆ จนถึง 2.0 ms Servo จะหยุดหมุนที่ 180 องศา ดังภาพสัญญาณด้านบน

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

         จากนั้นเข้าไปที่หน้าเว็บ Compiler ของ mbed สร้างไฟล์โปรแกรม main.cpp และอิมพอร์ตไลบรารี่พื้นฐานของ mbed เข้ามา จากนั้นเขียนโค้ดโปรแกรมในไฟล์ main.cpp

โค้ดโปรแกรมดังนี้

#include "mbed.h"
 
AnalogIn analog_ch_0 (A0);
AnalogIn analog_ch_1 (A1);
 
PwmOut servo_0(D3);
PwmOut servo_1(D5);
 
float value_ain_0 =0.0;
float value_ain_1 =0.0;
 
float map(float x, float in_min, float in_max, float out_min, float out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
 
int main()
{
    servo_0.period_ms(20);
    servo_0.pulsewidth_ms(0.5);
    servo_1.period_ms(20);
    servo_1.pulsewidth_ms(0.5);
    while(1) {
        value_ain_0 = analog_ch_0.read();
        value_ain_1 = analog_ch_1.read();
        value_ain_0 =  map(value_ain_0,0.0f,1.0f,0.025f,0.1f);
        value_ain_1=  map(value_ain_1,0.0f,1.0f,0.025f,0.1f);
        servo_0.write(value_ain_0);
        servo_1.write(value_ain_1);
        wait_ms(10); // 10 ms
    }
}

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

AnalogIn analog_ch_0 (A0);
AnalogIn analog_ch_1 (A1);
 
PwmOut servo_0(D3);
PwmOut servo_1(D5);
 
float value_ain_0 =0.0;
float value_ain_1 =0.0;

 กำหนดขา Analog Input ที่ขา A0 A1 ขาPWM ที่ขา D3 D5 สร้างตัวแปร float value_ain_0 และ flost value_ain_1 สำหรับเก็บค่าที่อ่านได้จาก Analog Input ทั้ง 2

float map(float x, float in_min, float in_max, float out_min, float out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

สร้างฟังก์ชัน map สำหรับกำหนดข้อมูลน้อยและมากที่สุดใหม่ ในตัวอย่างนี้ใช้อ่านค่าจากขา Analog Input ค่าที่อ่านได้จะมีค่าตั้งแต่ 0.0 – 1.0 เมื่อส่งค่าให้ขาสัญญาณ PWM ต้องกำหนดขนาดของข้อมูลใหม่ให้ใช้งานได้กับมอเตอร์ Servo

    servo_0.period_ms(20);
    servo_0.pulsewidth_ms(0.5);
    servo_1.period_ms(20);
    servo_1.pulsewidth_ms(0.5);

 ในฟังก์ชั่น main() กำหนดคาบสัญญาณของขา PWM ทั้ง 2 ที่ 20 ms และกำหนดค่าเริ่มต้นช่วง HIGH กว้าง 0.5 ms

while(1) {
        value_ain_0 = analog_ch_0.read();
        value_ain_1 = analog_ch_1.read();
 
        value_ain_0 =  map(value_ain_0,0.0f,1.0f,0.025f,0.1f);
        value_ain_1=  map(value_ain_1,0.0f,1.0f,0.025f,0.1f);
 
        servo_0.write(value_ain_0);
        servo_1.write(value_ain_1);
 
        wait_ms(10); // 10 ms
    }

   ในฟังก์ชัน while() ให้โปรแกรมอ่านค่าจากขา Analog Input เก็บไว้ในตัวแปร value_ain_0 และ value_ain_1 จากนั้นใช้ฟังชั่น map() แปลงค่าที่อ่านได้ให้ใช้งานกับมอเตอร์ Servo คือเริ่มต้นที่ 0.5 ms (Duty Cycle = 0.25%) ถึง 2.0 ms (Duty Cycle = 10 %) จากนั้นกำหนดค่าสัญญาณที่ขา PWM โดยใช้คำสั่ง .write() วนทำงานทุกๆ 10 ms

        สามารถดูข้อมูล และตัวอย่างการใช้งานเพิ่มเติมได้จาก http://developer.mbed.org/handbook/PwmOut

 จากนั้นทดลองใช้งานโปรแกรม โดยกดปุ่ม Compile All เพื่อสั่งให้คอมไพล์โปรแกรมและดาวน์โหลดโปรแกรมจากเว็บลงมา