Introduction: Motorize IoT With ESP8266

About: IT-professional by day, DIY hobbyist (among other things) on my free time. I always have one or more projects going on. Usually something to do with home improvement or a tech project or a combination of the t…

IoT is the big buzz these days and it can mean just about anything. For me IoT means that cheap off-the shelf components can enable me to affordably make, monitor and control just about anythything I can imagine.

Despite IoT in the heading, this is not about how to connect the ESP8266 to the internet. There are plenty of other tutorials about that and I will share my own example in the second instructable in this series. This instructable is about how to use the ESP8266 based NodeMCU prototype board with a motor control board to control two types of motors. This is the first instructable in a series of two. This first one will focus on how to get the motors spinning. See it as a technology demo rather than a finished project. The second one will be an example of an actual project that you can do. ESPs can also contol RC servos but there is no particular reason to use this board combo for that. You can hook servos up to any ESP board so long as you don't power the servo from the board.

Covered in this instructable:

  • DC motor control. The motor board supports the use of two DC motors with individual speed and direction control. Speed is controlled through pulse width modulation (PWM) and direction is controlled pulling a powered pin high or low, effectively reversing the PWM polarity.
  • Stepper motor control. The board supports one stepper motor. ESP8266 boards can control steppers with other boards that sometimes ship in bundles with the motors. However, with those boards you have a lot more loose wires. Personally I prefer this shield since everything is in one piece.

Why not use Arduino?

Arduino's have a lot of advantages in that they come in a limited number of pinouts thus allowing manufacturers to make all kinds of snap-on shields and addons for everything under the sun. The ESP boards have less addons and are not as robust but they have other features which make them very powerful for IoT projects. Among other things, the ESP-boards feature itegrated WiFi, more memory (than most Ardu's) and a more powerful CPU.

Update: Please read part two which includes a practical example https://www.instructables.com/id/Motorized-WiFi-IK...

Step 1: Items Used

For this instructable I used the following items from Gearbest:

A word of warning. Make sure you get NodeMCU 1.0. Gearbest also sell NodeMCU 0.9 (aka v1). It won't fit in the motor shield (I have first hand experience).

Step 2: The Motor Shield

The featured motor shield is manufactured by Shenzhen Doctors of Intelligence & Technology (I like the name). Whilst the board is pretty solid and well though out I find that that the documentation is lacking. The board is often sold bundled in a WiFi robo car kit for which software is available. That software is what I used instead of documentation. However, I couldn't find anything about using the driver with with stepper motors. Hopefully this instructable will shed some light on the matter.

Motor Shield documentation

WiFi Robo Car source

In essence, the motor shield features:

  1. Four powered outputs controlled by NodeMCU IO 1, 2, 3 and 4
  2. Optional dual voltage for motors and NodeMCU
  3. Convenience breakout for all relevant pins

