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.

Control PWM servo motor (Futaba S3003) with VHDL on Basys2 board

Status
Not open for further replies.

NOTSam

Newbie level 1
Joined
Apr 23, 2014
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
28
I am trying to control two Futaba S3003 servo motor with a basys2 board. I understand that the servo works of pulse width modulation and have done the required calculations to create the correct pulse widths.

I have written the implementation constraints to output on the the JA and JB terminals. I have tested the system with an oscilloscope/multimeter and have not been able to detect any output on the pins. Can anyone help me understand what I am doing wrong?


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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity Final_v1 is
    Port ( tup  : in STD_LOGIC;
              tdown: in STD_LOGIC;
              gclose : in STD_LOGIC;
              gopen  : in STD_LOGIC;
              reset : in STD_LOGIC;
              grip : out  STD_LOGIC;
              clk  : in STD_LOGIC;
           tilt : out  STD_LOGIC);
end Final_v1;
 
architecture Behavioral of Final_v1 is
    
        constant period:integer:=1000000;
      constant dcycle_max:integer:=100000;
      constant dcycle_min:integer:=50000;
      constant duty_in:integer:=200;
        
        signal tilt_reg,tilt_next:std_logic;
      signal grip_reg,grip_next:std_logic;
        
        
      signal gduty_cycle,gduty_cycle_next:integer:=0;
      signal gcounter,gcounter_next:integer:=0;
        
      signal tduty_cycle,tduty_cycle_next:integer:=0;
      signal tcounter,tcounter_next:integer:=0;
        
      signal gtick:std_logic;
      signal ttick:std_logic;
         
     begin   
     
--begin grip 
 
         process(clk,reset)
              begin
                   if reset = '1' then
                        grip_reg<='0';
                        gcounter<=0;
                        gduty_cycle<=0;
                   elsif clk='1' and clk'event then
                         grip_reg<=grip_next;
                         gcounter<=gcounter_next;
                         gduty_cycle<=gduty_cycle_next;
                   end if;
             end process;
 
            gcounter_next<= 0 when gcounter = period 
                else
            gcounter+1;
            gtick<= '1' when gcounter= 0 
                else
            '0';
 
--Changing Duty Cycle
   process(gclose,gopen,gtick,gduty_cycle)
        begin
             gduty_cycle_next<=gduty_cycle;
              if gtick='1' then
                   if gclose ='1' and gduty_cycle >dcycle_min then
                          gduty_cycle_next<=gduty_cycle-duty_in;
                   elsif gopen ='1' and gduty_cycle < dcycle_max then
                          gduty_cycle_next<=gduty_cycle+duty_in;
                  end if;             
            end if;                           
      end process;
 
 
--Buffer
grip<=grip_reg;    
grip_next<= '1' when gcounter < gduty_cycle 
    else
        '0';    
                                 
--end grip                               
 
--Begin tilt
 
 process(clk,reset)
              begin
                   if reset = '1' then
                        tilt_reg<='0';
                        tcounter<=0;
                        tduty_cycle<=0;
                   elsif clk='1' and clk'event then
                         tilt_reg<=tilt_next;
                         tcounter<=tcounter_next;
                         tduty_cycle<=tduty_cycle_next;
                   end if;
             end process;
 
tcounter_next<= 0 when tcounter = period else
                           tcounter+1;
ttick<= '1' when tcounter= 0 else
             '0';
 
--Changing Duty Cycle
   process(tup,tdown,ttick,tduty_cycle)
        begin
             tduty_cycle_next<=tduty_cycle;
              if ttick='1' then
                   if tup ='1' and tduty_cycle >dcycle_min then
                          tduty_cycle_next<=tduty_cycle-duty_in;
                   elsif tdown ='1' and tduty_cycle < dcycle_max then
                          tduty_cycle_next<=tduty_cycle+duty_in;
                  end if;             
            end if;                           
      end process;
--Buffer
tilt<=tilt_reg;    
tilt_next<= '1' when tcounter < tduty_cycle else
                         '0';    
                                 
--end tilt                                                           
end Behavioral;



Here is my setup
ServoConnection.jpg
 
Last edited by a moderator:

Get rid of all the _next garbage it's just making the design less readable, perform the assignments of _next signals in the sequential process.

Instead of doing this...

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
process (clk, reset) begin
  if reset = '1' then
    gcounter    <= 0;
  elsif clk='1' and clk'event then
    gcounter    <= gcounter_next;
  end if;
end process;
 
gcounter_next <= 0 when gcounter = period
                   else gcounter +1;



You should have done the following...

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
process (clk, reset) begin
  if reset = '1' then
    gcounter    <= 0;
  elsif rising_edge(clk) then
    if gcounter = period then
      gcounter <= 0;
    else
      gcounter <= gcounter +1;
    end if;
  end if;
end process;



This is going to glitch like crazy as all the comaparisons are done with 32-bit values (integer). I guarantee the routing won't be the same for all the bits.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
gtick <= '1' when gcounter= 0 
             else '0';
 
--Changing Duty Cycle
process(gclose,gopen,gtick,gduty_cycle) begin
  gduty_cycle_next<=gduty_cycle;
  if gtick='1' then
    if gclose ='1' and gduty_cycle >dcycle_min then
      gduty_cycle_next<=gduty_cycle-duty_in;
    elsif gopen ='1' and gduty_cycle < dcycle_max then
      gduty_cycle_next<=gduty_cycle+duty_in;
    end if; 
  end if; 
end process;



I can keep going, but it's just more of the same observations. You need to think about what the code represents. Sequential processes (clocked) end up becoming flip-flops and the combinational processes become the logic between the registers.

You also have an asynchronous reset that is an input to this component. Unless this is a sub-component in a top level that asyncrhonous reset may cause problems as it is unlikely to be debounced or able to make any sort of recovery removal time.

If you coded this properly your 119 lines would have likely been 80 lines or less.

Regards
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top