เรียนรู้และฝึกทดลองไปกับบอร์ดไมโครคอนโทรเลอร์ 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 เพื่อสั่งให้คอมไพล์โปรแกรมและดาวน์โหลดโปรแกรมจากเว็บลงมา