The motor power pins are labeled as A-, A+, B- and B+. The nodemcu and Arduino GPIO is not mapped the same. If you try to use the D1 pin as io-pin 1 in Arduino IDE it will not work. In Arduino You will have to use D1 (which is an alias to 5 or just 5. The pins are mapped like this:

Board pin |NodeMCU GPIO |Arduino IDE
A-15 or D1
A+30 or D3
B-24 or D2
B+42 or D4

Step 3: The ESP-12E (NodeMCU)

The NodeMCU 1.0 (aka v2) is a very nice board to work with. Other ESP8266 boards that I have worked with require 3.3v and also need special wiring for flashing. The NodeMCU has an on-board 3.3v voltage regulator so it can be powered from the same microusb-cable that is used to program it. It also has on-board buttons for flash-mode and reset.

NodeMCU boards can be delivered with different firmwares. For this Instructable I choose to use the NodeMCU Lua firmware. You can achieve the same thing with the Arduino IDE. It could be useful to know that even though the Lua firmware was developed for the NodeMCU board it can be used with any ESP board. Lua is a scripting language and is powerful and featurefull. The NodeMCU Lua environment also features a file system. There are plenty of modules in the firmware but you may situations when you have to resort to the Arduino IDE just to take advantage of some specific Library.

Let's assume you got a board without Lua firmware:

  1. Download ESP8266flasher here
  2. Download Lua firmware here. Alternatively you can cook you own here.
  3. Unpack the binary and flash the fimware with ESP8266flasher. Hold the flash button then reset to put the device in flash mode. If you run into trouble, more info can be found on the previous links.
  4. Download and install NodeMCU Lua IDE ESPlorer from here

Firmware and modules documentation is found here.

General Lua language documentation is found on lua.org.

Step 4: Driving DC Motors

The A+ pin (D1) controls the PWM out for the first DC motor and the A- (D3) pin controls direction. The PWM-out drives the motor and allow fors speed control. For instance, a 50% duty cycle in effect creates a lower out voltage. It has nothing to do with pulse count. The A- direction control simply goes low or high, effectively reversing voltage and as such the spin direction of the motor. Please note that you can drive the motors with separate power (usually higher voltage) by connecting motor power to VM and NodeMCU power to VIN. Important note: If you use two power sources, remove the jumper which connects VM and VIN.

To try it, do this:

  1. Connect the (-) (usually black) lead from the motor to A-
  2. Connect the (+) (usually red) lead from the motor to A+
  3. Attach motor B in the same way
  4. Using ESPlorer, upload init.lua (below)

After the upload, reset and watch the motors turn, reverse and stop. To repeat, press reset again. Obviusly this particular behaviour is not very useful other than for demo purposes. The motors should be controlled over wifi but that is for part two of this instructable. After loading/running the file you can control the motors from the ESPlorer command linte with calls to the motor functions, e. g.

> motor_a(FWD, 100)

--motordrive: init.lua
pin_a_speed = 1
pin_a_dir = 3
pin_b_speed = 2
pin_b_dir = 4
FWD = gpio.HIGH
REV = gpio.LOW
duty = 1023
--initiate motor A
gpio.mode(pin_a_speed,gpio.OUTPUT)
gpio.write(pin_a_speed,gpio.LOW)
pwm.setup(pin_a_speed,1000,duty) --PWM 1KHz, Duty 1023
pwm.start(pin_a_speed)
pwm.setduty(pin_a_speed,0)
gpio.mode(pin_a_dir,gpio.OUTPUT)
--initiate motor B
gpio.mode(pin_b_speed,gpio.OUTPUT)
gpio.write(pin_b_speed,gpio.LOW)
pwm.setup(pin_b_speed,1000,duty) --PWM 1KHz, Duty 1023
pwm.start(pin_b_speed)
pwm.setduty(pin_b_speed,0)
gpio.mode(pin_b_dir,gpio.OUTPUT)
-- speed is 0 - 100
function motor(pin_speed, pin_dir, dir, speed)
    gpio.write(pin_dir,dir)
    pwm.setduty(pin_speed, (speed * duty) / 100)
end
function motor_a(dir, speed)
    motor(pin_a_speed, pin_a_dir, dir, speed)
end
    
function motor_b(dir, speed)
    motor(pin_b_speed, pin_b_dir, dir, speed)
end
    
-------------------------------------------------
--start motors 100% speed forward
motor_a(FWD, 100)
motor_b(FWD, 100)
--reverse motors after 4s
tmr.register(0, 4000, tmr.ALARM_SINGLE, function() 
    motor_a(REV, 100)
    motor_b(REV, 100)
end)
tmr.start(0)
--turn motors off after 8s
tmr.register(1, 8000, tmr.ALARM_SINGLE, function() 
    motor_a(FWD, 0)
    motor_b(FWD, 0)
end)
tmr.start(1)

Step 5: Driving Stepper Motors

For the this demo, I have used a standard unipolar (5 wires) 28BYJ-48 geared stepper motor. Read more about steppers here.

  1. Attach the wires
    1. Blue -> A-
    2. Pink -> A+
    3. Yellow -> B-
    4. Orange -> B+
    5. Red -> VM
  2. Using ESPlorer, upload init.lua and stepper.lua

After the upload, reset and watch the motor turn half a revolution (2048 steps), reverse and stop. To repeat, press reset again. As for the DC motors the stepper motor should be controlled over wifi for most projects. You can run the stepper from the command line with the step_move function.

init.lua

--init.lua<br>--
dofile("stepper.lua")
--
FWD=1
REV=-1
--
ROTATION_FULL=4096 --One revolution, 28BYJ-48 geared stepper motor
ROTATION_HALF=ROTATION_FULL / 2
--
step_move(ROTATION_HALF,FWD,1)
tmr.register(0, 5000, tmr.ALARM_SINGLE, function() 
    step_move(ROTATION_HALF,REV,1) 
end);
tmr.start(0);

stepper.lua (credits to: wakenils http://www.esp8266.com/viewtopic.php?f=19&t=2326)

-- stepper.lua<br>-- code from: http://www.esp8266.com/viewtopic.php?f=19&t=2326
-- simple stepper driver for controlling a stepper motor with a
-- l293d driver
-- nodemcu pins:  0  5  6  7
stepper_pins = {1,3,2,4} -- (A-)blue, (A+)pink, (B-)yellow, (B+)orange
-- half or full stepping
step_states4 = {
 {1,0,0,1},
 {1,1,0,0},
 {0,1,1,0},
 {0,0,1,1}
}
step_states8 = {
 {1,0,0,0},
 {1,1,0,0},
 {0,1,0,0},
 {0,1,1,0},
 {0,0,1,0},
 {0,0,1,1},
 {0,0,0,1},
 {1,0,0,1},
}
step_states = step_states8 -- choose stepping mode
step_numstates = 8 -- change to match number of rows in step_states
step_delay = 20 -- choose speed
step_state = 0 -- updated by step_take-function
step_direction = 1 -- choose step direction -1, 1
step_stepsleft = 0 -- number of steps to move, will de decremented
step_timerid = 4 -- which timer to use for the steps
-- setup pins
for i = 1, 4, 1 do
  gpio.mode(stepper_pins[i],gpio.OUTPUT)
end
-- turn off all pins to let motor rest
function step_stopstate() 
  for i = 1, 4, 1 do
    gpio.write(stepper_pins[i], 0)
  end
end
-- make stepper take one step
function step_take()
  -- jump to the next state in the direction, wrap
  step_state = step_state + step_direction
  if step_state > step_numstates then
    step_state = 1;
  elseif step_state < 1 then
    step_state = step_numstates
  end
  -- write the current state to the pins
  for i = 1, 4, 1 do
    gpio.write(stepper_pins[i], step_states[step_state][i])
  end
  -- might take another step after step_delay
  step_stepsleft = step_stepsleft-1
  if step_stepsleft > 0 then
    tmr.alarm(step_timerid, step_delay, 0, step_take )
  else
    step_stopstate()
  end
end
-- public method to start moving number of 'int steps' in 'int direction'
function step_move(steps, direction, delay)
  tmr.stop(step_timerid)
  step_stepsleft = steps
  step_direction = direction
  step_delay = delay
  step_take()
end
-- public method to cancel moving
function step_stop()
  tmr.stop(step_timerid)
  step_stepsleft = 0
  step_stopstate()
end

Step 6: Conclusions

It took some time to figure out how to use the motor drive board with the NodeMCU. The documentation is really bad. However, now that I know how to use the combo I will definitely use it for more project. Hopefully the information shared in this instructable will help others to get started too. I really like the Arduino-like plug-in shield combo. I hope more manufacturers start making shields for NodeMCU.