Servomotor. PWM and VHDL

Status
Not open for further replies.

Gilgamesh90

Newbie level 2
Joined
Jun 30, 2014
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
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:

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.
 

1.Did you simulate your design?
2.What's the PWM frequency that you're trying to generate? I know that hobby grade servos work at around 400Hz - not 10KHz...
 
Last edited:

Thanks for the reply, I already found what the problem was. The frequencu divider has to de divided by 2 so instead of 5000, it has to be 2500 to get a frequency of 10KHz.

Also, 10Khz wont be the frequency to feed the servo, it will be the frequency to generate the pwm to feed the servo.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…