/ESP4S2

ESP8266 for MIT Scratch 2

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

ESP4S2 is a project on ESP8266 NodeMCU with control by MIT Scratch 2 or RoboRemo.

The development branch is scratchx, which contains new features, for example:

  • MIT Scratch support
  • Shorter Lua code
  • PWM, OLED support
  • Tank control in Scratch, too

TOC

Introduction

The aim of this project is giving microcontroller control into hands of kids. The solution is inspired by A4S and Firmata. Scratch or RoboRemo can be used as user interface. ESP4S2 is licensed under GPLv3.

ESP8266 is a cheap microcontroller with built-in WiFi (SoC). See IoT for $10 to execute a "Hello, World!" example. There are a lot of variants, examples are optimized for WeMos D1 mini.

Hardware instructions for WeMos D1 mini and tank example are described at instructables.com: Controlling LEGO Tank by ESP8266 With Scratch or RoboRemo

Software Components:

  • ESP8266: microcontroller with built-in WiFi (required)
    • NodeMCU firmware (required)
    • Controller, written in Lua for executing control commands and providing sensor values (required)
    • H-bridge (optional)
    • HC-SR04 (optional)
  • Scratch 2 Offline Editor: a programming interface (optional)
    • Bridge, a Scratch Extension written in Python (required to Scratch)
    • Python interpreter (required to Scratch)
  • Roboremo: a simple manual control interface on Android (optional)

Example setups:

                                                                    +----------+
+-------------------------------------+       +--------------+  +-->| HC-SR04  |
|            Desktop, Laptop          |       |              +--+   +----------+
|                                     |  +--->|  Controller  |
|  +-----------+        +----------+  |  |    |              +--+   +----------+
|  |           |  HTTP  |          +-----+    +--------------+  +-->| H-bridge |
|  |  Scratch  +------->|  Bridge  |  | WiFi                        +----------+
|  |           |        |          +-----+    +--------------+
|  +-----------+        +----------+  |  |    |              |      +----------+
|                                     |  +--->|  Controller  +----->| H-bridge |
|                                     |       |              |      +----------+
+-------------------------------------+       +--------------+


                   +------------------+
                   |  Tablet, Phone   |
                   |                  |                             +----------+
                   |  +------------+  |       +--------------+  +-->| H-bridge |
                   |  |            |  | WiFi  |              +--+   +----------+
                   |  |  RoboRemo  +--------->|  Controller  |
                   |  |            |  |       |              +--+   +----------+
                   |  +------------+  |       +--------------+  +-->| HC-SR04  |
                   |                  |                             +----------+
                   |                  |       
                   +------------------+              


                                                                    +----------+
                   +------------------+       +--------------+  +-->+ HC|SR04  |
                   |  Tablet, Phone   |       |              +--+   +----------+
                   |                  |  +--->+  Controller  |
                   |  +------------+  |  |    |              +--+   +----------+
                   |  |            +-----+    +--------------+  +-->+ H|bridge |
                   |  |  RoboRemo  |  | WiFi                        +----------+
                   |  |            +-----+    +--------------+
                   |  +------------+  |  |    |              |      +----------+
                   |                  |  +--->+  Controller  +----->+ H|bridge |
                   |                  |  UDP  |              |      +----------+
                   +------------------+ broad +--------------+
                                        -cast

Feature List

Supported Scratch commands:

  • Set network (initNet): Initialize WiFi subnet (only one subnet is supported simultaneously), IP address is a sum of subnet address and device id.
  • set pin (pinMode): NodeMCU command(s): gpio.mode or pwm.setup + pwm.start
  • digital write pin (digitalWrite): NodeMCU command(s): gpio.write
  • analog write pin (analogWrite): NodeMCU command(s): pwm.setduty
  • analog write pin pair (analogPairWrite): NodeMCU command(s): pwm.setduty
  • tank write pin pair (tankWrite): NodeMCU command(s): pwm.setduty
  • servo write pair (servoWrite): NodeMCU command(s): gpio.write
  • digital read pin (digitalRead): NodeMCU command(s): gpio.read
  • analog read pin (analogRead): NodeMCU command(s): adc.read or custom sensor command
  • Stop (reset_all): Reset state machine, NodeMCU command(s): gpio.write, pwm.setduty
  • poll: return cached values of digitalRead, analogRead
  • Simplified Block commands

