Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Spartan-6 Servo Control

Status
Not open for further replies.

prakash_kadri

Member level 2
Member level 2
Joined
Apr 11, 2013
Messages
42
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Bangalore
Activity points
1,721
Hi ,

Very recently I tried to learn VHDL using some online courses. With my limited knowledge and using the help of some experts online I wrote below code.

I am using ALINIX SPARTAN 6 XILINX board and Servo KS-3527

(https://www.aliexpress.com/item/KS3...DIY-robot-robotic-arm-gimbal/32877907004.html)

My system clock is 50MHz.

Below program is to generate 64kHz from 50mHz frequency.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-----------------------------------------------
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 780 := 0;
begin
    freq_divider: process (reset, clk) begin
        if (reset = '1') then
            temporal <= '0';
            counter  <= 0;
        elsif rising_edge(clk) then
            if (counter = 780) then
                temporal <= NOT(temporal);
                counter  <= 0;
            else
                counter <= counter + 1;
            end if;
        end if;
    end process;
    clk_out <= temporal;
end Behavioral;



Below program is generate PWM pulse.In order to have a frequency of 20ms->20 * 64=1280--> which is done by implementing counter from 0 to 1279



Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity servo_pwm is
    PORT (
        clk   : IN  STD_LOGIC;
        reset : IN  STD_LOGIC;
       -- pos   : IN  STD_LOGIC_VECTOR(6 downto 0);
        servo : OUT STD_LOGIC
    );
end servo_pwm;
 
architecture Behavioral of servo_pwm is
 
constant pos : std_logic_vector(6 downto 0):= "1111111";     ---Servo Position(pos) I kept constant just to check the program.
 
    -- Counter, from 0 to 1279.
    signal cnt : unsigned(10 downto 0);
    -- Temporal signal used to generate the PWM pulse.
    signal pwmi: unsigned(7 downto 0);
     
begin
    -- Minimum value should be 0.5ms.
    pwmi <= unsigned('0' & pos) + 32;
    -- Counter process, from 0 to 1279.
    counter: process (reset, clk) begin
        if (reset = '1') then
            cnt <= (others => '0');
        elsif rising_edge(clk) then
            if (cnt = 1279) then
                cnt <= (others => '0');
            else
                cnt <= cnt + 1;
            end if;
        end if;
    end process;
    -- Output signal for the servomotor.
    servo <= '1' when (cnt < pwmi) else '0';
end Behavioral;



Mapping both the above codes


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity servo_pwm_clk64kHz is
    PORT(
        clk  : IN  STD_LOGIC;
        reset: IN  STD_LOGIC;
        --pos  : IN  STD_LOGIC_VECTOR(6 downto 0);
        servo: OUT STD_LOGIC
          
    );
end servo_pwm_clk64kHz;
 
architecture Behavioral of servo_pwm_clk64kHz is
    COMPONENT clk64kHz
        PORT(
            clk    : in  STD_LOGIC;
            reset  : in  STD_LOGIC;
            clk_out: out STD_LOGIC
        );
    END COMPONENT;
    
    COMPONENT servo_pwm
        PORT (
            clk   : IN  STD_LOGIC;
            reset : IN  STD_LOGIC;
            --pos   : IN  STD_LOGIC_VECTOR(6 downto 0);
            servo : OUT STD_LOGIC
        );
    END COMPONENT;
         
    signal clk_out : STD_LOGIC := '0';
begin
    clk64kHz_map: clk64kHz PORT MAP(
        clk, reset, clk_out
    );
    
    servo_pwm_map: servo_pwm PORT MAP(
        clk_out, reset, servo
    );
         
end Behavioral;



Test bench:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
 
ENTITY servo_pwm_clk64kHz_tb IS
END servo_pwm_clk64kHz_tb;
 
ARCHITECTURE behavior OF servo_pwm_clk64kHz_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT servo_pwm_clk64kHz
    PORT(
         clk : IN  std_logic;
         reset : IN  std_logic;
         servo : OUT  std_logic
        );
    END COMPONENT;
    
 
   --Inputs
   signal clk : std_logic := '0';
   signal reset : std_logic := '0';
 
    --Outputs
   signal servo : std_logic;
 
   -- Clock period definitions
   constant clk_period : time := 10 ns;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: servo_pwm_clk64kHz PORT MAP (
          clk => clk,
          reset => reset,
          servo => servo
        );
 
   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;
 
 
   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for 100 ns;  
 
      wait for clk_period*10;
 
      -- insert stimulus here 
        
    reset <= '1';
        wait for 50 ns;
        reset <= '0';
 
      wait;
   end process;
 
END;
---------------------


I could able to simulate the above code and got the servo pulse as expected. But the actual servo is not working when connected to FPGA.
Servo is connected to separate 5Volt supply and control signal is connected to FPGA output pin.

Please help to rectify this issue.

Thanks.**broken link removed****broken link removed****broken link removed****broken link removed**


.
 

Attachments

  • Spartan-6.jpg
    Spartan-6.jpg
    259.8 KB · Views: 160
  • ISim_Simulator.JPG
    ISim_Simulator.JPG
    122.7 KB · Views: 150
Last edited by a moderator:

Have you tried checking the signals to the servo with a scope to see if they are there? Are you using the correct pins on the header?

Also, search for info on using clock enables with one clock (or few clocks) instead of dividing clocks and trying to use those (your "temporal" signal). The structure of the FPGA wants to use dedicated clock routes for the registers and the way you are doing it will lead to timing issues at higher speeds.
 
J4 Clk pin.JPGT8 Clk pin.JPGhi bking,

thank you for your reply,
No I haven't tried with Scope,I don't have one :-( . Yes I am using correct I/O pins in the FPGA. . About clock enables can you explain me bit in detail.

Also I have noticed 2 things,
1) When I compile the program in ISE design Suite 14.7 , for clock it assigns automatically pin J4, However as per the datasheet FPGA's global clock Pin is T8. should I assign the clock to T8 or J4?.anyway I tried both pins it dint work. What is the difference between these two clocks?

https://www.scribd.com/document/357977518/AX309-Xilinx-Spartan-6-Development-Board-Users-Manual

2) when my servo is connected to 5V supply with control signal open, the servo moves in random direction when I move my hand or mobile phone closer to it. If I am not wrong servo should not function if there is No control signal correct?. Is it my servo itself is faulty?
 
