Introduction: Motorize IoT With ESP8266
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:
- 2 x NodeMCU 1.0 (aka v2) - http://www.gearbest.com/transmitters-receivers-mod...
- 2 x ESP-12E Motor shield - http://www.gearbest.com/boards-shields/pp_340732.h...
- 2 x DC Geared motor - http://www.gearbest.com/development-boards/pp_7099...
- 1 x 28BYJ stepper motor - http://www.gearbest.com/other-accessories/pp_23115...
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.
In essence, the motor shield features:
- Four powered outputs controlled by NodeMCU IO 1, 2, 3 and 4
- Optional dual voltage for motors and NodeMCU
- 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- | 1 | 5 or D1 |
A+ | 3 | 0 or D3 |
B- | 2 | 4 or D2 |
B+ | 4 | 2 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:
- Download ESP8266flasher here
- Download Lua firmware here. Alternatively you can cook you own here.
- 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.
- 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:
- Connect the (-) (usually black) lead from the motor to A-
- Connect the (+) (usually red) lead from the motor to A+
- Attach motor B in the same way
- 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.
- Attach the wires
- Blue -> A-
- Pink -> A+
- Yellow -> B-
- Orange -> B+
- Red -> VM
- 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.