Bridge Features:

  • Supporting more NodeMCUs in one WiFi network
  • Command-line parameters
  • Overload protection by state machine (only changes are sent to Controller)
  • Overload protection by UDP "ACK" (waiting for processing the earlier sent command, +timeout)
  • Overload protection by batch command sending (programmatically configured)
  • Overload protection by rare poll and caching digitalRead/analogRead values
  • Overload protection by queue size limitation (drop)
  • Name resolution (instead of IP address)
  • Simplified Block commands
  • Unit tests

Controller Features:

  • Basic digital pin handling (mode, high/low, PWM)
  • analogRead: adc.read registers value to D16 (virtual)
  • analogPairWrite: transforms a [-100,+100] value to 2 pins of H-bridge for a DC motor
  • tankWrite: transforms a joystick XY value pair ([-100,+100], [-100,+100]) to A-B pins of H-bridge for 2 DC motor
  • getName: returns Bridge name
  • Too small PWM value is overwritten to 0 (for DC motors)
  • Too small PWM value is overwritten to 0 (for tank)
  • WiFi station and AP mode
  • MAC-based configuration
  • Configuration for more networks
  • State check for pin mode
  • Automatic pin mode
  • UDP
  • Send values back to RoboRemo
  • TCP
  • Supporting more NodeMCUs in one WiFi network, for Bridge
  • Supporting more NodeMCUs in one WiFi network, for RoboRemo (UDP broadcast)
  • HC-SR04 sensor support
  • DHT sensor support
  • BMP180 sensor support

Device and Sensor Extensions

HC-SR04

Original source from: node_hcsr04. Main change: replacing tmr.delay to tmr.alert. Optimized for WeMos D1 mini. Sensor pins:

  • ECHO: D8 (GPIO15) pulled down by 10k (R2) on WeMos D1 mini. R1 between ECHO and D8 as voltage divider: 4k7, see more: HC-SR04 Ultrasonic Range Sensor on the Raspberry Pi
  • TRIG: D0 (GPIO16). Can only be used as gpio read/write. No support for open-drain/interrupt/pwm/i2c/ow.
  • VCC: 5V
  • GND: G

Trig time: min. 10 us. Max echo time: 38 ms. Usage: dofile("hcsr.lua") device=hcsr.init() device.start(), automatically called by init.lua, if devices["hcsr"] in config.lua is set properly.

Installation and Configuration

Getting Repository

Clone or download and extract repository from GitHub. Please read LICENSE, TOC is created by gh-md-toc.

Wiring

WeMos D1 mini system has some additional resistors and dedicated pins for shields. These constraints determine a logical pinout:

ESP-8266 Pin Pin WeMos Function suggested ESP4S2 Function
A0 A0 Analog input, max 3.3V input Analog input
GPIO16 D0 IO HC-SR04 Trig
GPIO5 D1 IO, SCL I2C for shields
GPIO4 D2 IO, SDA I2C for shields
GPIO0 D3 IO, 10k Pull-up H-bridge B2
GPIO2 D4 IO, BUILTIN_LED
10k Pull-up
Blue LED
DHT Data
GPIO14 D5 IO, SCK H-bridge A1
GPIO12 D6 IO, MISO H-bridge A2
GPIO13 D7 IO, MOSI H-bridge B1
GPIO15 D8 IO, SS
10k Pull-down
HC-SR04 Echo
+ 4k7: 5V-->3.3V voltage divider

D8 pin works well with Pololu DRV8833 as B2 input, but activates motor B with cheap L9110 at power on. D3 works well with cheap L9110. I2C pins are used by WeMos shields OLED and Motor.

HC-SR04 needs 5V power, Echo pin output is 5V, too (3.3V input is good for Trig). A 4k7 with built-in 10k Pull-down resistor behave as a voltage divider, see: HC-SR04 Ultrasonic Range Sensor on the Raspberry Pi.

Pin D4 is used by WeMos shields DHT and DHT Pro.

Other pinout can also be used.

NodeMCU Firmware

NodeMCU is an embedded Lua firmware to ESP8266. Firmware can be download from NodeMCU custom builds (builds combined binary). For using H-bridge, PWM module must be selected. For using DHT sensor, DHT module must be selected. Integer build must be used. Firmware can be flashed by esptool.py or NodeMCU Flasher, see Flashing the firmware. Since 1.5.1-master, default baud is 115200 (instead of 9600).

