9. Chapter Motor & Driver

In this chapter, we will learn how to use a DC motor, including how to control the speed and direction of the motor.

9.1. Project Motor

In this project, we use L293D to drive the DC motor. We can click on the button in the Processing Display Window to control motor direction, and drag the progress bar to control the motor speed.

  1. Raspberry Pi (with 40 GPIO) x1

  2. GPIO Extension Board & Ribbon Cable x1

  3. Breadboard x1

Jumper Wires x22

jumper-wire

Breadboard Power Module x1

power-module

9V Battery (you provide) & 9V Battery Cable

Battery_cable

L293D IC Chip

L2983_chip

DC Motor x1

DC_Motor_Module

9.1.1. Circuit

Use caution: when connecting this circuit, because the DC Motor is a high-power component, do not use the power provided by the RPi to power the motor directly, as this may cause permanent damage to your RPi!

The logic circuit can be powered by the RPi’s power or an external power supply, which should share a common ground with RPi.

Schematic diagram

pr_MD_Sc

Hardware connection.

pr_MD_Fr

9.1.2. Sketch

9.1.2.1. Sketch Motor

First, observe the result after running the sketch, and then learn about the code in detail.

  1. Use Processing to open the file Sketch_09_1_1_Motor.

$ processing ~/Freenove_Kit/Processing/Sketches/Sketch_09_1_1_Motor/Sketch_09_1_1_Motor.pde
  1. Click on “RUN” to run the code.

After the program is executed, a virtual fan, a button and a progress bar are shown on Display Window. Dragging the progress bar can change the motor speed, and the virtual fan will rotate with different speed accordingly. Clicking Button with mouse can change the motor rotation direction.

../../../_images/pr_Motor.png

This project contains a lot of code files, and the core code is contained in the file Sketch_09_1_1_Motor. The other files only contain some custom classes.

../../../_images/processing09_02.png

The following is program code:

 1/*****************************************************
 2 * Filename    : Sketch_09_1_1_Motor
 3 * Description : Control speed and direction of the motor
 4 * auther      : www.freenove.com
 5 * modification: 2024/09/04
 6 *****************************************************/
 7import freenove.processing.io.*;
 8
 9int motorPin1 = 17;    //connect to the L293D
10int motorPin2 = 27;
11int enablePin = 22;
12final int borderSize = 45;    //border size 
13//MOTOR Object 
14MOTOR motor = new MOTOR(motorPin1, motorPin2, enablePin);
15ProgressBar mBar;    //ProgressBar Object
16boolean mMouse = false;    //determined whether a mouse click the ProgressBar
17BUTTON btn;    //BUTTON Object, For controlling the direction of motor 
18int motorDir = motor.CW;    //motor direction
19float rotaSpeed = 0, rotaPosition = 0;  //motor speed
20void setup() {
21  size(640, 360);
22  mBar = new ProgressBar(borderSize, height-borderSize, width-borderSize*2);
23  mBar.setTitle("Duty Cycle");    //set the ProgressBar's title
24  btn = new BUTTON(45, height - 90, 50, 30);   //define the button
25  btn.setBgColor(0, 255, 0);  //set button color
26  btn.setText("CW");        //set button text
27}
28
29void draw() {
30  background(255);
31  titleAndSiteInfo();  //title and site information
32  strokeWeight(4);    //border weight
33  mBar.create();      //create the ProgressBar
34  motor.start(motorDir, (int)(mBar.progress*100));  //control the motor starts to rotate
35  btn.create();      //create the button
36  rotaSpeed = mBar.progress * 0.02 * PI;  //virtual fan's rotating speed
37  if (motorDir == motor.CW) {
38    rotaPosition += rotaSpeed;
39    if (rotaPosition >= 2*PI) {
40      rotaPosition = 0;
41    }
42  } else {
43    rotaPosition -= rotaSpeed;
44    if (rotaPosition <= -2*PI) {
45      rotaPosition = 0;
46    }
47  }
48  drawFan(rotaPosition);    //show the virtual fan in Display window 
49}
50//Draw a clover fan according to the stating angle
51void drawFan(float angle) {    
52  constrain(angle, 0, 2*PI);
53  fill(0);
54  for (int i=0; i<3; i++) {
55    arc(width/2, height/2, 200, 200, 2*i*PI/3+angle, (2*i+0.3)*PI/3+angle, PIE);
56  }
57  fill(0);
58  ellipse(width/2, height/2, 30, 30);
59  fill(128);
60  ellipse(width/2, height/2, 15, 15);
61}
62
63void mousePressed() {
64  if ( (mouseY< mBar.y+5) && (mouseY>mBar.y-5) ) {
65    mMouse = true;    //the mouse click the progressBar
66  } else if ((mouseY< btn.y+btn.h) && (mouseY>btn.y) 
67    && (mouseX< btn.x+btn.w) && (mouseX>btn.x)) { // the mouse click the button
68    if (motorDir == motor.CW) {    //change the direction of rotation of motor
69      motorDir = motor.CCW;
70      btn.setBgColor(255, 0, 0);
71      btn.setText("CCW");
72    } else if (motorDir == motor.CCW) {
73      motorDir = motor.CW;
74      btn.setBgColor(0, 255, 0);
75      btn.setText("CW");
76    }
77  }
78}
79void mouseReleased() {
80  mMouse  = false;
81}
82void mouseDragged() {
83  int a = constrain(mouseX, borderSize, width - borderSize);
84  float t = map(a, borderSize, width - borderSize, 0.0, 1.0);
85  if (mMouse) {
86    mBar.setProgress(t);
87  }
88}
89void titleAndSiteInfo() {
90  fill(0);
91  textAlign(CENTER);    //set the text centered
92  textSize(40);        //set text size
93  text("Motor", width / 2, 40);    //title
94  textSize(16);
95  text("www.freenove.com", width / 2, height - 20);    //site
96}

