Make the robot move!

Now that everything is assembled, let 

We'll start off with a short discussion on the motors and the motor driver integrated circuit (IC) that is used to control them. If you'd rather just get the robot moving, skip ahead to the Let's code it section.

Physically, the motor driver is shown in the picture below.

The motor driver on an unassembled WiFi-bot PCBThe motor driver on an unassembled WiFi-bot PCB

How does all of this work? 

What is an IC?

The motor driver we're using is an integrated circuit (IC). The invention and development of the transistor and IC is what launched the semiconductor industry and won Jack Kilby his Nobel Prize in Physics. If you're interested in learning more about how ICs are manufactured, check out the YouTube videos below:

This first group of videos gives an overview of the entire process.

A very brief, high level overview from Intel
A very brief, high level overview from Intel
Global Foundries Sand to Silicon video
An overview of the entire process from a TV program about Texas Instruments
Demonstration of IC packaging solutions available from Quik-Pak

The second group of videos look at already manufactured ICs and use mechanical mills and chemical processes to "decap" (remove the packaging) of the ICs and view them under a microscope.

Zooming into an IC using a DSLR camera and Scanning Electron Microscope
Zooming into an IC using a DSLR camera and Scanning Electron Microscope
Looking at an IC under a microscope
Decapping an IC to look at what is inside

If you want to take a very deep dive into the world of semiconductors and ICs, there are a number of excellent university courses available online covering solid state chemistry, IC design or from MIT, manufacturing, and packaging.

The motor driver

This motor driver is the TB6612FNG, manufactured by Toshiba. This link brings you to the datasheet for the motor driver. In case you're unfamiliar, datasheets are provided by chip manufacturers to explain the function of the device. As indicated in the datasheet, the TB6612FNG is a dual DC motor driver that can take a power supply voltage of up to 15V to drive 2 DC motors with at a continuous 1.2A output current and a peak current of 3.2A for a single 10ms pulse.

The table below shows the pin function, number, and symbol for each pin of the IC.

Chip Pin Number Arduino Pin Number Label Input/Output (I/O) Function
1, 2 Wifi-Robot MotorA 1 AO1 Output channel A ouptut1
3, 4 -Vin (GND) PGND1 Power Power Ground 1
5, 6 Wifi-Robot MotorA 2 AO2 Output channel A output2
7,8 Wifi-Robot MotorB 2 BO2 Output channel B output2
9, 10 -Vin (GND) PGND2 Power Power Ground 2
11, 12 Wifi-Robot MotorB 1 BO1 Output channel B output1
13, 14 +Vin VM2/3 Power Motor supply (2.5-13.5V)
15 11 PWMB Input channel B PWM input
16 13 BIN2 Input channel B input 2
17 12 BIN1 Input channel B input 1
18 -Vin (GND) GND Power Logic Ground (Tied on PCB to PGND1 and PGND2 as well)
19 6 STBY Input When HIGH, allows H-bridges to function (and drive the motors). When LOW, H-bridges are disabled.
20 IOREF (+5V) VCC Power Provides power for the IC (2.7 - 5.5V)
21 3 AIN1 Input channel A input 1
22 4 AIN2 Input channel A input 2
23 5 PWMA Input channel A PWM input
24 +Vin VM1 Power Motor supply (2.5-13.5V)

The table below (copied from the Control Function section of the datasheet) shows us how to use this circuit to control the motors.

IN1 IN2 PWM STBY OUT1 OUT2 Mode
H H H/L H L L Short brake
L H H H L H CCW
L H L H L L Short brake
H L H H H L CW
H L L H L L Short brake
L L H H OFF (High impedance) OFF Stop
H/L H/L H/L L OFF OFF Standby

So, what does this mean? In order to drive a motor "forward" (counter-clockwise/CCW), we set that channel's input 1 to logic level low voltage (GND), input 2 to logic level high voltage (5V), PWM to a voltage level that will set the speed, and standby to high. As shown in the table (row 2) this results in the motor outputs OUT1 at a low voltage and OUT2 at a high voltage, driving the motor counter-clockwise. This can be applied to both the A and B channels to drive both motors simultaneously.

