Skip to content

Commit 60fa670

Browse files
committed
PB link doc moved and updated.
1 parent 2880bf1 commit 60fa670

File tree

2 files changed

+142
-70
lines changed

2 files changed

+142
-70
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ The interface between the Pyboard and the ESP8266 uses I2C and is based on the
836836
Resilient behaviour includes automatic recovery from WiFi and server outages;
837837
also from ESP8266 crashes.
838838

839-
See [documentation](./pb_link/README.md).
839+
See [documentation](./docs/PB_LINK.md).
840840

841841
# 10. How it works
842842

pb_link/README.md renamed to docs/PB_LINK.md

+141-69
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# WARNING: This doc is out of date and under review
2-
31
# 0. IOT design for clients lacking a LAN interface
42

53
This uses an ESP8266 to provide a resilient "socket-like" link between a non
@@ -10,20 +8,24 @@ Communication between the client and the ESP8266 uses I2C. The client must be
108
capable of running I2C slave mode. This includes STM boards such as the
119
Pyboard V1.x. In this doc the client device is referred to as the Pyboard.
1210

13-
0. [IOT design for clients lacking a LAN interface](./README.md#0-iot-design-for-clients-lacking-a-lan-interface)
14-
1. [Wiring](./README.md#1-wiring)
15-
2. [Files](./README.md#2-files)
16-
3. [Running the demo](./README.md#3-running-the-demo)
17-
4. [The Pyboard application](./README.md#4-the-pyboard-application)
18-
4.1 [Configuration](./README.md#41-configuration)
19-
4.2 [Application design](./README.md#42-application-design)
20-
4.3 [Special messages](./README.md#43-special-messages)
21-
4.4 [The AppBase class](./README.md#44-the-appbase-class)
22-
5. [ESP8266 crash detection](./README.md#5-esp8266-crash-detection)
23-
6. [Quality of service](./README.md#6-quality-of-service)
11+
0. [IOT design for clients lacking a LAN interface](./PB_LINK.md#0-iot-design-for-clients-lacking-a-lan-interface)
12+
1. [Wiring](./PB_LINK.md#1-wiring)
13+
2. [Files](./PB_LINK.md#2-files)
14+
3. [Running the demo](./PB_LINK.md#3-running-the-demo)
15+
4. [The Pyboard application](./PB_LINK.md#4-the-pyboard-application)
16+
4.1 [Configuration](./PB_LINK.md#41-configuration)
17+
4.2 [Application design](./PB_LINK.md#42-application-design)
18+
4.3 [Special messages](./PB_LINK.md#43-special-messages)
19+
4.4 [The AppBase class](./PB_LINK.md#44-the-appbase-class)
20+
5. [ESP8266 crash detection](./PB_LINK.md#5-esp8266-crash-detection)
21+
6. [Quality of service](./PB_LINK.md#6-quality-of-service)
22+
7. [Building ESP8266 firmware](./PB_LINK.md#7-building-esp8266-firmware)
2423

2524
# 1. Wiring
2625

26+
Firmware should be installed on the ESP8266 prior to connecting it to the
27+
Pyboard.
28+
2729
ESP8266 pin numbers are GPIO pins as used on the reference board. WeMos have
2830
their own numbering scheme.
2931

@@ -36,10 +38,11 @@ their own numbering scheme.
3638
| X12 | rst | reset | reset |
3739
| Y8 | 4 | ack | D2 |
3840

39-
Pyboard pins may be altered at will. The chosen pins enable hard I2C to be used
40-
but soft I2C with arbitrary pins also works. The `sync` and `ack` wires provide
41-
synchronisation and the `reset` line enables the Pyboard to reset the ESP8266
42-
if it crashes and fails to respond.
41+
Pyboard pins may be altered at will (with matching changes to `config.py`).
42+
The chosen pins enable hard I2C to be used but soft I2C with arbitrary pins
43+
also works. The `syn` and `ack` wires provide synchronisation and the `reset`
44+
line enables the Pyboard to reset the ESP8266 if it crashes and fails to
45+
respond.
4346

4447
I2C requires the devices to be connected via short links and to share a common
4548
ground. The `sda` and `scl` lines require pullup resistors. The chosen ESP8266
@@ -48,7 +51,9 @@ pullups are needed, a typical value is 4.7KΩ to 3.3V.
4851

4952
The I2C bus employed here cannot be shared with other devices.
5053

51-
A common power supply is usual but not essential.
54+
A common power supply is usual but not essential. If the Pyboard is powered by
55+
USB and the ESP8266 board has a voltage regulator, the ESP may be powered from
56+
the Pyboard Vin pin.
5257

5358
# 2. Installation
5459

@@ -59,27 +64,21 @@ A Python package is used so directory structures must be maintained.
5964
These instructions assume an installation to the SD card. If installing to
6065
flash, substitute `flash` for `sd` below.
6166

62-
On the Pyboard create a directory `/sd/micropython_iot`. Copy the following
63-
file to this directory:
64-
1. `__init__.py`
65-
66-
Create the directory `/sd/micropython_iot/pb_link` and copy the following
67-
files from `micropython_iot/pb_link` to it:
68-
1. `app_base.py`
69-
2. `asi2c_i.py`
70-
3. `config.py`
71-
4. `pb_client.py`
72-
5. `__init__.py`
73-
74-
Edit `micropython_iot/pb_link/config.py` to match local conditions, notably
75-
server IP address and WiFi credentials. WiFi credentials may be empty strings
76-
if the ESP8266 has been initialised with a WiFi connection.
77-
78-
Start by issuing
79-
```python
80-
import micropython_iot.pb_link.pb_client
67+
On the Pyboard copy the directory `pb_link` and its contents to '/sd'. If using
68+
rshell this may be done by issuing:
69+
```
70+
cp -r pb_link /sd
71+
```
72+
Clone [the async repo](https://github.com/peterhinch/micropython-async) to
73+
your PC, navigate to `v3` and copy the `primitives` directory to `/sd`:
74+
```
75+
cp -r primitives /sd
8176
```
8277

78+
Edit `iot/pb_link/config.py` to match local conditions, notably server IP
79+
address and WiFi credentials. WiFi credentials may be empty strings if the
80+
ESP8266 has been initialised with a WiFi connection.
81+
8382
#### On the ESP8266
8483

8584
For reliable operation this must be compiled as frozen bytecode. For those not
@@ -90,41 +89,34 @@ installed with the following commands:
9089
esptool.py --port /dev/ttyUSB0 erase_flash
9190
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash --verify --flash_size=detect -fm dio 0 firmware-combined.bin
9291
```
93-
This build is designed to start on boot so no further steps are required.
94-
95-
To compile your own build your `modules` directory must contain (in addition to
96-
its normal contents) an installation of `uasyncio`. See notes on this in the
97-
[main readme](../README.md#31-installation). Under `modules` create a
98-
directory `/pyboard/micropython_iot`. Copy the following files to it:
99-
1. `__init__.py`
100-
2. `client.py`
92+
Erasure is essential. The build is designed to start on boot so no further
93+
steps are required.
10194

102-
Copy the directory `esp_link` with its contents to the `micropython_iot`
103-
directory. Compile and install the build.
104-
105-
Edit `/pyboard/main.py` to read:
106-
```python
107-
from micropython_iot.esp_link import esp_link
108-
```
95+
To compile your own build see
96+
[Section 7](./PB_LINK.md#7-building-esp8266-firmware).
10997

11098
### Dependency
11199

112-
`uasyncio` is required on Pyboard and ESP8266. See the notes on this in the
113-
[main readme](../README.md#31-installation).
100+
The Pyboard must be running a daily build or a release build later than V1.12.
101+
This is to ensure a compatible version of `uasyncio` (V3).
114102

115103
# 3. Running the demo
116104

117-
Ensure `/sd/micropython_iot/pb_link/config.py` matches local conditions for
118-
WiFi credentials and the server IP address.
105+
Ensure `/sd/pb_link/config.py` matches local conditions for WiFi credentials
106+
and server IP address.
119107

120-
On the server navigate to the parent directory of `micropython_iot` and run
108+
On the server navigate to the parent directory of `pb_link` and run
109+
```
110+
micropython -m pb_link.s_app
111+
```
112+
or (given Python 3.8 or newer):
121113
```
122-
python3 -m micropython_iot.pb_link.s_app
114+
python3 -m pb_link.s_app
123115
```
124116

125-
On the Pyboard run
117+
On the Pyboard issue
126118
```python
127-
from micropython_iot.pb_link import pb_client
119+
import pb_link.pb_client
128120
```
129121

130122
# 4. The Pyboard application
@@ -168,8 +160,8 @@ The `hardware` list comprises the following elements:
168160
## 4.2 Application design
169161

170162
The code should create a class subclassed from `app_base.AppBase`. The base
171-
class performs initialisation. When this is complete, a `.start` method is
172-
called which the user class should implement.
163+
class performs initialisation. When this is complete, a `.start` synchronous
164+
method is called which the user class should implement.
173165

174166
Typically this will launch user coroutines and terminate, as in the demo.
175167

@@ -196,11 +188,10 @@ trigger asynchronous bound methods which the user may override.
196188
## 4.4 The AppBase class
197189

198190
Constructor args:
199-
1. `loop` The asyncio event loop.
200-
2. `conn_id` Connection ID. See below.
201-
3. `config` List retrieved from `config.py` as described above.
202-
4. `hardware` List retrieved from `config.py` defining the hardware interface.
203-
5. `verbose` Provide debug output.
191+
1. `conn_id` Connection ID. See below.
192+
2. `config` List retrieved from `config.py` as described above.
193+
3. `hardware` List retrieved from `config.py` defining the hardware interface.
194+
4. `verbose` Provide debug output.
204195

205196
Coroutines:
206197
1. `readline` Read a newline-terminated line from the server.
@@ -226,7 +217,7 @@ modify the default behaviour.
226217
credentials in the `config` list. If this fails an `OSError` is raised.
227218
2. `bad_server` No args. Awaited if server refuses an initial connection.
228219
Raises an `OSError`.
229-
3. `report` Regularly launched if reports are requested in the config. It
220+
3. `report` Regularly launched if reports are requested in the config. It
230221
receives a 3-list as an arg: `[connect_count, report_no, mem_free]` which
231222
describes the ESP8266 status. Prints the report.
232223
4. `server_ok` Launched whenever the status of the link to the server changes,
@@ -255,7 +246,7 @@ wire is in place there are two levels of crash recovery.
255246

256247
If I2C communication fails due to an ESP8266 reboot or power cycle, the
257248
underlying
258-
[asynchronous link](https://github.com/peterhinch/micropython-async/blob/master/i2c/README.md)
249+
[asynchronous link](https://github.com/peterhinch/micropython-async/blob/master/v3/docs/I2C.md)
259250
will reboot the ESP8266 and re-synchronise without the need for explicit code.
260251
This caters for the bulk of potential failures and can be verified by pressing
261252
the ESP8266 reset button while the application is running.
@@ -278,3 +269,84 @@ recover but message loss may occur. Two observations:
278269
achieved at application level using response messages. When designing such a
279270
system bear in mind that response messages may themselves be lost in the event
280271
of a crash.
272+
273+
# 7. Building ESP8266 firmware
274+
275+
The following instructions assume that you have the toolchain for ESP8266 and
276+
can build and install standard firmware. They also assume knowledge of the
277+
process of freezing modules and the manifest system. They are based on Linux,
278+
the only OS for which I have any remotely recent experience. If you run
279+
Windows or OSX support will comprise the suggestion of a Linux VM ;-)
280+
281+
Ensure your clone of
282+
[the MicroPython source](https://github.com/micropython/micropython) is up to
283+
date, and that of this repository. Also clone
284+
[micropython-lib](https://github.com/micropython/micropython-lib). As an
285+
alternative, the library `errno.py` may be installed to your PC using
286+
[micropip](https://github.com/peterhinch/micropython-samples/tree/master/micropip).
287+
288+
Create a directory on your PC for symlinks to modules to be frozen. In my case
289+
it's called `frozen`. It contains symlinks (denoted ->) to the following:
290+
1. `_boot.py` -> `esp_link/_boot.py`.
291+
2. `inisetup.py` -> `esp_link/inisetup.py`.
292+
3. `flashbdev.py` -> `ports/esp8266/modules/flashbdev.py` in source tree.
293+
4. `errno.py` -> file in micropython-lib (or downloaded with micropip).
294+
The `frozen` directory has a subdirectory `iot` containing:
295+
1. `primitives` -> `iot/primitives`
296+
2. `client.py` -> `iot/client.py`
297+
The `iot` directory has an `esp_link` subdirectory containing:
298+
1. `as_i2c.py` -> `esp_link/as_i2c.py`
299+
2. `esp_link.py` -> `esp_link/esp_link.py`
300+
3. `__init__.py` an empty file created using `touch`.
301+
302+
Create a PC file containing a manifest. Mine is `esp8266_iot_manifest.py`. It
303+
should be as follows (with the path changed to your `frozen` directory):
304+
```
305+
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
306+
freeze('/mnt/qnap2/data/Projects/MicroPython/micropython-iot/private/frozen')
307+
```
308+
I use the following build script, named `buildesplink` and marked executable.
309+
Adapt to ensure that `MANIFEST` points to your manifest file. The `cd` in line
310+
8 will need to be changed to match the location of your source clone. The `j 8`
311+
arg to `make` may also be non-optimal for your PC.
312+
313+
`PROJECT_DIR` causes the firmware build to be copied to the project root. This
314+
is done purely to maintain this repo: you can remove this and the build copy.
315+
```bash
316+
#! /bin/bash
317+
# Build for ESP8266 esp_link
318+
319+
PROJECT_DIR='/mnt/qnap2/data/Projects/MicroPython/micropython-iot/'
320+
MANIFEST='/mnt/qnap2/Scripts/manifests/esp8266_iot_manifest.py'
321+
BUILD='build-GENERIC'
322+
323+
cd /mnt/qnap2/data/Projects/MicroPython/micropython/ports/esp8266
324+
if [ $# -eq 1 ] && [ $1 = "--clean" ]
325+
then
326+
make clean
327+
fi
328+
if [ $# -eq 1 ] && [ $1 = "--erase" ]
329+
then
330+
make clean
331+
esptool.py --port /dev/ttyUSB0 erase_flash
332+
fi
333+
334+
if make -j 8 FROZEN_MANIFEST=$MANIFEST
335+
then
336+
cp $BUILD/firmware-combined.bin $PROJECT_DIR
337+
sleep 1
338+
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash --verify --flash_size=detect -fm dio 0 $BUILD/firmware-combined.bin
339+
cd -
340+
sleep 1
341+
# rshell -p /dev/ttyUSB0 --editor nano --buffer-size=30
342+
else
343+
echo Build failure
344+
fi
345+
cd -
346+
```
347+
If you use the above script, issue `--erase` to erase flash on the ESP8266
348+
prior to installing the build. This ensures the use of littlefs. It also
349+
ensures that `boot.py` and `main.py` are created. The files `_boot.py` and
350+
`inisetup.py` handle filesystem creation and initial creation of `boot.py`
351+
and `main.py`, but only if there is no pre-existing filesystem.
352+
```

0 commit comments

Comments
 (0)