- สัญญาณ PWM คืออะไร?
- การเขียนโปรแกรม PIC เพื่อสร้าง PWM บน GPIO Pins
- แผนภูมิวงจรรวม
- จำลองสถานการณ์
- การตั้งค่าฮาร์ดแวร์สำหรับควบคุมเซอร์โวมอเตอร์โดยใช้ไมโครคอนโทรลเลอร์ PIC
การสร้างสัญญาณ PWM เป็นเครื่องมือสำคัญในคลังแสงของวิศวกรฝังตัวทุกตัวซึ่งมีประโยชน์มากสำหรับการใช้งานจำนวนมากเช่นการควบคุมตำแหน่งของเซอร์โวมอเตอร์การเปลี่ยน IC อิเล็กทรอนิกส์กำลังเพียงไม่กี่ตัวในตัวแปลง / อินเวอร์เตอร์และแม้แต่การควบคุมความสว่างของ LED ในไมโครคอนโทรลเลอร์ PIC สัญญาณ PWM สามารถสร้างได้โดยใช้โมดูล เปรียบเทียบจับภาพและ PWM (CCP) โดยการตั้งค่ารีจิสเตอร์ที่ต้องการเราได้เรียนรู้วิธีการทำเช่นนั้นแล้วในบทช่วยสอน PIC PWM แต่มีข้อเสียเปรียบอย่างหนึ่งสำหรับวิธีการดังกล่าว
PIC16F877Aสามารถสร้างสัญญาณ PWM เฉพาะบนหมุด RC1 และ RC2 ถ้าเราใช้โมดูล CCP แต่เราอาจพบสถานการณ์ที่เราต้องการพินเพิ่มเติมเพื่อให้มีฟังก์ชัน PWM ตัวอย่างเช่นในกรณีของฉันฉันต้องการควบคุมเซอร์โวมอเตอร์ RC 6 ตัวสำหรับโครงการแขนหุ่นยนต์ของฉันซึ่งโมดูล CCP นั้นสิ้นหวัง ในสถานการณ์เหล่านี้เราสามารถเขียนโปรแกรมหมุด GPIO สัญญาณ PWM ผลิตโดยใช้โมดูลจับเวลาด้วยวิธีนี้เราสามารถสร้างสัญญาณ PWM ได้มากที่สุดโดยใช้พินที่ต้องการ นอกจากนี้ยังมีฮาร์ดแวร์แฮ็กอื่น ๆ เช่นการใช้มัลติเพล็กเซอร์ IC แต่ทำไมต้องลงทุนกับฮาร์ดแวร์ในเมื่อสิ่งเดียวกันสามารถทำได้แม้ว่าการเขียนโปรแกรม ดังนั้นในบทช่วยสอนนี้เราจะเรียนรู้วิธีการแปลงพิน PIC GPIO เป็นพิน PWMและเพื่อทดสอบเราจะจำลองบนโปรตีอุสด้วยออสซิลโลสโคปแบบดิจิตอลและควบคุมตำแหน่งของเซอร์โวมอเตอร์โดยใช้สัญญาณ PWMและเปลี่ยนรอบการทำงานโดยเปลี่ยนโพเทนชิออมิเตอร์
สัญญาณ PWM คืออะไร?
ก่อนที่เราจะเข้าสู่รายละเอียดให้เราทำความเข้าใจกับสัญญาณ PWM เล็กน้อย Pulse Width Modulation (PWM)เป็นสัญญาณดิจิทัลที่นิยมใช้ในวงจรควบคุม สัญญาณนี้ตั้งไว้สูง (5v) และต่ำ (0v) ในเวลาและความเร็วที่กำหนดไว้ล่วงหน้า เวลาที่สัญญาณอยู่สูงเรียกว่า "ตรงเวลา" และเวลาที่สัญญาณอยู่ต่ำเรียกว่า "เวลาปิด" มีพารามิเตอร์สำคัญสองประการสำหรับ PWM ดังที่กล่าวไว้ด้านล่าง:
รอบการทำงานของ PWM
เปอร์เซ็นต์ของเวลาที่สัญญาณ PWM ยังคงสูง (ตรงเวลา) เรียกว่าเป็นรอบการทำงาน หากสัญญาณเปิดอยู่เสมอสัญญาณจะอยู่ในรอบการทำงาน 100% และหากปิดอยู่เสมอจะเป็นรอบการทำงาน 0%
Duty Cycle = เปิดเวลา / (เปิดเวลา + ปิดเวลา)
ชื่อตัวแปร |
อ้างถึง |
PWM_Frequency |
ความถี่ของสัญญาณ PWM |
T_TOTAL |
รวมเวลาที่ใช้สำหรับ PWM ครบหนึ่งรอบ |
ตัน |
ตรงเวลาสัญญาณ PWM |
T_OFF |
เวลาปิดสัญญาณ PWM |
Duty_cycle |
รอบการทำงานของสัญญาณ PWM |
ตอนนี้เรามาทำคณิตศาสตร์กัน
นี้เป็นสูตรมาตรฐานที่ความถี่เป็นเพียงซึ่งกันและกันของเวลาค่าความถี่จะต้องได้รับการตัดสินใจและกำหนดโดยผู้ใช้ตามความต้องการของแอปพลิเคชันของเขา / เธอ
T_TOTAL = (1 / PWM_Frequency)
เมื่อผู้ใช้เปลี่ยนค่า Duty cycle โปรแกรมของเราควรปรับเวลา T_ON และเวลา T_OFF โดยอัตโนมัติตามนั้น ดังนั้นสูตรข้างต้นสามารถใช้ในการคำนวณ T_ON ขึ้นอยู่กับมูลค่าของ Duty_Cycle และ T_TOTAL
T_ON = (Duty_Cycle * T_TOTAL) / 100
เนื่องจากเวลารวมของสัญญาณ PWM สำหรับหนึ่งรอบเต็มจะเป็นผลรวมของเวลาตรงและเวลาปิด เราสามารถคำนวณเวลาปิด T_OFFดังที่แสดงไว้ด้านบน
T_OFF = T_TOTAL - T_ON
ด้วยสูตรเหล่านี้เราสามารถเริ่มการเขียนโปรแกรมไมโครคอนโทรลเลอร์ PIC ได้ โปรแกรมนี้เกี่ยวข้องกับโมดูลตัวจับเวลา PIC และโมดูล PIC ADC เพื่อสร้างสัญญาณ PWM โดยใช้วัฏจักรหน้าที่ที่แตกต่างกันตามค่า ADC ในรูปแบบ POT หากคุณยังใหม่กับการใช้โมดูลเหล่านี้ขอแนะนำอย่างยิ่งให้อ่านบทช่วยสอนที่เหมาะสมโดยคลิกที่ไฮเปอร์ลิงก์
การเขียนโปรแกรม PIC เพื่อสร้าง PWM บน GPIO Pins
โปรแกรมที่สมบูรณ์สำหรับการกวดวิชานี้สามารถพบได้ที่ด้านล่างของเว็บไซต์เช่นเสมอ ในส่วนนี้เรามาทำความเข้าใจว่าจริงๆแล้วโปรแกรมเขียนอย่างไร เช่นเดียวกับโปรแกรมอื่น ๆ เราเริ่มต้นด้วยการตั้งค่าบิตการกำหนดค่า ฉันใช้ตัวเลือกมุมมองหน่วยความจำเพื่อตั้งค่าให้ฉัน
// CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT ปิดใช้งาน) #pragma config BOREN = ON // Brown-out รีเซ็ตเปิดใช้งานบิต (เปิดใช้งาน BOR) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 เป็น Digital I / O ต้องใช้ HV บน MCLR ในการเขียนโปรแกรม) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; หน่วยความจำโปรแกรมทั้งหมดอาจถูกเขียนโดยการควบคุม EECON) #pragma config CP = OFF // บิตการป้องกันรหัสหน่วยความจำโปรแกรมแฟลช (ปิดการป้องกันรหัส) // คำสั่ง #pragma config ควรนำหน้าไฟล์โครงการรวม // ใช้โปรเจ็กต์ enums แทน #define สำหรับเปิดและปิด # รวม
จากนั้นเราจะพูดถึงความถี่สัญญาณนาฬิกาที่ใช้ในฮาร์ดแวร์ที่นี่ฮาร์ดแวร์ของฉันใช้คริสตัล 20MHz คุณสามารถป้อนค่าตามฮาร์ดแวร์ของคุณได้ ตามด้วยนั่นคือค่าความถี่ของสัญญาณ PWM เนื่องจากเป้าหมายของฉันที่นี่เพื่อควบคุมเซอร์โวมอเตอร์ RC งานอดิเรกซึ่งต้องการความถี่ PWM ที่ 50Hz ฉันจึงตั้งค่า 0.05KHz เป็นค่าความถี่คุณจึงสามารถเปลี่ยนสิ่งนี้ได้ตามข้อกำหนดการใช้งานของคุณ
#define _XTAL_FREQ 20000000 # กำหนด PWM_Frequency 0.05 // ใน KHz (50Hz)
ตอนนี้เรามีค่าความถี่เราสามารถคำนวณ T_TOTALโดยใช้สูตรที่กล่าวถึงข้างต้น ผลลัพธ์จะพุ่งไปที่ 10 เพื่อให้ได้ค่าของเวลาเป็นมิลลิวินาที ในกรณีของฉันค่า T_TOTAL จะเท่ากับ 2 มิลลิวินาที
int T_TOTAL = (1 / PWM_Frequency) / 10; // คำนวณเวลาทั้งหมดจากความถี่ (เป็นมิลลิวินาที)) // 2msec
ตามด้วยสิ่งนั้นเราเริ่มต้นโมดูล ADC เพื่ออ่านตำแหน่งของโพเทนชิออมิเตอร์ตามที่กล่าวไว้ในบทแนะนำ ADC PIC ของเรา ต่อไปเรามีรูทีนบริการขัดจังหวะซึ่งจะถูกเรียกทุกครั้งตัวจับเวลาจะล้นเราจะกลับไปที่สิ่งนี้ในภายหลังตอนนี้เรามาตรวจสอบฟังก์ชั่นหลักกัน
ภายในฟังก์ชั่นหลักที่เรากำหนดค่าโมดูลจับเวลาที่นี่ฉันได้กำหนดค่าโมดูล Timer ให้ล้นสำหรับทุกๆ 0.1ms ค่าของเวลาสามารถคำนวณได้โดยใช้สูตรด้านล่าง
RegValue = 256 - ((Delay * Fosc) / (Prescalar * 4)) ความล่าช้าเป็นวินาทีและ Fosc เป็นhz
ในกรณีของฉันสำหรับความล่าช้า 0.0001 วินาที (0.1ms) โดยมี prescalar เป็น 64 และ Fosc ที่ 20MHz ค่าของการลงทะเบียนของฉัน (TMR0) ควรเป็น 248 ดังนั้นการกำหนดค่าจะเป็นดังนี้
/ ***** การกำหนดค่าพอร์ตสำหรับ Timer ****** / OPTION_REG = 0b00000101; // Timer0 พร้อมความถี่ภายนอกและ 64 เป็น prescalar // ยังเปิดใช้งาน PULL UPs TMR0 = 248; // โหลดค่าเวลาสำหรับ 0.0001s; delayValue สามารถอยู่ระหว่าง 0-256 เท่านั้น TMR0IE = 1; // เปิดใช้งานบิตขัดจังหวะตัวจับเวลาใน PIE1 register GIE = 1; // เปิดใช้งาน Global Interrupt PEIE = 1; // เปิดใช้งานการขัดจังหวะอุปกรณ์ต่อพ่วง / *********** ______ *********** /
แล้วเราจะต้องตั้งค่าการกำหนดค่าอินพุตและเอาต์พุตที่นี่เรากำลังใช้พิน AN0 สำหรับอ่านค่า ADC และพิน PORTD เพื่อส่งสัญญาณ PWM ดังนั้นให้เริ่มต้นเป็นพินเอาต์พุตและทำให้ต่ำโดยใช้บรรทัดด้านล่างของโค้ด
/ ***** การกำหนดค่าพอร์ตสำหรับ I / O ****** / TRISD = 0x00; // สั่ง MCU ว่าพินทั้งหมดบน PORT D เป็นเอาต์พุต PORTD = 0x00; // เริ่มต้นพินทั้งหมดเป็น 0 / *********** ______ *********** /
ภายในลูป ในขณะที่ ไม่มีที่สิ้นสุดเราต้องคำนวณค่าของเวลาตรง (T_ON) จากรอบการทำงาน รอบ เวลา และ หน้าที่ แตกต่างกันไปตามตำแหน่งของ POT ดังนั้นเราจึงทำซ้ำ ๆ ภายในลูป while ดังที่แสดงด้านล่าง 0.0976 คือค่าที่ต้องคูณด้วย 1024 ถึงจะได้ 100 และในการคำนวณ T_ON เราได้คูณด้วย 10 เพื่อให้ได้ค่าเป็นมิลลิวินาที
ในขณะที่ (1) { POT_val = (ADC_Read (0)); // อ่านค่าของ POT โดยใช้ ADC Duty_cycle = (POT_val * 0.0976); // แผนที่ 0 ถึง 1024 ถึง 0 ถึง 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // คำนวณตรงเวลาโดยใช้หน่วยสูตรเป็นมิลลิวินาที __delay_ms (100); }
ตั้งแต่การจับเวลาการตั้งค่าไปกว่าการไหลทุก 0.1ms การจับเวลาขัดจังหวะบริการประจำ ISR จะได้รับการเรียกร้องให้ทุก 0.1ms ภายในรูทีนบริการเราใช้ตัวแปรที่เรียกว่า count และเพิ่มขึ้นทุกๆ 0.1 มิลลิวินาที วิธีนี้ทำให้เราสามารถติดตามเวลา f ได้ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับอินเตอร์รัปต์ในไมโครคอนโทรลเลอร์ PIC ให้ไปที่ลิงค์
ถ้า (TMR0IF == 1) // แฟล็กตัวจับเวลาถูกทริกเกอร์เนื่องจากตัวจับเวลาล้น -> ตั้งค่าเป็นโอเวอร์โฟลว์สำหรับทุกๆ 0.1ms { TMR0 = 248; // โหลดค่าตัวจับเวลา TMR0IF = 0; // ล้างการ นับ ค่าสถานะขัดจังหวะตัวจับเวลา++; // นับเพิ่มทุกๆ 0.1ms -> count / 10 จะให้ค่า count เป็นมิลลิวินาที}
ในที่สุดมันก็เป็นเวลาที่จะสลับขา GPIO ขึ้นอยู่กับมูลค่าของ T_ON และ T_OFF เรามีตัวแปร นับ ที่ติดตามเวลาเป็นมิลลิวินาที ดังนั้นเราจึงใช้ตัวแปรนั้นเพื่อตรวจสอบว่าเวลาน้อยกว่า ตรงเวลา หรือไม่ถ้าใช่เราจะเปิดพิน GPIO ไว้อย่างอื่นเราจะปิดและปิดไว้จนกว่ารอบใหม่จะเริ่มขึ้น สามารถทำได้โดยเปรียบเทียบกับเวลาทั้งหมดของรอบ PWM หนึ่งรอบ รหัสในการทำเช่นเดียวกันแสดงอยู่ด้านล่าง
ถ้า (นับ <= (T_ON)) // ถ้าเวลาน้อยกว่าเวลา RD1 = 1; // เปิด GPIO อื่น RD1 = 0; // อื่นปิด GPIO ถ้า (count> = (T_TOTAL * 10)) // ปิดไว้จนกว่ารอบใหม่จะเริ่ม นับ = 0;
แผนภูมิวงจรรวม
แผนภาพวงจรสำหรับสร้าง PWM ด้วยพิน GPIO ของไมโครคอนโทรลเลอร์ PICนั้นง่ายมากเพียงแค่จ่ายไฟ PIC ด้วยออสซิลเลเตอร์และเชื่อมต่อโพเทนชิออมิเตอร์เพื่อตรึง AN0 และเซอร์โวมอเตอร์เข้ากับขา RD1 เราสามารถใช้พิน GPIO เพื่อรับสัญญาณ PWM ได้ฉันเลือกแล้ว RD1 เพิ่งออกจากการสุ่ม ทั้งโพเทนชิออมิเตอร์และเซอร์โวมอเตอร์ใช้พลังงานจาก 5V ซึ่งควบคุมจาก 7805 ดังที่แสดงด้านล่างในแผนภาพวงจร
จำลองสถานการณ์
เพื่อจำลองโครงการฉันใช้ซอฟต์แวร์โปรตีอุส สร้างวงจรที่แสดงด้านล่างและเชื่อมโยงรหัสกับการจำลองของคุณและเรียกใช้ คุณควรได้รับสัญญาณ PWM บนขา RD1 GPIO ตามโปรแกรมของเราและวงจรการทำงานของ PWM ควรได้รับการควบคุมตามตำแหน่งของโพเทนชิออมิเตอร์ GIF ด้านล่างแสดงให้เห็นว่าสัญญาณ PWM และเซอร์โวมอเตอร์ตอบสนองอย่างไรเมื่อค่า ADC เปลี่ยนผ่านโพเทนชิออมิเตอร์
การตั้งค่าฮาร์ดแวร์สำหรับควบคุมเซอร์โวมอเตอร์โดยใช้ไมโครคอนโทรลเลอร์ PIC
การตั้งค่าฮาร์ดแวร์ที่สมบูรณ์ของฉันแสดงไว้ด้านล่างสำหรับผู้ที่กำลังติดตามบทช่วยสอนของฉันบอร์ดนี้ควรดูคุ้นเคยเป็นบอร์ดเดียวกับที่ฉันใช้ในบทแนะนำทั้งหมดจนถึงตอนนี้ คุณสามารถดูบทช่วยสอน LED กะพริบได้หากคุณสนใจที่จะรู้ว่าฉันสร้างมันอย่างไร มิฉะนั้นให้ทำตามแผนภาพด้านบนและทั้งหมดควรทำงานได้ดี
อัปโหลดโปรแกรมและเปลี่ยนโพเทนชิออมิเตอร์และคุณจะเห็นเซอร์โวเปลี่ยนตำแหน่งตามตำแหน่งของโพเทนชิออมิเตอร์ การทำงานที่สมบูรณ์ของโครงการจะแสดงในวิดีโอที่ให้ไว้ในตอนท้ายของหน้านี้ หวังว่าคุณจะเข้าใจโครงการและสนุกกับการสร้างหากคุณมีข้อสงสัยโปรดโพสต์ไว้ในฟอรัมและเราจะพยายามตอบอย่างเต็มที่
ฉันวางแผนที่จะดำเนินโครงการนี้ต่อไปโดยการเพิ่มตัวเลือกในการควบคุมเซอร์โวมอเตอร์หลายตัวและสร้างแขนหุ่นยนต์ขึ้นมาคล้ายกับ Arduino Robotic Arm ที่เราสร้างไว้แล้ว ถึงแล้วเจอกัน !!