First define the GPIO pin connected to the Motor, motor class object, the L293D class object, the ProgressBar class object, the Button class object, and some variables.

 1int motorPin1 = 17;    //connect to the L293D
 2int motorPin2 = 27;
 3int enablePin = 22;
 4final int borderSize = 45;    //border size 
 5//MOTOR Object 
 6MOTOR motor = new MOTOR(motorPin1, motorPin2, enablePin);
 7ProgressBar mBar;    //ProgressBar Object
 8boolean mMouse = false;    //determined whether a mouse click the ProgressBar
 9BUTTON btn;    //BUTTON Object, For controlling the direction of motor 
10int motorDir = motor.CW;    //motor direction
11float rotaSpeed = 0, rotaPosition = 0;  //motor speed

Initialize the ProgressBar and Button in setup().

1mBar = new ProgressBar(borderSize, height-borderSize, width-borderSize*2);
2mBar.setTitle("Duty Cycle");    //set the ProgressBar's title
3btn = new BUTTON(45, height - 90, 50, 30);   //define the button
4btn.setBgColor(0, 255, 0);  //set button color
5btn.setText("CW");        //set button text

In function draw(), draw all the contents to be displayed. Then set the motor speed, as well as the speed of virtual fan according to the progress of progress bar. And set the motor direction according to the button flag.

 1void draw() {
 2  background(255);
 3  titleAndSiteInfo();  //title and site information
 4  strokeWeight(4);    //border weight
 5  mBar.create();      //create the ProgressBar
 6  motor.start(motorDir, (int)(mBar.progress*100));  //control the motor starts to rotate
 7  btn.create();      //create the button
 8  rotaSpeed = mBar.progress * 0.02 * PI;  //virtual fan's rotating speed
 9  if (motorDir == motor.CW) {
10    rotaPosition += rotaSpeed;
11    if (rotaPosition >= 2*PI) {
12      rotaPosition = 0;
13    }
14  } else {
15    rotaPosition -= rotaSpeed;
16    if (rotaPosition <= -2*PI) {
17      rotaPosition = 0;
18    }
19  }
20  drawFan(rotaPosition);    //show the virtual fan in Display window 
21}

In the mousePressed(), determine whether the Button is clicked on. If the mouse clicked on the Button, then change the motor direction and the text and color of Button. We have learned how to drag ProgressBar before, so here is no introduction.

 1} else if ((mouseY< btn.y+btn.h) && (mouseY>btn.y) 
 2  && (mouseX< btn.x+btn.w) && (mouseX>btn.x)) { // the mouse click the button
 3  if (motorDir == motor.CW) {    //change the direction of rotation of motor
 4    motorDir = motor.CCW;
 5    btn.setBgColor(255, 0, 0);
 6    btn.setText("CCW");
 7  } else if (motorDir == motor.CCW) {
 8    motorDir = motor.CW;
 9    btn.setBgColor(0, 255, 0);
10    btn.setText("CW");
11  }

Subfunction drawFan(float angle) is used to draw a three-blade fan, based on an initial angle. And the angle between each two blades is 120°. Changing the value of “angle” can make the fan rotate to different angles.

 1void drawFan(float angle) {    
 2  constrain(angle, 0, 2*PI);
 3  fill(0);
 4  for (int i=0; i<3; i++) {
 5    arc(width/2, height/2, 200, 200, 2*i*PI/3+angle, (2*i+0.3)*PI/3+angle, PIE);
 6  }
 7  fill(0);
 8  ellipse(width/2, height/2, 30, 30);
 9  fill(128);
10  ellipse(width/2, height/2, 15, 15);
11}

9.1.2.2. Reference

class MOTOR

This is a custom class that is used to operate the motor controlled by L293D.

public MOTOR (int pin1, int pin2, int enablePin)

Constructor, the first two parameters are GPIO pins connected to the L293D pin, and the enablePin is used to create a PWM pin within the range of 0-100 and with frequency of 100Hz.

public void start (int dir, int speed)

Used to drive motor. Parameter dir represents the rotation direction, whose value is CW, CCW, STOP. Parameter speed is used to decide the duty cycle of PWM. Its value is within the range of 0-100.

About class BUTTON:

class BUTTON

This is a custom class that is used to create a Button.

public BUTTON (int ix, int iy, int iw, int ih)

Constructor, used to create a BUTTON class object. The parameters are for the location and size of the button to be created.

public void create ()

Used to draw Button.

public void setBgColor (int ir, int ig, int ib)

Used to set Button color.

public void setText (String str)

Used to set Button text.

public void setTextColor (int ir, int ig, int ib)

Used to set text color.