Lab 6 Report

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 27

SEMESTER I, ACADEMIC SESSION 2019/2020

SCHOOL OF ELECTRICAL & ELECTRONICS ENGINEERING


UNIVERSITI SAINS MALAYSIA
ENGINEERING CAMPUS

EEM 441 INSTRUMENTATION AND CONTROL LABORATORY

EXPERIMENT 6:
STEPPER MOTOR CONTROL

GROUP 8

Group members: 1) Mohamad Hafiz Bin Ahmad (134914)


2) Ahmad Izzat Zuhaili Bin Azman (134903)
3) Ahmad Baihaqi Bin Ghazali (134902)

Date: 7th November 2019


INTRODUCTION

UNIPOLAR STEPPER MOTOR

Stepper motors are ideally suited for precision control. This motor can be operated in
forward/reverse with controllable speed from a BASIC Stamp or any other microcontroller
through a transistor driver circuit. Some of the applications for this motor include educational
experimentation, robotics and precision mechanical control. The #27964 is a Unipolar (4
phase) 12 VDC, 150 mA motor that takes 3.6 degrees per step [5].

Figure 1: Parralax 4 Phase 12- Volt 75 Ohm Unipolar Stepper Motor

ULN2003

The ULN2003A is an array of seven NPN Darlington transistors capable of


500 mA, 50 V output. It features common-cathode fly-back diodes for switching inductive
loads. The ULN2003 is known for its high-current, high-voltage capacity. The drivers can be
paralleled for even higher current output. Even further, stacking one chip on top of another,
both electrically and physically, has been done. Generally, it can also be used for interfacing
with a stepper motor, where the motor requires high ratings which cannot be provided by
other interfacing devices [4]. The pin location of ULN2003 are as shown in Figure 2 below.
Figure 2: ULN2003A pin location [6].

OBJECTIVES
1. To design digital circuits in FPGA to control stepper motor
2. To use Verilog as a design entry in Altera Quartus II Software
3. To simulate the circuit using Altera Quartus II Software
4. To download the design on Altera DE2 board

EQUIPMENT/SOFTWARE USED
1. Altera Quartus II software
2. Altera DE2 board
3. Parralax 4 Phase 12- Volt 75 Ohm Unipolar Stepper Motor
4. ULN 2003
PROCEDURE

ACTIVITY 1: To write Verilog code to control the motion of a stepper motor


1. Double click Quartus II 7.2 Web Edition
2. Write Verilog code as shown in appendix 6A in the lab manual.
5. Create a symbol for each module stepper motor controller and module divider.
6. Draw a schematic diagram as shown in Figure 3.
7. Assign pin number as shown in Figure 4.
8. The stepper motor is connected to ULN2003A as Figure 5.
9. Download the program on Altera DE2 board.
10. Discuss the result base on your observation on LCD.

Figure 3: Schematic diagram

Figure 4: Pin assignment


Figure 5: Wiring connection

ACTIVITY 2: To write Verilog code to control stepper motor in Altera Quarters II


software

1. Verilog code is written as shown in the appendix section in this report.


2. Create a symbol for each module as explained in Lab 1.
3. Draw a schematic diagram as shown in Figure 6.
4. Assign pin number as shown in Figure 7.
5. Maintain the same wiring connection from activity 1.
6. Download the program on Altera DE2 board.
7. Observe and record the results.

Figure 6: Schematic diagram


Figure 7: Pin assignment
Results

ACTIVITY 1: To write Verilog code to control the motion of a stepper motor

1. Verilog code for module “step”, ”divider”, and ”stepper” in appendix 6A are compiled.
An overview diagram is shown by using netlist viewer in Figure 3 below.

stepper:sl

1 clk

dir dir

mode mode phaseout[3..0] phaseout[3..0]


move move 4' h0 -- ledr[3..0]
reset reset

divider:dl

osc osc

Figure 3: Schematic representation of the design for Activity 1.

2. Pins are assigned as shown in Figure 4 below.

Figure 4: pin assignment for Activity 1.

3. The diagram is downloaded to Altera DE2 Board. A circuit is connected to the board as
shown in Figure 5 and below to run the motor.
Figure 5: Stepper motor connection.

