An ESP32 Based Coprocessor System
Motivation
Simple microcontrollers are widely used in embedded systems for IoT and robotic applications. There is a growing need to connect these systems to the Internet in order to transmit the data collected by sensors to a remote control system or to receive commands for connected actuators. A direct connection of the microcontroller with the Internet via Ethernet or WLAN, or creating a local access point is often impossible because no such communication hardware is available on the chip. To overcome this problem, a coprocessor can be added to perform these communication tasks.
Data exchange between the microcontroller and the coprocessor should be as simple as possible, as the microcontroller usually has modest resources. The easiest way is to consider the coprocessor as a special type of sensor that receives commands via a standard protocol to perform the communication task. The coprocessor may return information the the microcontroller by the same was. Common protocols for data exchange with sensors are I²C, SPI and UART.
The general concept is shown here (using an Arduino or micro:bit as master, not both at the same time):
Note:
The ESP32 and not the ESP8266 is used here, since the latter cannot be configured as an I²C slave. There are WLAN add-on boards with the ESP8266 on the market which communicate via a serial interface (UART). However, since the UART interface on the microcontroller is often used for runtime debugging, the connection of the coprocessor via I²C is preferrable. In addition, the ESP32 is much more powerful than the ESP8266, which is especially noticeable when used as a web server.
The LinkUp overcomes the limitations of small microcontroller systems in memory and WLan communication. It opens a wide door to the outside world and applications in the following areas are easy built because the details of the code running on the coprocessor are completely hidden to the application developer.
- HTTP/HTTPS GET and POST requests (used for most cloud appllications)
- Web server exposed via a Wlan router
- Running a local Wlan hotspot for TCP communicaion
- MQTT publisher and subscriber for typical IoT applications
- NTP clock synchronization
Linkup Manager
After flashing the ESP32 with MicroPython, the program LinkupManager.py is started. It runs an I²C slave at address 0x77 and waits for commands in string format received from an I²C master. The command processor performs the requested action and reports the results back to the master. Typically the master is a small microcontroller with little memory (micro:bit, Arduino, etc.) and only a few lines of command code is necessary to perfom quite complicate actions on the ESP coprocessor. The master program can be written in any programming language (typically MicroPython, C/C++, JavaScript, etc.) or in a visual programming environment (Scratch, Blockly, etc.). The programmer is completely isolated from the code of the LinkupManager and only concerned with the interface API, which is restricted to string exchange.
The ESP32 can be installed on any development board, for example as LOLIN32, Huzzah32 Feather, ESP32-WROOM, ESP32MiniKit Wemos, etc. Because of the small dimensions, the latter is preferred here.
The communication between the master (Arduino, micro:bit) and the slave (ESP32) is based on a simple user definied protocol. The master sends a integer command ID and a string argument and waits eventually for a single string reply. If more than one value is passed, the values are packed into a single string by using a separator ('"?", ":" or "\1").
Linkup Interface Protocol
Description |
ID
(int) |
Arguments
(string) |
Return value
(string) |
Blocking
(wait for task done) |
Login to an access point (disconnect, if already connected) |
1 |
ssid;password |
IP address attributed by the access point, empty if login failed |
Yes |
Create access point |
9 |
ssid;password |
empty |
Yes |
Perform HTTP GET request |
2 |
url/?key=value;... |
Response (content only) |
Yes |
Perform HTTP POST request |
3 |
url?key=value;... |
Response
(content only) |
Yes |
Perform HTTP DELETE request |
4 |
url |
empty |
Yes |
Start Web server |
5 |
empty |
address?filename?params |
No |
Request deep sleep |
6 |
empty |
empty |
No |
Request reboot |
7 |
empty |
empty |
No |
Receive text |
8 |
line<wait>line<wait>...
empty_line |
empty |
Yes (line per line) |
Create MQTT client |
10 |
host\0port\0
user\0password\0\keepalive
keepalive = "0": disabled
keepalive = "1": enabled |
empty |
Yes |
Disconnect from MQTT broker |
11 |
empty |
empty |
No |
Publish MQTT topic |
12 |
topic\0payload\0retain\0qos
qos: "0", "1", "2"
retain = "False", "True" |
"True", if successful
"False", if failed |
Yes |
Subscribe MQTT topic |
13 |
topic\qos
qos: "0", "1", "2" |
"True", if successful
"False", if failed |
Yes |
Request MQTT message
from Fifo queue |
14 |
empty |
topic\1message
empty, if no message in queue |
Yes |
Perform MQTT ping |
15 |
empty |
"True", if successful
"False", if failed |
Yes |
Set MQTT last will |
16 |
topic\0payload\0retain\0qos
qos: "0", "1", "2"
retain = "False", "True" |
True", if successful
"False", if failed |
Yes |
Connect MQTT broker |
17 |
"True" if clean session; else "False" |
True", if successful
"False", if failed |
Yes |
Get time from NTP server |
18 |
empty or server URL
if empty: pool.ntp.org |
yyyy:mm:dd:hh:mm:ss:ww
empty, if failed |
Yes |
Get version info |
19 |
empty |
Version of Linkup firmware |
Yes |
The protocol is easily implemented for different programming environments on the master. Libraries are available written in MicroPython for the micro:bit and in written in C/C++ for the Arduino. See the right side bar for the API definitions. The source of the LinkUpManager and the libraries are part of the LinkUp distribution.
Web Server
Command option 5 starts a Web server that replies to HTTP GET requests on port 80. The command differs from others because in this mode the ESP32 remains in an endless loop and does not respond any more to other commands (with the exception of a terminate-server command). To set the ESP32 to normal mode, the reset button must be clicked (or a terminate-server command is issued).
The URL of the client's GET request is extracted and transmitted from the ESP32 to the I²C master (Arduino, micro:bit) in the form clientIP?filename?(key1=value1,key2=value2,... e.g. for a request with the URL
http://clientIP/index.html?lamp1=on,lamp2=off
"clientIP?index.html?lamp1=on,lamp2=off"
The Arduino or micro:bit register a callback function onRequest() that receives the three part of the URL. It processes this information and returns a appropriate string that is sent back to the ESP32 and assembled into the HTTP reponse. For the programmer of the Arduino or micro:bit only the callback function is of his concern since the internals are fully transparent, More information can be found in the sample programs.
The Web server is useful in robotics applications so that a rover can communicate with its environment, for example to be controlled remotely with a smartphone and to transfer state information. This eliminates the need to develop a dedicated mobile app, and the user interface is determined solely by the design of the Web page. Simple knowledge of HTML and possibly JavaScript is sufficient.
Installation of the LinkUp coprocessor firmware
A standalone flash utility for Windows and Mac is part of the Linkup distribution. A flash option for the ESP32 coprocessor is also included in the TigerJython IDE. Since the standard MicroPython firmware does not support I²C slaves, the LoBo version of MicroPython developed by Boris Lovosevic is used.
|