ステッピングモーターを前後に動かすためのコンポーネントをいくつか作成しました。私は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