4. Observation:
I. SW16 is used to choose the stepper motor operation mode. 0 for continuous
mode, 1 for step mode
II. SW15 is used to set the direction of rotation of the stepper motor. When SW15 is
off, the stepper motor will rotate in clockwise direction. When SW15 is on, the stepper
motor will rotate in anti-clockwise direction.
III. SW17 is used to control the movement of the stepper motor in step mode. When
SW17 is off, the stepper motor will not rotate. When SW17 is toggled on, the motor
will rotate 3.75° (half step).
IV. The 4 LEDs shows different output when the motor run in different direction.
When the motor rotates in clockwise direction, the LEDs light up in the sequence of
0011, 1001, 1100, 0110 repeatedly. When the motor rotates in anti-clockwise direction,
the LEDs light up in the sequence of 0011, 0110, 1100, 1001 repeatedly.

ACTIVITY 2: To write Verilog code to control stepper motor in Altera Quarters II


software

1. Verilog code for the module in appendix 6B are compiled. An overview diagram is
shown by using netlist viewer in Figure 6 below.

Figure 6: Schematic representation of the design for Activity 2.


2. Pins are assigned as shown in Figure 7 below.

Figure 7: Pin Assignment 2.


3. The diagram is downloaded to Altera DE2 Board. A circuit is connected to the board
as shown in Figure 5 to run the motor.

4. Observation:
I. SW16 is to choose the mode of operation, 0 for continuous and 1 for step.
For step mode, SW17 is used to control the motor movement, 0 will stop the
motor and 1 will rotate the motor.
II. The S12, SW13 and SW14 are used to set the speed of the motor.

SW12 SW13 SW14 Speed


0 0 0 0
1 0 0 1
0 1 0 2
0 0 1 3
Else X

III. SW15 is used to set the direction of the stepper motor. When SW0 is off,
the motor rotates in clockwise direction. When SW1 is on, the motor rotates in
anti-clockwise direction. The second 7-segment from the right is used to shows
the direction of rotation of the motor as shown in Figure 10 below.

Clockwise: Anti-
clockwise:

Figure 10: Motor direction displayed by 7-segment.


.

IV.SW10 is used to reset the LCD. The speed, direction and running mode of
the motor are shown on the LCD screen. Whenever there is a change, the LCD
need to be reset in order to display the changes. The LCD display for all
possible combinations are shown in Figure 11 below.
Figure 11: LCD display for activity 2.
Discussion
1. Stepper motors are discreetly driving DC motors. We have several coils grouped in
"phases" groups. The motor must rotate, one step at a time, by energizing each stage in
a series.
2. The output voltage of Altera DE2 board is not enough to rotate the stepper motor.
Therefore, ULN2003 is used to scale up the voltage that feed into the stepper motor.
The IC is connected between the output from Altera DE2 board and the stepper motor.
The ULN2003 is an array of seven NPN Darlington transistors capable of 500mA, 50V
output. For swapping inductive loads it features common-cathode fly-back diodes. The
12V Unipolar Stepper Motor is the motor we used in this test. The IC's COM pin is
therefore attached to the 12V power supply.
3. In activity 1, the excitation mode of the stepper motor is half step. Half step excitation
is alternating single and dual phase operation resulting in steps that are half the basic
step angle. Due to the smaller step angle, this mode provides twice the resolution and
smoother operation. Half stepping produces roughly 15% less torque than dual phase
full stepping. Figure below shows half step operation of the motor in clockwise
direction [7].

Figure 12: Stepper motor operation in half step mode.

4. In activity 2, when the continuous mode of the stepper motor is chosen, the motor works
in dual phase mode of full step operation. In full step operation, the motor moves
through its basic angle, which is 7.5° for the stepper motor we used in this experiment.
In dual phase mode, also known as “two-phase on, full step” excitation, the motor is
operated with both phases energized at the same time. This mode provides improved
torque and speed performance. Dual phase excitation provides about 30% to 40% more
torque than single phase excitation but does require twice as much power from the
driver. Figure below shows dual phase mode of full step operation in clockwise
direction.
Figure 13: Stepper motor operation in dual phase full step mode.

5. The stepper motor rotates one step for each clock pulse. Therefore, when the motor run
in continuous mode in activity 1 and activity 2, the speed of the stepper motor can be
changed by changing the input frequency of clock pulse. In activity 2, when the input
frequency of clock pulse is fixed, the speed of the motor can be changed by choosing
different bit of output of the frequency divider designed previously using Verilog code.
Conclusion
In conclusion, we learned how to model virtual circuit in FPGA to power stepper
motor through this experiment. In Activity 1, we learned how to write the Verilog code to
control a stepper motor's movement. We learned to write the Verilog code in Activity 2, to
monitor the stepper motor speed, direction, mode (continuous or step).
Appendix

/***********************************************************************/

module step2(CLOCK_50,RST_LCD,reset,dir,mode,move,phaseout,speed, HEX0, LCD_ON, LCD_BLON, LCD_RW, LCD_EN, LCD_RS,


LCD_DATA,);

