ESP8266 servo

Control Servo motor via WiFi using ESP8266

ESP8266 servo

This page explains how to remote control a servo motor using ESP8266 with NodeMCU Firmware.

Materials needed:
- ESP8266 WiFi module
- USB to Serial converter (like FTDI)
- servo motor
- 3.3V 250mA voltage regulator
- 2x 47uF (or 100uF) capacitors
- 2x 220R resistors
- 1x 470R resistor
- 1x 2k (or 1k) resistor
- wires
- Android phone with RoboRemo app installed

Introduction

A Servo motor is a special type of motor that can be precisely controlled to move to a specific angle. It is widely used in robotics. It has 3 pins: Ground (GND), Power (usually +5V) and signal input.
The signal input type is usually known as Servo PWM signal. PWM = Pulse Width Modulation. The signal consists of periodic pulses, one pulse every 20ms. Each pulse has a variable width of 1ms to 2ms. That width carries the information. A pulse means that pin goes HIGH (+5V) for the duration of that pulse. The remaining time the pin stays LOW (0V).
The Servo motor has a microcontroller inside, that measures the pulse width and moves the motor to the corresponding angle. 1ms -> 0°, 1.5ms -> 90°, 2ms -> 180°. These numerical values together with the 20ms period are standard values. They can slightly differ from one Servo motor to another.

The NodeMCU is a firmware for ESP8266 that allows it to run lua scripts directly from its flash memory.

Steps:

1.
Flash the NodeMCU Firmware to the ESP8266
flashing-nodemcu-firmware-to-esp8266

2.
Upload this lua script:
(first modify the ssid, password, ip and port according to your needs)
(I use LuaPaste for uploading)

wifi.setmode(wifi.SOFTAP)

cfg={}
cfg.ssid="mywifi"
cfg.pwd="qwerty123"

cfg.ip="192.168.0.1"
cfg.netmask="255.255.255.0"
cfg.gateway="192.168.0.1"

port = 9876

wifi.ap.setip(cfg)
wifi.ap.config(cfg)

function stringStarts(a,b)
    return string.sub(a,1,string.len(b))==b
end

function stringEnds(a,b)
   return b=='' or string.sub(a,-string.len(b))==b
end

servo = {}
servo.pin = 4 --this is GPIO2
servo.value = 1500
servo.id = "servo"


cmd = ""

gpio.mode(servo.pin,gpio.OUTPUT)
gpio.write(servo.pin,gpio.LOW)

tmr.alarm(0,20,1,function() -- 50Hz 
    if servo.value then -- generate pulse
        gpio.write(servo.pin, gpio.HIGH)
        tmr.delay(servo.value)
        gpio.write(servo.pin, gpio.LOW)
    end
end)
    

function exeCmd(st) -- example: "servo 1500"
    if stringStarts(st, servo.id.." ") then -- value comes after id + space
        servo.value = tonumber( string.sub(st,1+string.len(servo.id.." "),string.len(st)) )
    end
end


function receiveData(conn, data)
    cmd = cmd .. data

    local a, b = string.find(cmd, "\n", 1, true)   
    while a do
        exeCmd( string.sub(cmd, 1, a-1) )
        cmd = string.sub(cmd, a+1, string.len(cmd))
        a, b = string.find(cmd, "\n", 1, true)
    end 
end


srv=net.createServer(net.TCP, 28800) 
srv:listen(port,function(conn)
    print("RoboRemo connected")
    conn:send("dbg connected ok\n")
     
    conn:on("receive",receiveData)  
    
    conn:on("disconnection",function(c) 
        print("RoboRemo disconnected")
    end)
    
end)

3.
Build the circuit according to the schematic:

esp8266-servo-schematic.png


Connect the servo to GND, +5V and GPIO2. Also connect the 2k resistor between +3.3V and GPIO2, because ESP-01 wants GPIO2 HIGH at power on.

2k-resistor.jpg

4.
To start the servo.lua program, type dofile("servo.lua") in terminal.
You may want to compile it first with node.compile("servo.lua") and then start with dofile("servo.lc").
If you want it to start automatically at power on, write dofile("servo.lc") to the init.lua file.

5.
Open WiFi settings on your phone and connect to the AP.

6.
Open RoboRemo and add a slider with id = "servo", min = 1000 and max = 2000 and "send when moved". Then connect.

7.
Enjoy :)