ตัวอย่างการควบคุม RC Servo มอเตอร์ ด้วย VHDL และ FPGA ทำใว้ 2 แบบ
แบบที่ 1 กำหนดตำแหน่งใว้ตายตัว 4 ตำแหน่ง การหมุ่นไปในแต่ละตำแหน่ง ใช้สวิทช์ 2 ตัวเป็นตัวเลือก
แบบแรกนี้ โปรแกรม VHDL เขียนใว้ไม่ซับซ้อน เหมาะสำหรับ ศึกษาเทคนิคการเขียน
บล็อกไดอะแกรมมีดังรูป
บล็อกไดอะแกรมสำหรับการทดลอง
การทำงานของเซอร์โวมอเตอร์ (Servo motor)
การควบคุมเซอร์โวมอเตอร์จะทำผ่านสายไฟ 3 เส้น คือสายไฟบวก สายกราวด์ และสายสัญญาณ
สายไฟบวกปกติจะต่ออยู่กับ +5V ส่วนกราวด์ ก็ต่อกับขั่วลบของแหล่งจ่าย การควบคุมตำแหน่งการหมุนของมอเตอร์ ใช้การป้อนสัญญาณพัลส์ ที่มีความถี่ 50 Hz (T = 20 mS) เข้าที่สายสัญญาณ การกำหนดตำแหน่งการหมุนกหนดได้ด้วยความก้วางของพัลส์ (PW) ของสัญญาณ เช่น ถ้า PW = 1.5 ms การหมุนของมอเตอร์จะไปหยุดที่ 90 องศา (ความเที่ยงตรงนี้ขึ้นอยู่กับคุณภาพของมอเตอร์)
รูปแสดงลักษณะความก้วางของพัลส์ ที่สัมพันธ์กับตำแหน่ง
การออกแบบ
โมดูลสร้างสัญญาณ PWM ประกอบด้วยวงจรนับ และวงจรเปรียบเทียบ ถ้าค่าที่นับ น้อยกว่าหรือเท่ากับค่าที่ใช้กำหนดความกว้างของพัลส์ จะให้ลอจิก 1 ออกทางขา Q แต่ถ้ามากกว่า จะให้เป็นลอจิก 0 ถ้าต้องการให้สร้างพัลส์ได้ 200 ขนาด และขนาดเล็กสุด (ความละเอียด) 10 ไมโครวินาที
ค่า PW มีค่าได้ตั้งแต่ 0 ถึง 200 คิดเป็นค่า PW ได้เท่ากับ 0 ถึง 2 ms
ค่า 200 คิดเป็น 2 ms
ค่า 1 = 2000 uS/200 = 10 uS (ความละเอียด)
ดังนั้นความถี่ CLK ที่ใช้นับ = 1/10us = 100 kHz
Counter ต้องนับจาก 0 ถึง 2000 (2000 x 10 uS = 200000 uS = 20 mS) เป็นค่าเวลา (T Period) ของสัญญาณพัลส์
แต่เนื่องจากบอร์ดทดลองที่ใช้ สัญญาณนาฬิกามีความถี่ 50 MHz จึงตั้งมีการหารความถี่ จาก 50MHz ให้เหลือ 100 KHz รายละเอียดตาม บล็อกไดอะแกรมของโมดูลควบคุมเซอร์โวมอเตอร์
บล็อกไดอะแกรมของโมดูลสร้างสัญญาณ PWM (PWM Generator)
บล็อกไดอะแกรมของโมดูลควบคุมเซอร์โวมอเตอร์
โค้ด VHDL
---------------------------------------------------------------------------------------------------------------------------
โมดูลหารความถี่ Divider.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity DIVIDER is
generic (fin: integer := 50000000;
fout: integer := 100000);
port (CLK: in std_logic;
Q : out std_logic );
end DIVIDER;
architecture RTL of DIVIDER is
signal COUNT : integer range 0 to (fin/(2*fout)) ;
signal qs : std_logic := '0';
begin
process (CLK)
begin
if CLK'event and CLK = '1' then
if (COUNT >= (fin/(2*fout)-1)) then
COUNT <= 0;
qs <= not(qs);
else
COUNT <= COUNT +1;
end if;
end if;
end process;
Q <= qs ;
end RTL;
อธิบายโปรแกรม
โปรแกรมนี้ให้สัญญาณเอาท์พุทมี Duty Cycle 50%
entity DIVIDER is
generic (fin: integer := 50000000; กำหนดความถี่อินพุท 50 MHz
fout: integer := 100000); กำหนดค่าความถี่เอาท์พุท 100 KHz
port (CLK: in std_logic;
Q : out std_logic );
end DIVIDER;
----------------------------------------------------------------------------------------
โมดูลสร้างสัญญาณ PWM สำหรับ เซอร์โวมอเตอร์
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity servo_1 is
Port ( clk : in STD_LOGIC;
s : in STD_LOGIC_VECTOR(1 DOWNTO 0);
Qpwm : out STD_LOGIC);
end servo_1;
architecture Behavioral of servo_1 is
signal COUNT : integer range 0 to 2048 ;
signal sq : std_logic;
signal spwm : STD_LOGIC_VECTOR(3 DOWNTO 0);
component DIVIDER is
port (CLK : in std_logic;
Q : out std_logic);
end component;
begin
process (sq)
begin
if sq'event and sq = '1' then
if (COUNT >= 2000) then
COUNT <= 0;
else
COUNT <= COUNT +1;
end if;
end if;
end process;
process (COUNT)
begin
if (COUNT <= 100) then
spwm(0) <= '1';
else
spwm(0) <= '0';
end if;
if (COUNT <= 130) then
spwm(1) <= '1';
else
spwm(1) <= '0';
end if;
if (COUNT <= 150) then
spwm(2) <= '1';
else
spwm(2) <= '0';
end if;
if (COUNT <= 200) then
spwm(3) <= '1';
else
spwm(3) <= '0';
end if;
end process;
Qpwm <= spwm(0) when s = "00" else
spwm(1) when s = "01" else
spwm(2) when s = "10" else
spwm(3);
c1: DIVIDER port map(CLK, sq);
end Behavioral;
ไฟล์ตัวอย่างเพื่อนำไปทดลอง แบบที่ 1
---------------------------------------------------------------------------------------------------------------------------
แบบที่ 2 เป็นการควบคุม ด้วยการใช้ potentiometer (R ปรับค่าได้) แบบนี้สามาถกำหนดตำหน่งการหมุนของมอเตอร์
ได้ทุกตำแหน่ง ตามคลิปวิดีโอ
แบบนี้โค้ด VHDL ค่อนข้างซับซ้อน เพราะต้องมีการสื่อสารกับพอร์ทอนาลอก ของคอนโทรลเลอร์ AVR ATmega32u4
ดูรายละเอียดได้จาก
บล็อกไดอะแกรมมีดังรูป
โค้ด VHDL
---------------------------------------------------------------------------------------------------------------------------
จะนำมาใส่ภายหลัง
ไฟล์ตัวอย่างเพื่อนำไปทดลอง แบบที่ 2
---------------------------------------------------------------------------------------------------------------------------