output [7:0]LCD_DATA; //LCD Data bus 8 bits

output LCD_ON; //LCD Power ON/OFF

output LCD_BLON; //LCD Back Light ON/OFF

output LCD_RW; //LCD Read/Write Select, 0 = Write, 1 = Read

output LCD_EN; //LCD Enable

output LCD_RS; //LCD Command/Data Select, 0 = Command, 1 = Data

input CLOCK_50,RST_LCD;

input reset, mode, dir, move; //reset when asserted brings the shaft to reference position.

input [2:0] speed;

output [3:0] phaseout; //mode specifies step operation or continuous operation.

output [6:0] HEX0;

wire osc,clk; //dir is for clockwise or anti clockwise motion.

//move shifts the shaft by half

assign LCD_ON = 1'b1; //on LCD

assign LCD_BLON = 1'b1;

/* Instantiation of clk divider module.*/

divider d1( .osc (CLOCK_50),.clk (clk),.speed(speed),.clk_1 (clk_1) );

/* Instantiation of controller module.*/

stepper s1(.clk (clk), .clk_1 (clk_1),.reset (reset),.dir (dir),.mode (mode),.move (move),.phaseout (phaseout),.seg_out(HEX0));

LCD_DISP

( .iCLK(CLOCK_50),.iRST_N(RST_LCD),.LCD_DATA(LCD_DATA),.LCD_RW(LCD_RW),.LCD_EN(LCD_EN),.LCD_RS(LCD_RS),.speed(speed),.dir(dir
),.mode(mode),.LCD_BLON(LCD_BLON),. LCD_ON(LCD_ON) );

endmodule

/***********************************************************************/

/***********************************************************************/

module divider (osc, clk, clk_1, speed);


input osc;

input [2:0] speed;

output clk, clk_1;

reg clk,clk_1;

reg [22:0] count;

reg [2:0] num;

always @(posedge osc)

begin

case(speed)

3'b000 :num=3'b000;

3'b001 :num=3'b001;

3'b010 :num=3'b010;

3'b100 :num=3'b011;

endcase

clk_1 = count[22];

count = count + 1;

