+ Post New Thread
Results 1 to 2 of 2
  1. #1
    Newbie level 1
    Points: 14, Level: 1

    Join Date
    Apr 2014
    Posts
    1
    Helped
    0 / 0
    Points
    14
    Level
    1

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

    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
    Click image for larger version. 

Name:	ServoConnection.jpg 
Views:	10 
Size:	56.6 KB 
ID:	104606
    Last edited by andre_teprom; 23rd April 2014 at 22:48. Reason: added VHDL syntax formatting

    •   AltAdvertisment

        
       

  2. #2
    Super Moderator
    Points: 30,136, Level: 42
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    6,937
    Helped
    1654 / 1654
    Points
    30,136
    Level
    42

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

    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


    1 members found this post helpful.

--[[ ]]--