In code, on the Arduino, this results in the following function (where AIN1 and AIN2 are IN1 and IN2 for the A channel (motor A) and BIN1 and BIN2 are IN1 and IN2 for the B channel (motor B):

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
// Move the robot forward for STEPTIME
void goForward ( ) {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    writePwms (STRAIGHTSPEED-leftOffset,STRAIGHTSPEED-rightOffset);
    pwmTimeout = millis() + STEPTIME;
}

We use the Arduino's digitalWrite() function to set the value of the pins. writePwms() is a function shown below that wraps Arduino's analogWrite() function.

Download file Copy to clipboard
1
2
3
4
5
// Function to write out pwm values
void writePwms ( int left, int right) {
    analogWrite (pwms[0], left);
    analogWrite (pwms[1], right);
}

We use the variable pwmTimeout to determine when to turn off the motor by recording the current time in milliseconds (obtained via the millis() function) and adding STEPTIME to that. We'll then compare pwmTimeout to the current time and zero out the voltage to the PWM pins to stop the motors from turning, as shown in the code snippet below.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
if (pwmTimeout > 0) {
	// Check pwmTimeout has not been reached.
	if (millis() > pwmTimeout) {
		// If it has, zero voltage to PWM pins
		pwmTimeout = 0;
		writePwms (0,0);       
	}
}

Let 

First, we'll start with an Arduino sketch that drives the robot forward continuously. Upload the code below to your robot using the Arduino IDE.

If you don't have the Arduino IDE installed, visit the Arduino download page to download it for your operating system (it is free). Then, copy and paste the code below into the IDE and upload it to your robot by plugging in the USB cable and clicking the upload button in the IDE program. Arduino has detailed instructions on Getting started as well as how to upload a program to an Arduino Uno board.

Once you click upload, the robot will upload the code and should start to drive both motors forward immediately. If your robot isn't moving, double check that you have the 4 AA batteries installed. If your robot is driving continuously in a circle, figure out which motor is rotating backwards. Then, remove the batteries to stop the robot. Grab your screwdriver and loosen the terminal blocks for that motor's wired connections, then swap the two wires and tighten the terminal block connector screws to secure them.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Pin assignments
#define AIN1 3
#define AIN2 4
#define APWM 5
#define BIN1 12
#define BIN2 13
#define BPWM 11
#define STBY 6

// Constants for motor control functions
#define STEPTIME 600 
#define STRAIGHTSPEED 200
#define TURNSPEED 120
#define TURNTIME 300

// Array to track current PWM values for each channel (A and B)
int pwms[] = {APWM, BPWM};

// Offsets to be used to compensate for one motor being more powerful
byte leftOffset = 0;
byte rightOffset = 0;

// Variable to track remaining time
unsigned long pwmTimeout = 0;

// Function to write out pwm values
void writePwms ( int left, int right) {
    analogWrite (pwms[0], left);
    analogWrite (pwms[1], right);
}

// Move the robot forward for STEPTIME
void goForward ( ) {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    writePwms (STRAIGHTSPEED-leftOffset,STRAIGHTSPEED-rightOffset);
    pwmTimeout = millis() + STEPTIME;
}

// Move the robot backward for STEPTIME
void goBack() {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    writePwms (STRAIGHTSPEED-leftOffset,STRAIGHTSPEED-rightOffset);
    pwmTimeout = millis() + STEPTIME;
}

// Turn the robot left for TURNTIME
void goLeft () {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);

    writePwms (TURNSPEED,TURNSPEED);
    pwmTimeout = millis() + TURNTIME;
}

// Turn the robot right for TURNTIME
void goRight () {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);

    writePwms (TURNSPEED,TURNSPEED);
    pwmTimeout = millis() + TURNTIME;
}

// Stop the robot (using standby)
void stop(){
    digitalWrite(STBY, LOW); 
}

// Arduino setup function
void setup() {
    // Initialize pins as outputs
    pinMode (STBY, OUTPUT);
    pinMode (AIN1, OUTPUT);
    pinMode (AIN2, OUTPUT);
    pinMode (APWM, OUTPUT);
    pinMode (BIN1, OUTPUT);
    pinMode (BIN2, OUTPUT);
    pinMode (BPWM, OUTPUT);
}

// Loop (code betwen {}'s repeats over and over again)
void loop() {
    // Make the robot go Forward.
    goForward();
}

The following Arduino sketch contains uses the previous code as a base and modifies the loop() function so that the robot drives forward for 1 second, stops for 1 second, drives the robot backward for 1 second, stops for 5 seconds, and then repeats. Upload this code to your robot to see the robot follow the commands you programmed into it.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Pin assignments
#define AIN1 3
#define AIN2 4
#define APWM 5
#define BIN1 12
#define BIN2 13
#define BPWM 11
#define STBY 6

// Constants for motor control functions
#define STEPTIME 600 
#define STRAIGHTSPEED 200
#define TURNSPEED 120
#define TURNTIME 300

// Array to track current PWM values for each channel (A and B)
int pwms[] = {APWM, BPWM};

// Offsets to be used to compensate for one motor being more powerful
byte leftOffset = 0;
byte rightOffset = 0;

// Variable to track remaining time
unsigned long pwmTimeout = 0;

// Function to write out pwm values
void writePwms ( int left, int right) {
    analogWrite (pwms[0], left);
    analogWrite (pwms[1], right);
}

// Move the robot forward for STEPTIME
void goForward ( ) {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    writePwms (STRAIGHTSPEED-leftOffset,STRAIGHTSPEED-rightOffset);
    pwmTimeout = millis() + STEPTIME;
}

// Move the robot backward for STEPTIME
void goBack() {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    writePwms (STRAIGHTSPEED-leftOffset,STRAIGHTSPEED-rightOffset);
    pwmTimeout = millis() + STEPTIME;
}

// Turn the robot left for TURNTIME
void goLeft () {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);

    writePwms (TURNSPEED,TURNSPEED);
    pwmTimeout = millis() + TURNTIME;
}

// Turn the robot right for TURNTIME
void goRight () {
    digitalWrite(STBY, HIGH);
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);

    writePwms (TURNSPEED,TURNSPEED);
    pwmTimeout = millis() + TURNTIME;
}

// Stop the robot (using standby)
void stop(){
    digitalWrite(STBY, LOW); 
}

// Arduino setup function
void setup() {
    // Initialize pins as outputs
    pinMode (STBY, OUTPUT);
    pinMode (AIN1, OUTPUT);
    pinMode (AIN2, OUTPUT);
    pinMode (APWM, OUTPUT);
    pinMode (BIN1, OUTPUT);
    pinMode (BIN2, OUTPUT);
    pinMode (BPWM, OUTPUT);
}

// Loop (code betwen {}'s repeats over and over again)
void loop() {
    // Make the robot go Forward.
    goForward();
    // Wait for one second
    delay(1000);
    // Make the robot stop
    stop();
    // Wait for one second
    delay(1000);
    // Make the robot go backward
    goBack();
    // Wait for one second
    delay(1000);
    // Make the robot stop
    stop();
    // Wait for one second
    delay(1000);
}