Note that there are some explanatory texts on larger screens.

plurals
  1. POVHDL simulates fine, but doesn't act the same in hardware
    primarykey
    data
    text
    <p>I've written a few components to move a stepper motor back and forwards. I've simulated it in modelsim and it works as expected, but it won't work the same in hardware at all.</p> <p>Basically I have a motor driving component, which takes a command of number of steps, hold time and speed and then performs the movement. Then I have the control_arbiter, which is just an intermediate bridge that connects components wanting access to the motors and the motor driving components. Finally I have a 'search pattern' component, which basically issues the commands to move the motor back and forth.</p> <p>My problem is that I can't seem to get direction to change when it's running in hardware, regardless of it working in simulation. </p> <p>Any help with this would be greatly appreciated</p> <p>Motor driver:</p> <pre><code>library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity motor_ctrl is port( clk: in std_logic; -- Hardware ports SCLK, CW, EN: out std_logic; -- stepper driver control pins -- Soft ports Speed, steps: in integer; dir: in std_logic; -- 1 = CW; 0 = CCW; hold_time: in integer; -- if &gt; 0, steppers will be held on for this many clock periods after moving ready: out std_logic; -- indicates if ready for a movement activate: in std_logic; -- setting activate starts instructed motion. pos_out: out integer -- starts at 2000, 180deg = 200 steps, 10 full rotations trackable ); end motor_ctrl; architecture behavioural of motor_ctrl is type action is (IDLE, HOLD, MOVE); signal motor_action: action := IDLE; signal clk_new: std_logic; signal position: integer := 2000; signal step_count: integer := 0; signal drive: boolean := false; begin -- Clock divider clk_manipulator: entity work.clk_divide port map(clk, speed, clk_new); -- Drive motors with drive select SCLK &lt;= clk_new when true, '0' when false; pos_out &lt;= position; process(clk_new) -- Counter variables variable hold_count: integer := 0; begin if rising_edge(clk_new) then case motor_action is when IDLE =&gt; -- reset counter vars, disable the driver and assert 'ready' signal hold_count := 0; step_count &lt;= 0; drive &lt;= false; EN &lt;= '0'; ready &lt;= '1'; -- When activated, start moving and de-assert ready signal if(activate = '1') then motor_action &lt;= MOVE; end if; when HOLD =&gt; -- Stop the step clock signal ready &lt;= '0'; drive &lt;= false; -- Hold for given number of clock periods before returning to idle state if(hold_count = hold_time) then motor_action &lt;= IDLE; end if; -- increment counter hold_count := hold_count + 1; when MOVE =&gt; -- Enable driver, apply clock output and set direction ready &lt;= '0'; EN &lt;= '1'; drive &lt;= true; CW &lt;= dir; -- track the position of the motor --if(dir = '1') then -- position &lt;= steps + step_count; --else -- position &lt;= steps - step_count; --end if; -- Increment count until complete, then hold/idle if(step_count &lt; steps-1) then step_count &lt;= step_count + 1; else motor_action &lt;= HOLD; end if; end case; end if; end process; end behavioural; </code></pre> <p>Control_arbiter:</p> <pre><code>entity Control_arbiter is port (clk: in std_logic; EN, RST, CTRL, HALF, SCLK, CW: out std_logic_vector(2 downto 0) -- needs signals for levelling and lock ); end Control_arbiter; architecture fsm of Control_arbiter is type option is (INIT, SEARCH); signal arbitration: option := INIT; -- Motor controller arbiter signals -- ELEVATION signal El_spd, El_stps, El_hold, El_pos: integer; signal El_dir, El_rdy, El_run: std_logic; -- Search signals signal search_spd, search_stps, search_hold: integer; signal search_dir, search_Az_run, search_El_run: std_logic := '0'; -- status signal lock: std_logic := '0'; begin -- Motor controller components El_motor: entity work.motor_ctrl port map(clk, SCLK(0), CW(0), EN(0), El_spd, El_stps, El_dir, El_hold, El_rdy, El_run); -- Search component search_cpmnt: entity work.search_pattern port map( clk, '1', search_dir, search_stps, search_spd, search_hold, El_rdy, search_El_run); process(clk, arbitration) begin if rising_edge(clk) then case arbitration is when INIT =&gt; -- Initialise driver signals EN(2 downto 1) &lt;= "11"; CW(2 downto 1) &lt;= "11"; SCLK(2 downto 1) &lt;= "11"; RST &lt;= "111"; CTRL &lt;= "111"; HALF &lt;= "111"; -- Move to first stage arbitration &lt;= SEARCH; when SEARCH =&gt; -- Map search signals to motor controllers El_dir &lt;= search_dir; El_stps &lt;= search_stps; El_spd &lt;= search_spd; El_hold &lt;= search_hold; El_run &lt;= search_El_run; -- Pass control to search -- Once pointed, begin search maneuvers -- map search signals to motor controllers -- set a flag to begin search -- if new pointing instruction received, break and move to that position (keep track of change) -- On sensing 'lock', halt search -- return to holding that position end case; end if; end process; end fsm; </code></pre> <p>Search Pattern:</p> <pre><code>entity search_pattern is generic (step_inc: unsigned(7 downto 0) := "00010000" ); port (clk: in std_logic; enable: in std_logic; dir: out std_logic; steps, speed, hold_time: out integer; El_rdy: in std_logic; El_run: out std_logic ); end search_pattern; architecture behavioural of search_pattern is type action is (WAIT_FOR_COMPLETE, LATCH_WAIT, MOVE_EL_CW, MOVE_EL_CCW); signal search_state: action := WAIT_FOR_COMPLETE; signal last_state: action := MOVE_EL_CCW; begin hold_time &lt;= 1; speed &lt;= 1; steps &lt;= 2; process(clk) begin if rising_edge(clk) then -- enable if statement case search_state is when LATCH_WAIT =&gt; -- Make sure a GPMC has registered the command before waiting for it to complete if(El_rdy = '0') then -- xx_rdy will go low if a stepper starts moving search_state &lt;= WAIT_FOR_COMPLETE; -- Go to waiting state and get ready to issue next cmd end if; when WAIT_FOR_COMPLETE =&gt; -- Wait for the movement to complete before making next if(El_rdy = '1') then -- Choose next command based on the last if last_state = MOVE_EL_CCW then search_state &lt;= MOVE_EL_CW; elsif last_state = MOVE_EL_CW then search_state &lt;= MOVE_EL_CCW; end if; end if; when MOVE_EL_CW =&gt; dir &lt;= '1'; El_run &lt;= '1'; last_state &lt;= MOVE_EL_CW; search_state &lt;= LATCH_WAIT; when MOVE_EL_CCW =&gt; dir &lt;= '0'; El_run &lt;= '1'; last_state &lt;= MOVE_EL_CCW; search_state &lt;= LATCH_WAIT; when others =&gt; null; end case; -- else step reset on not enable end if; end process; end behavioural; </code></pre> <p>Sim: <a href="http://i.imgur.com/JAuevvP.png" rel="nofollow">http://i.imgur.com/JAuevvP.png</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload