Adafruit Motor Controller (Video 188)

Adafruit Motor Controller (Video 188)

My name is Ed Malloy. This is my first article for Cheap Controls. This post will show how to control a DC motor and a couple of LEDs with an Adafruit Metro Mini and TB6612 motor controller. The site is beginning a new era. As we move into the control systems market, we will attempt to save the rare and elusive Flutterbird. But, first things first, a simple tutorial about a motor, an LED, and a lot of fun. I will use the help of our residential, and sometimes nemesis, engineer Sarah Jean Williams.

We will build a windmill out of the ingenious product called Lux Blox. We considered a full-scale model but had to adjust it due to the current budget. We are not kidding when we refer to the company as CHEAP Controls. The links below are for the parts used in this tutorial. On the Lux Blox website, you can use the code “cheapcontrols25” for a 25% discount.

THE WINDMILL

Windmill example made out of Lux Blox
Windmill

You can build the windmill however you want. Have fun but be careful. We don’t want any black holes. If you destroy the universe, don’t come back and complain to me. I included a pdf made by my co-worker and sometimes irrational Sarah Jean. If I can get her out of the local shoe stores, she should be putting this information into a post soon.

Custom Adafruit Shield

Working with Cheap Controls, Lux Blox has developed a custom shield that combines the Adafruit TB6612 motor controller with the Adafruit Metro Mini. This tutorial will be using this shield. The shield makes it easy to select the output pins from the Metro Mini before and after the motor controller. It also makes it easy to connect a Nextion Display. We will cover the Nextion display in the following tutorial.

Custom Adafruit Shield

THE SCHEMATIC

I have the circuit configured, as the image below illustrates. The TB6612 controller is considered a motor controller, but I consider it a current/voltage amplifier. This small device can control more than DC motors. One nice feature is the output of the TB6612 can have a higher output voltage than the Arduino or Metro Mini can support. This makes the TB6612 a good low-cost solution for motor control. There are different ways to control the output of the controller board. This tutorial will consider a simple on-and-off configuration.

THE METRO MINI

I have the Metro Mini pins configured as follows

  • D12 – push button input for motor run and direction
  • D11 – push button input for motor run and reverse direction
  • D10 – output to DC motor
  • D09 – output to DC motor
  • D06 – output to an LED
  • D05 – output to the other LED
  • 5V – 5 volt supply – Metro Mini is powered by USB cable from PC
  • GND – GND
  • A01 – Analog input for LED PWM control
  • A02 – Analog input for LED PWM control

Metro Mini Configuration

THE TB6612 BOARD

In this image, it is hard to see the pin names. I will work from left to right and top to bottom. On the bottom row, note the labels for MOTORA and MOTORB. This implies that they need to be motor pins, but this is not the case. Each input is tied to an output and independent of the other.

  • PWMA – connected to 5V not discussed in this tutorial
  • AIN2 – Input from D5 — controls MOTORA right
  • AIN1 – Input from D6 — controls MOTORA left
  • STBY – standby — not connected or discussed in this tutorial
  • BIN1 – Input from D09 — controls MOTORB right
  • BIN2 – Input from D10 — controls MOTORB left
  • PWMB – connected to 5V not discussed in this tutorial
  • GND – GND
  • VCC – Power Input
  • VM – Motor power — connected to VCC

MOTORA is connected to the two led lights and MOTORB is connected to the DC motor

Adafruit TB6612

THE CODE

This website has a lot of tutorials that use the Nextion touch display. We have a standard configuration that is used for the Nextion projects. I am going to use that standard configuration. You can download the starting config below if you want to follow along with the tutorial.

I start by adding some variables. I note my changes to the original code in red. The motor_counter will be used to count up seconds. We will turn the motor on and off based on the current count. The LED1 and LED2 variables will send PWM to the LED. This will show that you can’t pass PWM through the TB6612 board. This will become clear as we work through the tutorial.

// NOTE : Below is a String I use to add to the data sent to the Nextion Display
//        And to verify the end of the string for incoming data.
//        Replace 3 x Serial2.write(0xff);
String  endChar = String(char(0xff)) + String(char(0xff)) + String(char(0xff));
String  dfd  = ""; // data from display
// NOTE : General Async Delay 
unsigned	long asyncDelay = 0;// NOTE : 4,294,967,295
int	delayLength = 1000;
// NOTE : Comment out the next two lines if using an Arduino with more than 1 serial port(MEGA)
#include <SoftwareSerial.h>
SoftwareSerial Serial2(2, 3); // RX, TX

// NOTE :  motor variables
int motor_counter = 0;

In the setup, we configure the Adafruit pins. The Metro Mini is similar to an Arduino UNO, and the UNO should be selected in the IDE. I added the pinMode for each pin used.

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  pinMode(5,OUTPUT); //LED
  pinMode(6,OUTPUT); //LED
  pinMode(9,OUTPUT); // DC motor
  pinMode(10,OUTPUT); // DC motor
  pinMode(11,INPUT_PULLUP); // DC motor switch
  pinMode(12,INPUT_PULLUP); // DC motor switch
  pinMode(A1,INPUT); //LED CONTROL
  pinMode(A2,INPUT); //LED CONTROL
  pinMode(13,OUTPUT);
}

