Μια γεννήτρια παλμών με PWM για έλεγχο servo
Για τον έλεγχο του servo πρέπει να παράγουμε μια PWM κυματομορφή. Αυτή η κυματομορφή αποτελείται από δύο τμήματα. Το τμήμα ON στο οποίο η κυματομορφή έχει την μέγιστη τιμή της και το τμήμα OFF στο οποίο έχει την τιμή μηδέν.
Το ON τμήμα ονομάζεται Duty Cycle και μετριέται είτε σε μονάδες χρόνου (ms, us κτλ) είτε σε ποσοστό επί της περιόδου. Εφαρμόζοντας μια PWM κυματομορφή στην τροφοδοσία ενός φορτίου επιτυγχάνουμε να ελέγξουμε το ποσοστό της ισχύος που πέφτει πάνω στο φορτίο. Στην περίπτωσή μας ελέγχουμε τις στροφές του servo.
Αρχικά θα κατασκευάσουμε την PWM γεννήτρια. Το DE0-nano έχει 50MHz ρολόι δηλαδή 20ns περίοδο. Το servo μας χρειάζεται 20ms περίοδο επομένως 20ms/20ns = 1000000 παλμοί των 20ns ισοδυναμούν σε μια περίοδο των 20ms.
Στην συνέχεια πρέπει να ορίσουμε τα άνω και κάτω όρια του duty cycle τα οποία είναι 0.5ns έως και 2.5ns.
dcycle_min = 0.5ms / 20ns = 25000
dcycle_max = 2.5ms / 20ns = 125000
dcycle_mid = (dcycle_max – dcycle_min) / 2 = 75000
Για την περιστροφή του servo θα χρησιμοποιήσουμε τα δύο κουμπιά που διαθέτει το DE0-nano.
Ο κώδικας VHDL:
LIBRARY IEEE;
USE [login to view URL];
ENTITY servo_pwm IS
PORT(
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
button_l : IN STD_LOGIC;
button_r : IN STD_LOGIC;
pwm : OUT STD_LOGIC
);
END servo_pwm;
ARCHITECTURE Behavioral OF servo_pwm IS
CONSTANT period:INTEGER:=1000000;
CONSTANT dcycle_max:INTEGER:=125000;
CONSTANT dcycle_min:INTEGER:=25000;
CONSTANT duty_in:INTEGER:=1000;
SIGNAL pwm_reg,pwm_next:STD_LOGIC;
SIGNAL duty_cycle, duty_cycle_next:INTEGER:=75000;
SIGNAL counter,counter_next:INTEGER:=0;
SIGNAL tick:STD_LOGIC;
BEGIN
--initialize
PROCESS(clk,reset)
BEGIN
IF reset = '1' THEN
pwm_reg <= '0';
counter <= 0;
duty_cycle <= 75000; --start in the middle
ELSIF clk='1' and clk'EVENT THEN
pwm_reg <= pwm_next;
counter <= counter_next;
duty_cycle <= duty_cycle_next;
END IF;
END PROCESS;
counter_next <= 0 WHEN counter = period ELSE counter+1;
tick <= '1' WHEN counter = 0 ELSE '0';
--αλλαγή του Duty Cycle
PROCESS(button_l,button_r,tick,duty_cycle)
BEGIN
duty_cycle_next <= duty_cycle;
IF tick='1' THEN
Συμπληρώστε τον κώδικα του if
END IF;
END PROCESS;
--έξοδος του PWM σήματος
pwm <= pwm_reg;
pwm_next <= '1' WHEN counter < duty_cycle ELSE '0';
END Behavioral;