if (num==3'b000)

clk = 0;

else

clk = count[22-num];

end

endmodule

/***********************************************************************/

/***********************************************************************/

module LCD_DISP ( iCLK,iRST_N,LCD_DATA,LCD_RW,LCD_EN,LCD_RS,dir,speed,mode,LCD_BLON, LCD_ON );

input iCLK,iRST_N, LCD_ON, LCD_BLON;

input dir,mode;

input [2:0] speed;

output [7:0]LCD_DATA;

output LCD_RW,LCD_EN,LCD_RS; // Internal Wires/Registers

reg [5:0] LUT_INDEX;


reg [8:0] LUT_DATA;

reg [5:0] mLCD_ST;

reg [17:0] mDLY;

reg mLCD_Start;

reg [7:0] mLCD_DATA;

reg mLCD_RS;

//reg dispDone; //display done

wire mLCD_Done;

//assign dispDone=0;

//assign INDEX=0;

parameter LCD_INTIAL = 0;

parameter LCD_LINE1 = 5;

parameter LCD_CH_LINE = LCD_LINE1+16;

parameter LCD_LINE2 = LCD_LINE1+16+1;

parameter LUT_SIZE = LCD_LINE1+32+1;

always@(posedge iCLK or negedge iRST_N)

begin

if(!iRST_N)

begin

LUT_INDEX <= 0;

mLCD_ST <= 0;

mDLY <= 0;

mLCD_Start <= 0;

mLCD_DATA <= 0;

mLCD_RS <= 0;

end

else

begin

if(LUT_INDEX<LUT_SIZE)

begin

case(mLCD_ST)

0:

begin

mLCD_DATA <= LUT_DATA[7:0];


mLCD_RS <= LUT_DATA[8];

mLCD_Start <= 1;

mLCD_ST <= 1;

end

1:

begin

if(mLCD_Done)

begin

mLCD_Start <= 0;

mLCD_ST <= 2;

end

end

2:

begin

if(mDLY<18'h3FFFE)

mDLY <= mDLY+1;

else

begin

mDLY <= 0;

mLCD_ST <= 3;

end

end

3:

begin

LUT_INDEX <= LUT_INDEX+1;

mLCD_ST <= 0;

end

endcase

end

else

//dispDone=1;

LUT_INDEX<=4;

end

end

always

begin

begin
case(LUT_INDEX)

// Initial

LCD_INTIAL+0: LUT_DATA <= 9'h038;

LCD_INTIAL+1: LUT_DATA <= 9'h00C;

LCD_INTIAL+2: LUT_DATA <= 9'h001;

LCD_INTIAL+3: LUT_DATA <= 9'h006;

LCD_INTIAL+4: LUT_DATA <= 9'h080; // Line 1

// SPEED

LCD_LINE1+0: LUT_DATA <= 9'h153;//S

LCD_LINE1+1: LUT_DATA <= 9'h150;//P

LCD_LINE1+2: LUT_DATA <= 9'h145;//E

LCD_LINE1+3: LUT_DATA <= 9'h145;//E

LCD_LINE1+4: LUT_DATA <= 9'h144;//D

LCD_LINE1+5: LUT_DATA <= 9'h13D;//=

LCD_LINE1+6:

case (speed)

3'b000: LUT_DATA <= 9'h130;

3'b001: LUT_DATA <= 9'h131;

3'b010: LUT_DATA <= 9'h132;

3'b100: LUT_DATA <= 9'h133;

default: LUT_DATA <= 9'h158;

endcase

LCD_LINE1+7: LUT_DATA <= 9'h120;

LCD_LINE1+8: LUT_DATA <= 9'h120;

// dir=ccw(counterclockwise) / cw(clockwise)

LCD_LINE1+9: LUT_DATA <= 9'h144;//D

LCD_LINE1+10: LUT_DATA <= 9'h149;//I

LCD_LINE1+11: LUT_DATA <= 9'h152;//R

LCD_LINE1+12: LUT_DATA <= 9'h13D;//=

LCD_LINE1+13: LUT_DATA <= 9'h143;//C

LCD_LINE1+14:

if (dir==1)

LUT_DATA <= 9'h143; //C

else

LUT_DATA <= 9'h157; //W


LCD_LINE1+15:

if (dir==1)

LUT_DATA <= 9'h157; //W

else

LUT_DATA <= 9'h120; //space

// Change Line

LCD_CH_LINE: LUT_DATA <= 9'h0C0;

// Line 2

LCD_LINE2+0: LUT_DATA <= 9'h120;//space

LCD_LINE2+1: LUT_DATA <= 9'h120;//space

LCD_LINE2+2: LUT_DATA <= 9'h120;//space

LCD_LINE2+3: LUT_DATA <= 9'h120;//space

LCD_LINE2+4: LUT_DATA <= 9'h14D; //M

LCD_LINE2+5: LUT_DATA <= 9'h14F; //O

LCD_LINE2+6: LUT_DATA <= 9'h144; //D

LCD_LINE2+7: LUT_DATA <= 9'h145; //E

LCD_LINE2+8: LUT_DATA <= 9'h13D; //=

LCD_LINE2+9:

if (mode==0)

LUT_DATA <= 9'h143; //C

else

LUT_DATA <= 9'h153; //S

LCD_LINE2+10:

if (mode==0)

LUT_DATA <= 9'h14F; //O

else

LUT_DATA <= 9'h154; //T

LCD_LINE2+11:

if (mode==0)

LUT_DATA <= 9'h14E; //N

else

LUT_DATA <= 9'h145; //E

LCD_LINE2+12:

if (mode==0)

LUT_DATA <= 9'h154; //T

else

LUT_DATA <= 9'h150; //P


LCD_LINE2+13: LUT_DATA <= 9'h120;//space

LCD_LINE2+14: LUT_DATA <= 9'h120;//space

LCD_LINE2+15: LUT_DATA <= 9'h120;//space

default: LUT_DATA <= 9'h000;

endcase

end

end

LCD_Controller

(.iDATA(mLCD_DATA),.iRS(mLCD_RS),.iStart(mLCD_Start),.oDone(mLCD_Done),.iCLK(iCLK),.
iRST_N(iRST_N),.LCD_DATA(LCD_DATA), .LCD_RW(LCD_RW),.LCD_EN(LCD_EN),.LCD_RS(LCD_RS) );

endmodule

/***********************************************************************/

/***********************************************************************/

module LCD_Controller ( // Host Side // LCD Interface

iDATA,iRS, iStart,oDone,iCLK,iRST_N,LCD_DATA, LCD_RW, LCD_EN,LCD_RS );

// CLK

parameter CLK_Divide = 16;

// Host Side

input [7:0]iDATA;

input iRS,iStart;

input iCLK,iRST_N;

output reg oDone; // LCD Interface

output [7:0] LCD_DATA;

output reg LCD_EN;

output LCD_RW;

output LCD_RS;

// Internal Register

reg [4:0] Cont;

reg [1:0] ST;

reg preStart,mStart;

/////////////////////////////////////////////

// Only write to LCD, bypass iRS to LCD_RS

assign LCD_DATA = iDATA;

assign LCD_RW = 1'b0;

assign LCD_RS = iRS;

/////////////////////////////////////////////

always@(posedge iCLK or negedge iRST_N)

begin
if(!iRST_N)

begin

oDone <= 1'b0;

LCD_EN <= 1'b0;

preStart<= 1'b0;

mStart <= 1'b0;

Cont <= 0;

ST <= 0;

end

else

begin

////// Input Start Detect ///////

preStart<= iStart;

if({preStart,iStart}==2'b01)

begin

mStart <= 1'b1;

oDone <= 1'b0;

end

//////////////////////////////////

if(mStart)

begin

case(ST)

0: ST <= 1; // Wait Setup

1:

begin

LCD_EN <= 1'b1;

ST <= 2;

end

2:

begin

if(Cont<CLK_Divide)

Cont <= Cont+1;

else

ST <= 3;

end

3:

begin
LCD_EN <= 1'b0;

mStart <= 1'b0;

oDone <= 1'b1;

Cont <= 0;

ST <= 0;

end

endcase

end

end

end

endmodule /***********************************************************************/

/***********************************************************************/

module stepper (clk,clk_1,reset,dir,mode,move,phaseout,seg_out);

input clk,clk_1,reset,dir,mode;

input move;

output [3:0] phaseout;

output reg [6:0] seg_out;

reg [3:0] phaseout,position;

reg [2:0] round;

initial seg_out=7'b1001111;

initial phaseout=4'b1100;

always@ (posedge clk_1 )

begin

if (mode==0)

begin

if (dir==1) //clockwise

seg_out <= {seg_out[6],seg_out[0],seg_out[5:1]};

else //anticlockwise

seg_out <= {seg_out[6],seg_out[4:0],seg_out[5]};

end

else

begin

if (move==0)
begin

if (dir==1)//clockwise

seg_out <= {seg_out[6],seg_out[0],seg_out[5:1]};

else//anticlockwise

seg_out <= {seg_out[6],seg_out[4:0],seg_out[5]};

end

end

end

always@(posedge clk or negedge reset)

begin

if(reset==0)

begin // motor resets to 1000 at reset=0

phaseout=4'b1000;

end

else

begin //reset=1

/* Mode=0 for continous motion */

if (mode==0)

begin

if (dir==0)

phaseout <= {phaseout[0],phaseout[3:1]};//dir=1 for clockwise motion

else

phaseout <= {phaseout[2:0],phaseout[3]};//dir=0 for anticlockwise motion

/* Mode=1 for step motion */

end

else

begin

if(move==0)

begin

case (position)

4'b1000 :

if (dir==0)

begin

phaseout=4'b1100; //ledr=phaseout;

end

else

begin

phaseout=4'b1001; //ledr=phaseout;
end

4'b1100 :

if(dir==0)

begin

phaseout=4'b0100; //ledr=phaseout;

end

else

begin

phaseout=4'b1000; //ledr=phaseout;

end

4'b0100 :

if (dir==0)

begin

phaseout=4'b0110; //ledr=phaseout;

end

else

begin

phaseout=4'b1100; //ledr=phaseout;

end

4'b0110 :

if (dir==0)

begin

phaseout=4'b0010; //ledr=phaseout;

end

else

begin

phaseout=4'b0100; //ledr=phaseout;

end

4'b0010 :

if (dir==0)

begin

phaseout=4'b0011; //ledr=phaseout;

end

else

begin

phaseout=4'b0110; //ledr=phaseout;

end

4'b0011 :

if (dir==0)
begin

phaseout=4'b0001; //ledr=phaseout;

end

else

begin

phaseout=4'b0010; //ledr=phaseout;

end

4'b0001 :

if (dir==0)

begin

phaseout=4'b1001; //ledr=phaseout;

end

else

begin

phaseout=4'b0011; //ledr=phaseout;

end

4'b1001 :

if (dir==0)

begin

phaseout=4'b1000; //ledr=phaseout;

end

else

begin

phaseout=4'b0001; //ledr=phaseout;

end

default:

$display("invalid input");

endcase

end

end

end

end

/* Motor moves half step on the negetive edge of move*/

always@(negedge move or negedge reset)

begin

if (reset==0)

begin

position=4'b1000;
end

else if (reset==1)

begin

position=phaseout;

end

end

/* Motor moves half step on the negetive edge of move */

endmodule

You might also like