IMG_20201013_105104

How to ‘Control a Stepper Motor From Alexa’

I thought this project was going to be really difficult. I’m not a programmer and Internet of Things (IoT) is a long way out of my comfort zones. But how I was wrong…so, let’s control a stepper motor from Alexa!

Among other things, I wanted to control a stepper motor using voice activation. I already use Alexa around my home so it seemed like an obvious link to make. In my case, I needed the stepper motor to ‘home’ itself – that is to say find the ‘closed’ position. Then travel a known distance to the ‘open position’. In addition, I wanted to use a load of parts which I already had left over from other projects.

Wiring up the electronics on this one is really straight forward. And thanks to the fantastic work of a lot of individuals, the programming involved isn’t too complex either. The libraries I use are well documented, have some great examples and generally are really straight forward.

And what am I controlling you ask? Well….a secret bar! If you have read my how to build an industrial sideboard article, you might have noticed I am making a few other units. One of them is a secret bar which will be Alexa controlled.

What you’ll need

Like I said, I wanted to use parts I already had left over from other projects. So you would be able to do this project with lots of alternative parts to the ones I’ve used below:

Parts

  • A controller: ESP32-DevKitC (ESP32-WROOM-32)
  • A Stepper Motor: 2.2A Nema 23
  • A Stepper Driver: A Pololu DRV8825
  • A motor power source: 12v 3A DC Supply
  • A controller power source: I used a 12v to 5v converter
  • Some jumper wires
  • A 100µF capacitor
  • (Optional) A switch for homing
  • (Optional) A breadboard for testing

Software & Libraries

Wiring it all up

The first step is to wiring everything up. To do this we need to understand the pins of our stepper motor driver and controller. Luckily, the Pololu website has a really clear image on how to wire up the driver to a micro-controller:

Taken from pololu.com/

Note the use of the capacitor between the VMOT and GND lines! At this point, it is a really good idea to set the current limiter based on your stepper motor set up. Here is a really clear article with shows you how to do this.

Optional: the SLEEP pin on the driver, is a method of switching off the stepper motor when it is not in use. This is something I wanted to incorporate when my motor was in the ‘closed’ position. So, instead of wiring SLEEP to the logic power supply, I wired it to GPIO0 instead. This allows me to put the motor drive to sleep via the code.

Now we just need to work out which pins to connect to on our ESP32 module (the blue arrows in the above diagram). The ESP32 has lots of GPIO pins options to choose from. All we need to do is connect one of these GPIO pins to the DIR pin on the Stepper, and one to the STEP in. In my case I used pins GPIO 2 and GPIO 4. If you are using the ESP32 DevKitC like I did, then Components 101 has a great article which include the following fantastic diagram:

Image taken from components101.com

Optional: Add in a motor homing switch

Like I mentioned earlier, I needed the stepper motor to ‘home’ itself – that is to say find the ‘closed’ position. Then travel a known distance to the ‘open position’. A common way to do this is to position a switch on your system at the end of its travel. Then, when the motor moves to the ‘closed’ position, the switch is pressed.

I was using a push to make switch. So I connected one side to a +5v line and the other side to GPIO16 on my ESP32. Note, if you are not using a homing switch, you will need to remove the relevant motorHome() section in the code below.

Installing Libraries in the Arduino IDE

If your a beginner like me, let me take a second to tell you how to install a new library into the Arduino IDE. But wait, what is a libary anyway? Well…

Libraries are files written in C or C++ (.c, .cpp) which provide your sketches with extra functionality (e.g. the ability to control an LED matrix, or read an encoder, etc.).

https://www.arduino.cc/

Libraries are basically code that other people have written in order to help you out! And adding a library couldn’t be simpler: just open the Arduino IDE and click on ‘Tools’ > ‘Manage Libraries’ then just search for the library you want. Once you have found the libraries, click ‘Install’.

The two libaries we need to install are:

