0

ステッピングモーターを前後に動かすためのコンポーネントをいくつか作成しました。私はmodelsimでシミュレーションしましたが、期待どおりに機能しますが、ハードウェアではまったく同じようには機能しません。

基本的に私はモーター駆動コンポーネントを持っています。それはステップ数のコマンドを取り、時間と速度を保持してから動きを実行します。次に、control_arbiterがあります。これは、モーターへのアクセスを必要とするコンポーネントとモーター駆動コンポーネントを接続する単なる中間ブリッジです。最後に、「検索パターン」コンポーネントがあります。これは基本的に、モーターを前後に動かすコマンドを発行します。

私の問題は、シミュレーションで動作しているにもかかわらず、ハードウェアで実行しているときに方向を変えることができないように見えることです。

これに関する助けをいただければ幸いです

モータードライバー:

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 > 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 <= clk_new when true,
                    '0' when false;

pos_out <= position;

process(clk_new)
    -- Counter variables
    variable hold_count: integer := 0;      
begin

    if rising_edge(clk_new) then
        case motor_action is

            when IDLE =>
                -- reset counter vars, disable the driver and assert 'ready' signal
                hold_count := 0;
                step_count <= 0;
                drive <= false;
                EN <= '0';
                ready <= '1';

                -- When activated, start moving and de-assert ready signal
                if(activate = '1') then
                    motor_action <= MOVE;
                end if;

            when HOLD =>
                -- Stop the step clock signal
                ready <= '0';
                drive <= false; 
                -- Hold for given number of clock periods before returning to idle state
                if(hold_count = hold_time) then
                    motor_action <= IDLE;
                end if;
                -- increment counter
                hold_count := hold_count + 1;

            when MOVE =>                    
                -- Enable driver, apply clock output and set direction
                ready <= '0';
                EN <= '1';
                drive <= true;
                CW <= dir;      

                -- track the position of the motor
                --if(dir = '1') then    
                --  position <= steps + step_count;
                --else
                --  position <= steps - step_count;
                --end if;

                -- Increment count until complete, then hold/idle
                if(step_count < steps-1) then
                    step_count <= step_count + 1;
                else
                    motor_action <= HOLD;
                end if;

        end case;
    end if;

end process;


end behavioural;

Control_arbiter:

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 =>
                -- Initialise driver signals
                EN(2 downto 1) <= "11";
                CW(2 downto 1) <= "11";
                SCLK(2 downto 1) <= "11";
                RST  <= "111";
                CTRL <= "111";
                HALF <= "111";
                -- Move to first stage
                arbitration <= SEARCH;

            when SEARCH =>
                -- Map search signals to motor controllers
                El_dir  <= search_dir;
                El_stps <= search_stps;
                El_spd  <= search_spd;
                El_hold <= search_hold;
                El_run  <= 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;

検索パターン:

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 <= 1; 
speed <= 1;
steps <= 2;

process(clk)

begin

    if rising_edge(clk) then

        -- enable if statement

            case search_state is

                when LATCH_WAIT =>
                    -- 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 <= WAIT_FOR_COMPLETE;      -- Go to waiting state and get ready to issue next cmd
                    end if;

                when WAIT_FOR_COMPLETE =>

                    -- 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 <= MOVE_EL_CW;
                        elsif last_state = MOVE_EL_CW  then
                            search_state <= MOVE_EL_CCW;
                        end if;
                    end if;             

                when MOVE_EL_CW =>
                    dir <= '1';
                    El_run <= '1';
                    last_state <= MOVE_EL_CW;
                    search_state <= LATCH_WAIT;

                when MOVE_EL_CCW =>
                    dir <= '0';
                    El_run <= '1';
                    last_state <= MOVE_EL_CCW;
                    search_state <= LATCH_WAIT;

                when others =>
                    null;
            end case;

        -- else step reset on not enable

    end if;

end process;

end behavioural;        

シム: http: //i.imgur.com/JAuevvP.png

4

1 に答える 1

1

コードをすばやくスキャンする場合、合成のために変更する必要があることがいくつかあります。

1)クロック分周器:motor_driverプロセスをclk_newではなくclkに敏感にします。クロックを分周するには、nクロックごとに1クロックサイクルのイネーブル信号を生成します。プロセスの開始は次のようになります。

    process(clk)
        ... 
    begin

    if rising_edge(clk) then
        if enable='1' then
            case motor_action is
             ...

2)フォームの初期化

    signal position: integer := 2000;

シミュレーションでのみ機能しますが、合成では機能しません。合成の初期化には、プロセス内でリセット信号を使用します。

3)すべてのステートマシンに「whenothers」句を追加します。この句では、状態が定義された値に設定されます(たとえば、search_state <= INIT)。

于 2013-03-21T21:57:12.567 に答える