Controller

Copy secure.lua.example to secure.lua and edit own WiFi authentication configuration.

Copy config.lua.example to config.lua and edit network configuration.

  • Controller supports more WiFi network configuration, selected by WIFI_CFG_NAME.

  • Controllers are identified by its MAC address. STATION and AP mode are supported. In STATION mode (wifiMode=wifi.STATION), Controller requests an IP address from a WiFi AP (a WiFi router or an ESP8266 in SOFTAP or STATIONAP mode). If WiFi AP is not alive, ip parameter will be used. If static_ip=true, Controller enforces ip as IP address (netmask should be declared, too). In SOFTAP mode (wifiMode=wifi.SOFTAP), NodeMCU runs as WiFi AP and WiFi router is not required for WiFi communication. Other Controllers in this WiFi network should be configured with static IP address (static_ip=true).

  • The Controller listening port can be set by ROBOREMO_PORT, its default value is 9876. Sensors with custom feature can be configured in devices.

ESPlorer can be used to upload Lua files to ESP. Upload all *.lua files of directory lua to NodeMCU. After reset, NodeMCU will be ready to receive commands and send back input values.

Socat

socat can be used for testing Controller without any GUIs (Scratch, RoboRemo). Socat can be installed on Cygwin and Linux. Anoter famous program, nc (Netcat), can also send UDP messages, but cannot send from and receive to same port.

Example for sending commands to a specific IP address (Scratch use case):

socat readline UDP4-DATAGRAM:192.168.10.102:9876,bind=:9877
getName
pinMode 4 1
digitalWrite 4 0
digitalWrite 4 1

Example for sending commands to broadcast address (RoboRemo use case):

socat readline UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877
getName
tank-tower pinMode 4 1
tank-tower digitalWrite 4 0
tank-tower digitalWrite 4 1