The Arduino IDE Library Manager

Adding the ESP32 Board in the Arduino IDE

I have used the micro controller known as an ESP32 (DevKit C). By default, the Arduino doesn’t support this board. However, it is really easy to install. Just click on ‘File’ > ‘Preferences’ and in the box for ‘Additional Board Manager URLs:’ copy ‘https://dl.espressif.com/dl/package_esp32_index.json‘.

If you already have something in the additional boards box, you can separate URLs using a comma (,).

Adding the addition board manager URL

Now we have the URL added, we can go to ‘Tools’ > ‘Board’ > ‘Board Manager’ and in the search box, search for ‘ESP32’. Look for ‘esp32 by Espressid Systems’ and then hit ‘Install’.

Once this is installed, go back to ‘Tools’ > ‘Board’ and select your ESP variant from the list. I am using a 32pin ESP32 DevKitC and the ‘ESP32 Dev Module’ works for me.

Lets start simple…moving a stepper

Before we learn how to control a stepper motor with Alexa, it’s always best to start simple and check our wiring! Most libraries come with some sort of example files, and the AccelStepper library is no exception. We are going to use one of these example files to test our setup.

In the Arduino IDE, click on ‘File’ > ‘Examples’ > ‘AccelStepper’ > ‘Constant Speed’. Now there are some slight tweeks we need to make to this code to check our set up.

The first is to define the pins we hooked up to our ESP32. Just below the line which states #include <AccelStepper.h> add the following:

#define dirPin 2 //this is the GPIO pin connected to the DIR pin on the stepper driver
#define stepPin 4 //this is the GPIO pin connected to the STEP pin on the stepper driver

If you used different pins to me, just change them here. The next thing is to add our ‘motor interface type’ as a ‘driver’ (since we are using the DRV8825 driver). So, just below the lines you just inserted, add the following:

#define motorInterfaceType 1

Finally, we need to replace the line AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5 to the following:

AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

Great – our basic code is now complete. So with your ESP hooked up to the USB port on your laptop, now you should be able to flash your new program. If you run into any trouble here try:

  1. Check the COM port is correctly selected under Tools > Port
  2. Check that you have the correct board selected under Tools > Board
  3. On my ESP, I had to hold down the ‘Boot’ button until the fireware started to flash

With any luck, you now have a motor moving around on your desk! Have a play around with the stepper.setMaxSpeed and stepper.setSpeed values to find something that is comfortable with your set up.

Alexa, how the hell do I get you to do something!?

So we are over half way there now. You have your circuit, you’ve flashed some simple code and you have a motor spinning away on your desk. Now it’s time to link this up to your Alexa.

The excellent ESPAlexa libary is focused around smart lighting, but that doesn’t mean it can’t be used for other devices like stepper motors. In my case, I just used the default ESPAlexa code and modified it to suit my needs. Hence you will notice reference to lights in my code where there aren’t any!

Right, starting a new Arduino project, lets step through the code bit by bit so we know what is going on. If you just want the code in its entirety, just skip on down to the final file download.

Defining our pins, values and objects

Like most projects, we start by including our libraries, defining the pins we have used and setting some basic information. Because it sits before the void setup(), this code is not ‘executed’. It merely defines the names and variables we will be using in the rest of the code.

Assuming you are using the same set up as me, the only thing you should need to change in this section is your WiFi details. You can also change the name of your device in the line EspalexaDevice* TheBar; //this is the name of our device for ESPAlexa if your not building a bar!

/*  Alexa controlled Bar Project Aug 2020
 *  Created by Wayne Morton https://MechApe.co.uk, with a lot of work from Aircoookie and Mike McCauley
 *  Code in public domain
 *  Feel free to use, modify, share or completely discard!
 */

#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <Espalexa.h> //awesome lib by Aircoookie
#include <AccelStepper.h> //awesome lib by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/