I did not make any changes to the Main loop. We won’t receive any Serial2 input, but I am leaving it in this tutorial because the follow-up will use this portion of the code.

void loop() {
  // NOTE : COLLECT CHARACTERS FROM NEXTION DISPLAY
  if(Serial2.available()){
    inputFunction();
  }
  // NOTE : ASYNC DELAY
  if(millis() > asyncDelay){
    asyncDelay+=delayLength;
    delayFunction();
  }
}

If you have downloaded the starting code from the link above, you will see a tab labeled “delay.” The same code could be placed with the main program tab. If you place it in the main program, place it below the “void loop().” We will do most of the work in this function. To start, we will have the motor change direction every 5 seconds with a 5-second pause between changing direction. Another way to phrase this is 5 seconds clockwise, then 5 seconds stopped, then 5 seconds counterclockwise, then 5 seconds stopped. We will repeat this forever. We are using pins D9 and D10 for the DC motor. I have added some notes to the code to help explain

void delayFunction(){
  digitalWrite(13,!(digitalRead(13)));
  if(motor_counter == 21) motor_counter = 1;
  // NOTE : motor_counter will count to 20

  // NOTE : motor turns one direction for counts 15 - 20
  if(motor_counter < 21 && motor_counter > 15){
    digitalWrite(9, LOW);
    digitalWrite(10, HIGH);
    Serial.println("MOTOR RUNNING");
  }
  // NOTE : motor stopped for counts 11 - 15
  if(motor_counter < 16 && motor_counter > 10){
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    Serial.println("MOTOR STOPPED");
  }
  // NOTE : motor turns other direction for counts 5 - 10
  if(motor_counter < 11 && motor_counter > 5){
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);
    Serial.println("MOTOR RUNNING");
  }
  // NOTE : motor stopped for counts 1 - 5
  if(motor_counter < 6){
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    Serial.println("MOTOR STOPPED");
  }
  motor_counter++;
}

In the video, I show why the controller is necessary. The DC motor won’t run directly powered by the Adafruit Metro Mini. I should probably say the motor shouldn’t run. In some circumstances, the motor will operate, but it is not a good practice. You could damage the Metro Mini.

Now we will switch the motor direction control to physical buttons. The async delay will be increased to help the reaction of pressing the button. You can skip this step if you want to see the effect of a longer delay. You can return to this step and alter the delay rate. I have the code change highlighted below.

// NOTE : Below is a String I use to add to the data sent to the Nextion Display
//        And to verify the end of the string for incoming data.
//        Replace 3 x Serial2.write(0xff);
String  endChar = String(char(0xff)) + String(char(0xff)) + String(char(0xff));
String  dfd  = ""; // data from display
// NOTE : General Async Delay 
unsigned	long asyncDelay = 0;// NOTE : 4,294,967,295
int	delayLength = 50;
// NOTE : Comment out the next two lines if using an Arduino with more than 1 serial port(MEGA)
#include <SoftwareSerial.h>
SoftwareSerial Serial2(2, 3); // RX, TX

// NOTE :  motor variables
int motor_counter = 0;

The delay tab is now changed to take advantage of the buttons. It will take less code to accomplish this, and the results are better. We read the values of the switches and then set the motor pins accordingly. I would encourage you to plug some LEDs in place of the motor and press both switches. You will notice that both lights go off. I did not expect this result, but it must be built into the motor controller because if you place the LEDs on the outputs of the Metro Mini, you see that both lights are on.

void delayFunction(){
  digitalWrite(13,!(digitalRead(13)));
  if(digitalRead(11) == LOW) digitalWrite(9, HIGH);
  else digitalWrite(9, LOW);
  if(digitalRead(12) == LOW) digitalWrite(10, HIGH);
  else digitalWrite(10, LOW);

Now we will take a look at the LEDs. It is important to use bright lights. This is better to show your hunky profile:-) I will show the entire code for the delay tab with the changes in red. It would be best if you placed the LEDs on the Metro Mini side of the motor controller and then moved them to the controller outputs. You will see interesting results. The controller will try to invert the PWM signal on the output that is not in use. Once again, I must stress the importance of watching the YouTube video accompanying this post.

void delayFunction(){
  digitalWrite(13,!(digitalRead(13)));
  if(digitalRead(11) == LOW) digitalWrite(9, HIGH);
  else digitalWrite(9, LOW);
  if(digitalRead(12) == LOW) digitalWrite(10, HIGH);
  else digitalWrite(10, LOW);
  // NOTE : analog read values 0-1025
  // NOTE : PWM uses values 0-255
  // NOTE : we divde analog read by 4 then write it out
  Serial.println(analogRead(A1));
  analogWrite(5,(analogRead(A1)/4));
  analogWrite(6,(analogRead(A2)/4));
}

That’s about it for this tutorial. We will have many more coming out. Thank you for taking the time to read it, and I hope you also enjoyed the video.