Last edited:

when my servo is connected to 5V supply with control signal open, the servo moves in random direction when I move my hand or mobile phone closer to it.

A servo shows 'jittery' behavior when exposed to inconsistent control signals. (R/C operators often see it when a second operator is transmitting on the same radio channel nearby.)

Do you leave the control wire unconnected? Then it is at high impedance. It can be like an antenna, responding to unknown waveforms reaching it.
(Normally you control a servo by sending pulses between 1 and 2 mSec long.) If you ground the control wire then I believe the jittery behavior should stop.
 
A servo shows 'jittery' behavior when exposed to inconsistent control signals. (R/C operators often see it when a second operator is transmitting on the same radio channel nearby.)

Do you leave the control wire unconnected? Then it is at high impedance. It can be like an antenna, responding to unknown waveforms reaching it.
(Normally you control a servo by sending pulses between 1 and 2 mSec long.) If you ground the control wire then I believe the jittery behavior should stop.


yes the control wire is unconnected.
 

View attachment 150261View attachment 150262hi bking,

thank you for your reply,
No I haven't tried with Scope,I don't have one :-( . Yes I am using correct I/O pins in the FPGA. . About clock enables can you explain me bit in detail.

Also I have noticed 2 things,
1) When I compile the program in ISE design Suite 14.7 , for clock it assigns automatically pin J4, However as per the datasheet FPGA's global clock Pin is T8. should I assign the clock to T8 or J4?.anyway I tried both pins it dint work. What is the difference between these two clocks?

https://www.scribd.com/document/357977518/AX309-Xilinx-Spartan-6-Development-Board-Users-Manual

2) when my servo is connected to 5V supply with control signal open, the servo moves in random direction when I move my hand or mobile phone closer to it. If I am not wrong servo should not function if there is No control signal correct?. Is it my servo itself is faulty?

Are you saying you didn't write or use an existing ucf file to assign the pins of your design?

If the documentation of the board says the clock comes in on pin T8 then your clock input should be assigned T8 as the pin the clock comes in on in the UCF file. If you didn't do all the assignments or use an existing UCF file provided by the vendor (and having a top-level file that has the same signal names) then don't expect ISE to place the pins where they need to be to work on your board.
 
Are you saying you didn't write or use an existing ucf file to assign the pins of your design?


If the documentation of the board says the clock comes in on pin T8 then your clock input should be assigned T8 as the pin the clock comes in on in the UCF file. If you didn't do all the assignments or use an existing UCF file provided by the vendor (and having a top-level file that has the same signal names) then don't expect ISE to place the pins where they need to be to work on your board.

I wrote .ucf file myself and assigned the pins for each inputs/outputs.

Only Clock input pin I had some doubt. Thank you for clarifying that it should be T8. However, in .ucf file I tried with T8 as clock input and assigned pins for other inputs and outputs, but still the servo dint work. I am unable to find out where I am doing mistake. Let me know if you need more details.
Unfortunately I don't have Scope to measure the PWM at output pin. The board output(PWM) is at 3.3 volts, do I need to use level shifter to bring it to 5 volt before connecting it to servo?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top