//pins used to connect my hardware
#define dirPin 2
#define stepPin 4
#define sleep 0
#define homingSwitch 16 //Push to make button

// values
boolean connectWifi();
long homePosition=-1;
int state = HIGH;      //is the bar open (High) or closed (Low)

//callback functions
void firstLightChanged(uint8_t brightness); //this is the fuction for ESPAlexa

// Create a new instance of the AccelStepper class:
#define motorInterfaceType 1
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin); //since we are using an external motor driver

// Wifi Details
const char* ssid = "WIFI-SSID"; //add in your WiFi details here
const char* password = "PASSWORD"; //add in your WiFi detailed here
boolean wifiConnected = false;

Espalexa espalexa;
EspalexaDevice* TheBar; //this is the name of our device for ESPAlexa

The all important Set Up

The void setup() section of any program is a function with runs once at the beginning of the project. Unlike the previous section, this code is executed. In this section of the code we start the serial monitor, connect to WiFi, add our ESPAlexa device and set up our pin modes. Then finally, we call the motorHome() function.

void setup()
{
  Serial.begin(115200); //useful for trouble shooting your code
  delay(1000); //allow time for the serial monitor
  
  // Initialise wifi connection
  wifiConnected = connectWifi();
  
  if(wifiConnected){
    
    // Define your devices here. 
    TheBar = new EspalexaDevice("The Bar", firstLightChanged); //sets 'device[0]' as the 'TheBar' device with friendly name 'The Bar'
    espalexa.addDevice(TheBar);                               //add the device to ESP Alexa
    
    espalexa.begin();
    
  } else
  {
    while (1) {
      Serial.println("Cannot connect to WiFi. Please check data and reset the ESP.");
      delay(2500);
    }
  }
  pinMode(sleep, OUTPUT);
  pinMode(homingSwitch, INPUT);
  delay(10000); //10s wait
  motorHome(); //home the motor on startup so we start from the base
}

Connecting to WiFi

Notice that from our setup function, we called the connectWiFi() function. This function is taken directly from the ESPAlexa code so I won’t go into it here.

Homing our motor

Also from the setup function we called the motorHome() function, so lets discuss that here. As it says on the tin, this function homes the stepper motor….clever right? If you are not homing your motor, you can comment out this from the void setup() and skip this section.

Most homing routines, for example from 3D Printers or CNC Machines, typically reverse a motor until the switch is triggered. Then the motor moves forward slightly, and finally reverses slowly until the switch is triggered again. This allows the system to quickly find home, then accurately find home. However, in my case, I didn’t need accuracy since I planned on disabling the motor power once we had reached home. So my code is relatively simple:

void motorHome(){
  Serial.println("Homing Motor");
  stepper.setMaxSpeed(1000); //initial speed should be low for homing
  digitalWrite(sleep, HIGH); //turn on the stepper driver

  while (digitalRead(homingSwitch)==LOW) { //if the switch is open, loop through this
    stepper.moveTo(homePosition); //move to the current home position
    homePosition--; //decrease the home position by 1
    stepper.runSpeedToPosition(); //move the motor without acceleration
    delay (10); //wait 10ms
  }

  stepper.setCurrentPosition(0);
  Serial.println("Homing Complete");
  digitalWrite(sleep, LOW); //Can now turn off the stepper driver since bar is supported on frame
  state = LOW;
}

Our main loop and ESPAlexa Trigger

The void loop() function for this project couldn’t be simpler since, basically, all we want to do is keep ESPAlexa running. I.e. keep talking to Alexa:

void loop() {
   espalexa.loop();
   delay(1);
}

And that’s it!

The reason I was attracted to the ESPAlexa code was due to it’s simplicity. I am not a programmer by nature so anything that makes my life easy is great! Now the way ESPAlexa handles changes is simple enough.

