Gilgamesh90
Newbie level 2
- Joined
- Jun 30, 2014
- Messages
- 2
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1
- Activity points
- 18
Hi:
I'm trying to control a servomotor HS-645MG with the Altera FPGA DE0 using VHDL. According to my limited knowledge (and according to other programmers) these are the code for frequency dividing and pwm:
Frequency divider:
PWM
Top-design code
Described with my own words, the frequency is divided by a 5000 factor which yields to a new frequency of 10000Hz (0.1ms). Then the period of the pwm is assigned as 200 so the frequency of pwm will be 20ms and the duty cycle will be controlled with the DE0 built-in switches.
Unfortunately this doesnt work very well when the servo is connected, for example, if the duty cycle is 0.5ms the servo is supposed to moved to one end but instead, it seems to take a 45º position. For every other position, the servo also moves but it doesnt move accordingly to the duty cycle.
I have tested the servo with an arduino uno and works wonders.
What could be the problem?
Any ideas are welcomed.
I'm trying to control a servomotor HS-645MG with the Altera FPGA DE0 using VHDL. According to my limited knowledge (and according to other programmers) these are the code for frequency dividing and pwm:
Frequency divider:
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk64kHz is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk64kHz;
architecture Behavioral of clk64kHz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 4999 := 0;
begin
freq_divider: process (reset, clk) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk) then
if (counter = 4999) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;
PWM
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
-----------------------------------------------------
entity pwm is
port(
clr : in std_logic;
clk : in std_logic;
duty : in std_logic_vector (7 downto 0);
period : in std_logic_vector (7 downto 0);
pwm : out std_logic
);
end pwm;
-----------------------------------------------------
architecture pwm of pwm is
signal count : std_logic_vector(7 downto 0);
begin
cnt: process(clk, clr) -- 4 bit counter
begin
if clr = '1' then
count <= "00000000";
elsif clk'event and clk = '1' then
if count = period -1 then
count <= "00000000";
else
count <= count +1;
end if;
end if;
end process cnt;
pwmout: process(count, duty)
begin
if count < duty then
pwm <= '1';
else
pwm <= '0';
end if;
end process pwmout;
end pwm;
Top-design code
Code:
-----------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
-----------------------------------------------------
entity pwm_top is
port(
clr : in std_logic;
clk : in std_logic;
duty : in std_logic_vector (7 downto 0);
pwm : out std_logic
);
end pwm_top;
-----------------------------------------------------
architecture pwm_top of pwm_top is
signal new_clock : std_logic;
begin
clk_div: entity work.clk64kHz
port map(
clk => clk, reset => '0', clk_out => new_clock);
Pulse: entity work.pwm
port map(
clr => clr, clk => new_clock, duty => duty, period => "11001000", pwm => pwm);
end pwm_top;
Described with my own words, the frequency is divided by a 5000 factor which yields to a new frequency of 10000Hz (0.1ms). Then the period of the pwm is assigned as 200 so the frequency of pwm will be 20ms and the duty cycle will be controlled with the DE0 built-in switches.
Unfortunately this doesnt work very well when the servo is connected, for example, if the duty cycle is 0.5ms the servo is supposed to moved to one end but instead, it seems to take a 45º position. For every other position, the servo also moves but it doesnt move accordingly to the duty cycle.
I have tested the servo with an arduino uno and works wonders.
What could be the problem?
Any ideas are welcomed.