Stepper Controller

Projects you are planning or working on with the Mojo
Post Reply
nubs
Posts: 1
Joined: August 4th, 2014, 9:26 am

Stepper Controller

Post by nubs » August 4th, 2014, 6:37 pm

Hello everyone. I've started working on a stepper controller. It doesn't work yet but I figured I would share my progress. This is my first fpga project so it's not sophisticated and I'm trying to work in steps. My long term goal is make my own cnc or 3d printer controller.

My first approach is to start small and just get speed control. My objective is to pass a string through the serial port and use it to either slow down or speed up. The motor controller I want to interface with is the big easy driver. It needs a step pulse, at least 1 microsecond long and direction pulse, either high or low. I'll worry about the direction pulse later. It should be easy compared to the step.

I originally started by using a using a 10 bit long counter. At a certain point it would send a pulse and then go low. When the counter reached the end, it would start over and send another pulse. I attempted to set up a state machine that would start this counter over a little earlier if the string "w" was detected. It didn't work, probably for a number of reasons. I tested it with a scope and it looked almost, um, AC like. And it was giving me 5 volts which was interesting to say the least. Did I mention this is my first fpga project?

After talking with some people it seams like my approach is the wrong way to go. I was probably messing up the timing. It was suggested I set up a state machine that uses an "and" gate to join pulse sequences together.

I'll post my code even though it doesn't work. I based it off some of the examples. Let me know if you have any ideas or tips. Thanks

Code: Select all

------------Top module---------------------------------
module mojo_top(
    input clk,
    input rst_n,
    input cclk,
    output[7:0]led,
    output spi_miso,
    input spi_ss,
    input spi_mosi,
    input spi_sck,
    output [3:0] spi_channel,
    
	 input avr_tx,
    output avr_rx,
    input avr_rx_busy,
    
	 output motor_step,
          
	 output motor_dir
	 
    );

wire rst = ~rst_n;

assign spi_miso = 1'bz;
assign avr_rx = 1'bz;
assign spi_channel = 4'bzzzz;

assign led[7] = 8'b1;
assign led[6] = 8'b0;
assign led[5] = 8'b1;
assign led[4] = 8'b0;
assign led[3] = 8'b1;
assign led[2] = 8'b0;
assign led[1] = 8'b1;
assign led[0] = 8'b0;

wire [7:0] tx_data;
wire new_tx_data;
wire tx_busy;
wire [7:0] rx_data;
wire new_rx_data;



stepper stepper_1 (
    .clk(clk),
    .rst(rst),
    .period(period),
    .motor_step(motor_step)
);

stepper_fsm stepper_serial_controll(
	.clk(clk),
	.rst(rst),
	.tx_busy(tx_busy),
	.rx_data(rx_data),
	.new_rx_data(new_rx_data),
	.period(period)
	
	);
	
avr_interface avr_serial (
    .clk(clk),
    .rst(rst),
    .cclk(cclk),
    .spi_miso(spi_miso),
    .spi_mosi(spi_mosi),
    .spi_sck(spi_sck),
    .spi_ss(spi_ss),
    .spi_channel(spi_channel),
    .tx(avr_rx), // FPGA tx goes to AVR rx
    .rx(avr_tx),
    .channel(4'd15), // invalid channel disables the ADC
    .new_sample(),
    .sample(),
    .sample_channel(),
    .tx_data(tx_data),
    .new_tx_data(new_tx_data),
    .tx_busy(tx_busy),
    .tx_block(avr_rx_busy),
    .rx_data(rx_data),
    .new_rx_data(new_rx_data)
);

endmodule


--------------Step Pulse Module-------------------------
module stepper (
	input clk,
	input rst,
	input period,
	output motor_step
	
);

reg pwm_d, pwm_q;
reg [10:0] ctr_d, ctr_q;

assign motor_step = pwm_q;

always @(*) begin
	ctr_d = ctr_q + 1'b1;
	
	
	if (ctr_q > 3'd8  & ctr_q < 6'd60  )
		pwm_d = 1'b1;
		
	else
		pwm_d = 1'b0;
	
end

always @(posedge clk) begin
	if (rst) begin
		ctr_q <= 1'b0;
	end 

	if (ctr_q > period) begin
		ctr_q <= 1'b0;
		end
	
	else begin
		ctr_q <= ctr_d;
	end

	pwm_q <= pwm_d;
	
end

endmodule

----------------State machine module-------------

module stepper_fsm(
    
	 input clk,
    input rst,
    output [7:0] tx_data,
    output reg new_tx_data,
    input tx_busy,
    input [7:0] rx_data,
    input new_rx_data,
	 output reg [9:0]period
);
 
localparam STATE_SIZE = 1;

localparam IDLE = 0,
           INCREASE_SPEED = 1,
			  DECREASE_SPEED = 2;
 
reg [STATE_SIZE-1:0] state_d, state_q;
 
reg [3:0] addr_d, addr_q;
period = 9'd512;

always @(*) begin
    state_d = state_q; // default values
    addr_d = addr_q;   // needed to prevent latches
    new_tx_data = 1'b0;
 
    case (state_q) //look for the value of state q
        IDLE: begin
            addr_d = 4'd0;
            if (new_rx_data && rx_data == "w")
                state_d = INCREASE_SPEED;
				if (new_rx_data && rx_data == "s")
					state_d = DECREASE_SPEED;
				end
        INCREASE_SPEED: begin 
            period = period - 9'd256;
            end
			DECREASE_SPEED: begin
				period = period +9'd256;
				end
	
        	  
        default: state_d = IDLE;
    endcase
end
 
always @(posedge clk) begin
    if (rst) begin
        state_q <= IDLE;
    end else begin
        state_q <= state_d;
    end
 
    addr_q <= addr_d;
end
 
endmodule

Post Reply