You may have noticed that in our first section of code, we defined firstLightChanged? Well this the function that will run every time Alexa changes the “state” of our device – i.e. turns on, turns off, set to 50% etc. Why firstLightChanged, well ESPAlexa is intended for lights but can be used for all sorts of devices. You can easily change the name of the function if you like.

For my bar, I decided to keep it simple and only accept values from Alexa which were ON (100%) or OFF (0%). Everything else is ignored. So a simple switchcase based on the “brightness” set up works for me:

void firstLightChanged(uint8_t brightness) {
    Serial.print("Device 1 changed to ");
    
    //do what you need to do here
    switch (brightness) {
      case 255: //switch is on
        Serial.println("The bar is opening");
        barOpen();
        break;
      case 0: //switch is off
        Serial.println("Last orders, the bar is closing");
        barClose();
        break;
      default: //optional - all other cases
        break;
    }

I need a drink, open the bar!

So now we have triggered the barOpen() function which, you’ve guessed it, opens the bar. This is relatively simple whereby we set our speeds and accelerations, turn on the motor and then run to the top position. You will need to experiment to find the speed, acceleration and ‘top’ position for your system.

void barOpen () {
  Serial.println("Bar opening");
  stepper.setMaxSpeed(4000); //motor speed
  stepper.setAcceleration(100); //motor acceleration
  digitalWrite(sleep, HIGH); //turn on the stepper driver
  stepper.moveTo(20000); //top position of lift
  stepper.runToPosition();
  state = HIGH;
}

Last Orders, close the bar 🙁

And just like opening, closing is exactly the same in reverse:

void barClose () {
  Serial.println("Bar closing");
  stepper.moveTo(0);
  stepper.runToPosition();
  digitalWrite(sleep, LOW); //turn off the stepper driver
  state = LOW;
}

The final file

So, that’s it! Now we have the complete code and we can now ‘Control a Stepper Motor From Alexa’. You can download the completed code below:

Adding to Alexa

Assuming everything has gone smoothly, you should be able to add your new device to your Alexa ecosystem like any other device. Try saying “Alexa, discover devices”. Alternatively, head on over to your Alexa app, select ‘Devices’, click the plus symbol and ‘Add Device’. Select light (remember that ESPAlexa is based on a lighting system) and follow the instructions. Add your new device to a group now if you wish.

If this doesn’t work, connect your ESP to your computer using the USB. Then open the Arduino IDE and head over to ‘Tools’, ‘Serial Monitor’ and confirm the baud rate is 115200. Hopefully you’ll see some status updates from your program which will help you troubleshoot. The likelihood is that your ESP isn’t connecting to the Wifi correctly. Check the obvious stiff like Wifi SSID and password.

If it is connecting to the Wifi, try going to http://[yourEspIP]/espalexa and this should display all your ESP devices and their status. Failing that, check out the help section on the ESPAlexa GitHub Page for more trouble shooting tips.

Final Tweaks

From an Alexa side, there are a few tweaks that I made. I found it a little odd saying things things like “Alexa, turn on the bar” or “Alexa, turn off the bar”. So to make things a little more natural sounding, head over to the Alexa app, select ‘more’ and then hit routines. Three easy steps:

  1. Click on the plus symbol and enter a routine name (e.g. bar open)
  2. Add a new trigger (e.g. voice: ‘Alexa, open the bar’).
  3. Add a new action: ‘Smart Home’ > ‘Lightings’ > ‘The Bar’
  4. Optional. Add a new action: ‘Alexa says’ “Cheers!”

Now I can say “Alexa, open the bar” or “Alexa, close the bar”. Here you can also get creative and set music or other lighting to really set the atmosphere in your bar!

I’m still putting the finishing touches on this project from a wood working perspective but I’ll be sure to add some photos up soon. Hopefully this post has been helpful to some of the beginners like me out there! Let me know how you get on in the comments below, or feel free to get in touch via the contact page.

Add a Comment

Your email address will not be published. Required fields are marked *