There are several online portals, where broadcast address can be calculated, for example: [http://www.subnet-calculator.com/](IP Subnet Calculator).

Bridge

Bridge requires Python 2.7. Bridge command line options will be printed out by --help parameter. Bridge listening port can be set by --esp-listen-port, its default value is 9877. Controllers port can be set by --esp-port, its default value is 9876.

Windows install

Python 2.7 can be downloaded and installed from Python Releases for Windows. Example for starting Bridge:

C:\Python27\python.exe -c src\ESP4S2.py

Cygwin install

Pyton 2.7 package can be installed to Cygwin. Example for starting Bridge:

src/ESP4S2.py

Linux install

Pyton 2.7 package installation is described at the Linux distributor. Example for starting Bridge:

src/ESP4S2.py

Scratch

Install Scratch 2 Offline Editor. Import ESP42S extension description src/ESP4S2.s2e (shift-click on "File" and select "Import Experimental Extension" from the menu). The new extension blocks will appear in the More Blocks palette.

RoboRemo

RoboRemo can be installed for Android by Google Play. Commands are described in the chapter Controller Command Reference.

Single Controller

To connect RoboRemo to Controller, use "Internet (UDP)" connection. Example for a connection string: 192.168.10.102:9876, where the ip and port was set up in lua/config.lua.
A button should be created for initialize pins. Example init button configuration for a H-bridged DC motor on pins 5, 6 and a LED on pin 4:

  • set press action (\n is also supported instead of Enter):
pinMode 4 1
pinMode 5 3
pinMode 6 3
  • repeat: delay, period = 0, only press action

Example on/off button configuration for a LED on pin 4:

  • set press action: digitalWrite 4 1 or digitalWrite 4 0, depending on a pull-up resistor of the pin.
  • repeat: delay, period = 0, only press action

Example slider for a H-bridged DC motor on pins 5, 6:

  • set id: analogPairWrite 5 6
  • set min, max: min = -100, max = 100
  • send when released (tricky: send when move should be seen)
  • set repeat period: 500 ms

Multiple Controllers

RoboRemo cannot connect to multiple IP addresses. In this case, the boradcast IP address of subnet can be used. For example, if the subnet is 192.168.10.0/24, the broadcast address is 192.168.10.255. There are several online portals, where broadcast address can be calculated, for example: [http://www.subnet-calculator.com/](IP Subnet Calculator). The command sending to this address will be received by all of Controllers. The target Controller name must be marked by the beginning of the command, for example: tank-tower pinMode 4 1, tank-tower digitalWrite 4 0, tank-tower digitalWrite 4 1. Without marking the Controller name, all Controllers will execute the command.

Programer's Guides

Scratch Beginner Programer's Guide

Blocks for full functionality looks too complex for young children. Simplified blocks are created for them in order to have experience on microcontrollers. These Blocks have some limitations, for example:

  • Only one Controller is supported.
  • Pin groups must be named for group operations (for example: analogPairWrite, tankWrite).
  • Waiting for next command (W) is not supported.

With this limitations, each student can handle own named Controller.

First steps

Coming soon...

Blocks

Coming soon...

LED project

Coming soon...

PWM project

Coming soon...

DC motor project

Coming soon...

Scratch Advanced Programer's Guide

First steps

After starting Bridge (src/ESP4S2.py) and loading ESP42S extension description (src/ESP4S2.s2e), Scratch is ready to create block programs. The first block which must be executed is the Set network. This block initializes Bridge and requests Controllers to send its names back for name resolution. Example for Set network block: initNet, where 192.168.10.0 is the subnet ID and 24 is the subnet mask bits. There are several online portals, where subnet ID and subnet mask bits can be calculated, for example: [http://www.subnet-calculator.com/](IP Subnet Calculator). At least one second must be wait to collect responses from Controllers, for example: wait1s.

Blocks

Pin mode must be set before using a pin (set pin). A block can be executed immediately (E) or with the next (W). More blocks can be bundled to one group until the first E block. The last block of execution bundle must be E. Examples for bundled blocks:

  • pinMode_tank-tower
  • pinMode_tank-chassis

The simplest control block is the digital write pin. See examples for controlling WeMos built-in led:

  • digitalWrite_high
  • digitalWrite_low

PWM can be controlled by block analog write pin, for example: analogWrite.

H-bridged DC motors can be controlled by analog write pin pair block, for example: analogPairWrite. The value must be set in interval [-100, 100].

Two H-bridged DC motors can be controlled by tank write pin quad block, for example: tankWrite. Four pins and XY values (joystick) must be set in interval [-100, 100]. Controller transforms XY values to A-B values.

Values can be used by blocks digital read pin and analog read pin, for example:

  • digitalRead
  • analogRead_cycle

LED project

It's the "Hello, World!" example of microcontroller world. Built-in blue LED of WeMos is connected to pin 4. Because of built-in pull-up resistor, LED behaves opposite. After starting Controller and Bridge, please create the below project:

LED

Click once on Set network. The 192.168.10.0/24 network will be used for communicating to Bridges. It will be valid until Brigde running. Depending on the network setup (WiFi router, ESP AP), the network can be different.

Click on Start. Block set pin will set pin 4 to OUTPUT.

When o key pressed, pin 4 will be set Low (0). Because of built-in pull-up resistor, LED will be turned on. When x key pressed, pin 4 will be set High (1). Because of built-in pull-up resistor, LED will be turned off.

Click on Stop to stop all pins.

PWM project

This project demonstrates PWM. Because of built-in pull-up resistor on pin 4, LED behaves opposite: it will ligth strongest by setting PWM duty cycle to 0% and LED will be turned off by setting PWM duty cycle 100%. After starting Controller and Bridge, please create the below project:

PWM

Click once on Set network. It will be valid until Brigde running.

Click on Start. Block set pin will set pin 4 to PWM.

Press keys 0, 1, 2, 3, 4 to try PWM duty cycles 0%, 50%, 80%, 95%, 100%.

Click on Stop to stop all pins.

DC motor project

This project demonstrates DC motor control using PWM and H-bridge.

Controller Command Reference

A command can be sent to one Controller or to all Controllers, using broadcast address. In this case, the Controller name must be specified before the command. General syntax of commands is:

[controller-name ]commandName[ option1[ option2[ option3[...]]]

Endline (\n) is required at the end of command. Controller name can be set in config.lua.

Get Controller Name

Command getName returns Controller name. This feature is used for Scratch for name resolution. Practically, it should be sent to broadcast address. Example:

echo "getName" | socat STDIO UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877

Set Pin Mode

Command pinMode initializes pin. The below modes are supported:

  • 0: INPUT, called NodeMCU command: gpio.mode(pin, gpio.INPUT)
  • 1: OUTPUT, called NodeMCU command: gpio.mode(pin, gpio.OUTPUT)
  • 2: Analog input. If pin 0, adc.read will be called later, otherwise, a sensor driver can store integer value on this pin.
  • 3: PWM, called NodeMCU commands: pwm.setup(pin,1000,0), pwm.start(pin)
  • 4: Servo, not supported yet.

Command syntax is: pinMode <pin> <mode>. Example for set pin 4 mode to OUTPUT using single IP address and broadcast address:

echo "pinMode 4 1" | socat STDIO UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877

echo "tank-chassis pinMode 4 1" | socat STDIO UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877

Digital Read

Command digitalRead reads digital GPIO pin value. It calls gpio.read(pin) and returns by the given level. Before executing this command, pin mode must be set to INPUT. Command syntax is: digitalRead <pin>. Example for set pin 3 mode to INPUT and reading pin level:

socat readline UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877
pinMode 3 0
digitalRead 3

Digital Write

Command digitalWrite sets digital GPIO pin value. It calls gpio.write(pin, level). Before executing this command, pin mode must be set to OUTPUT. Command syntax is: digitalWrite <pin> <level>. Example for set pin 4 mode to OUTPUT and set its level to gpio.LOW and gpio.HIGH:

socat readline UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877
pinMode 4 1
digitalWrite 4 0
digitalWrite 4 1

PWM Write

Command analogWrite sets duty cycle for a pin, duty interval is [0,100]. It calls pwm.setduty(pin, duty). Before executing this command, pin mode must be set to PWM. Command syntax is: analogWrite <pin> <duty>. Example for set pin 4 mode to PWM and set duty cycle to 50 and 100:

socat readline UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877
pinMode 4 3
analogWrite 4 50
analogWrite 4 100

PWM Pair Write

Command analogPairWrite sets duty cycle for 2 pins of a H-bridged DC motor, duty interval is [-100,100]. If the duty is negative, DC motor will turn reverse. In simple case, it calls pwm.setduty(pin1, duty) and pwm.setduty(pin2, 0). If the value is negative, the polarity should be changed, so pwm.setduty(pin1, 0) and pwm.setduty(pin2, 0-duty) will be called. Before executing this command, pin mode must be set to PWM both on 2 pins. Command syntax is: analogWrite <pin1> <pin2> <duty>. Example for set pins 5 and 6 mode to PWM and set duty cycle to 50 and -50 (reverse turn):

socat readline UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877
pinMode 5 3
pinMode 6 3
analogPairWrite 5 6 50
analogPairWrite 5 6 -50

Tank Write

Command tankWrite transforms a joystick XY value pair ([-100,+100], [-100,+100]) to A-B pins of H-bridge for 2 DC motor. The command calls pwm.setduty(pin, duty) on each 4 pins. Before executing this command, pin mode must be set to PWM both on 4 pins. Command syntax is: tankWrite <pinA1> <pinA2> <pinB1> <pinB2> <x> <y>. Example for set pins 5, 6, 7, 3 mode to PWM and set x and y values to drive forward, right and turn left in place:

socat readline UDP4-DATAGRAM:192.168.10.103:9876,bind=:9877
pinMode 5 3
pinMode 6 3
pinMode 7 3
pinMode 3 3
tankWrite 5 6 7 3 0 100
tankWrite 5 6 7 3 100 100
tankWrite 5 6 7 3 -100 0

Servo Write

Not supported yet.

Analog Read

Command analogRead reads integer values on pins. If pin is 0, adc.read(0) will be called, otherwise, returns sample value of custom sensor driver. Pin mode (pinMode) should not called on the pin. Command syntax is: analogRead <pin>. Example for getting sensor sample configured on pin 8:

echo "analogRead 8" | socat STDIO UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877

Poll

Command poll returns all cached digitalRead and analogRead values. Example for getting all cached values:

echo "poll" | socat STDIO UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877

Reset All

Command reset_all resets output values to 0. It calls gpio.write(pin, 0) on mode OUTPUT and calls pwm.setduty(pin, 0) on mode PWM. Example for getting all cached values:

echo "reset_all" | socat STDIO UDP4-DATAGRAM:192.168.10.255:9876,bind=:9877