docs/esp8266: Add ESP8266 tutorial.
This commit is contained in:
parent
5e94f0b43a
commit
879bc4197a
19
docs/esp8266/tutorial/adc.rst
Normal file
19
docs/esp8266/tutorial/adc.rst
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Analog to Digital Conversion
|
||||||
|
============================
|
||||||
|
|
||||||
|
The ESP8266 has a single pin (separate to the GPIO pins) which can be used to
|
||||||
|
read analog voltages and convert them to a digital value. You can construct
|
||||||
|
such an ADC pin object using::
|
||||||
|
|
||||||
|
>>> import machine
|
||||||
|
>>> adc = machine.ADC(0)
|
||||||
|
|
||||||
|
Then read its value with::
|
||||||
|
|
||||||
|
>>> adc.read()
|
||||||
|
58
|
||||||
|
|
||||||
|
The values returned from the ``read()`` function are between 0 (for 0.0 volts)
|
||||||
|
and 1024 (for 1.0 volts). Please note that this input can only tolerate a
|
||||||
|
maximum of 1.0 volts and you must use a voltage divider circuit to measure
|
||||||
|
larger voltages.
|
70
docs/esp8266/tutorial/filesystem.rst
Normal file
70
docs/esp8266/tutorial/filesystem.rst
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
The internal filesystem
|
||||||
|
=======================
|
||||||
|
|
||||||
|
If your devices has 1Mbyte or more of storage then it will be set up (upon first
|
||||||
|
boot) to contain a filesystem. This filesystem uses the FAT format and is
|
||||||
|
stored in the flash after the MicroPython firmware.
|
||||||
|
|
||||||
|
Creating and reading files
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
MicroPython on the ESP8266 supports the standard way of accessing files in
|
||||||
|
Python, using the built-in ``open()`` function.
|
||||||
|
|
||||||
|
To create a file try::
|
||||||
|
|
||||||
|
>>> f = open('data.txt', 'w')
|
||||||
|
>>> f.write('some data')
|
||||||
|
9
|
||||||
|
>>> f.close()
|
||||||
|
|
||||||
|
The "9" is the number of bytes that were written with the ``write()`` method.
|
||||||
|
Then you can read back the contents of this new file using::
|
||||||
|
|
||||||
|
>>> f = open('data.txt')
|
||||||
|
>>> f.read()
|
||||||
|
'some data'
|
||||||
|
>>> f.close()
|
||||||
|
|
||||||
|
Note that the default mode when opening a file is to open it in read-only mode,
|
||||||
|
and as a text file. Specify ``'wb'`` as the second argument to ``open()`` to
|
||||||
|
open for writing in binary mode, and ``'rb'`` to open for reading in binary
|
||||||
|
mode.
|
||||||
|
|
||||||
|
Listing file and more
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The os module can be used for further control over the filesystem. First
|
||||||
|
import the module::
|
||||||
|
|
||||||
|
>>> import os
|
||||||
|
|
||||||
|
Then try listing the contents of the filesystem::
|
||||||
|
|
||||||
|
>>> os.listdir()
|
||||||
|
['boot.py', 'port_config.py', 'data.txt']
|
||||||
|
|
||||||
|
You can make directories::
|
||||||
|
|
||||||
|
>>> os.mkdir('dir')
|
||||||
|
|
||||||
|
And remove entries::
|
||||||
|
|
||||||
|
>>> os.remove('data.txt')
|
||||||
|
|
||||||
|
Start up scripts
|
||||||
|
----------------
|
||||||
|
|
||||||
|
There are two files that are treated specially by the ESP8266 when it starts up:
|
||||||
|
boot.py and main.py. The boot.py script is executed first (if it exists) and
|
||||||
|
then once it completes the main.py script is executed. You can create these
|
||||||
|
files yourself and populate them with the code that you want to run when the
|
||||||
|
device starts up.
|
||||||
|
|
||||||
|
Accessing the filesystem via WebREPL
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
You can access the filesystem over WebREPL using the provided command-line
|
||||||
|
tool. This tool is found at `<https://github.com/micropython/webrepl>`__
|
||||||
|
and is called webrepl_cli.py. Please refer to that program for information
|
||||||
|
on how to use it.
|
@ -3,4 +3,30 @@
|
|||||||
MicroPython tutorial for ESP8266
|
MicroPython tutorial for ESP8266
|
||||||
================================
|
================================
|
||||||
|
|
||||||
TBD
|
This tutorial is intended to get you started using MicroPython on the ESP8266
|
||||||
|
system-on-a-chip. If it is your first time it is recommended to follow the
|
||||||
|
tutorial through in the order below. Otherwise the sections are mostly self
|
||||||
|
contained, so feel free to skip to those that interest you.
|
||||||
|
|
||||||
|
The tutorial does not assume that you know Python, but it also does not attempt
|
||||||
|
to explain any of the details of the Python language. Instead it provides you
|
||||||
|
with commands that are ready to run, and hopes that you will gain a bit of
|
||||||
|
Python knowledge along the way. To learn more about Python itself please refer
|
||||||
|
to `<https://www.python.org>`__.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:numbered:
|
||||||
|
|
||||||
|
intro.rst
|
||||||
|
repl.rst
|
||||||
|
filesystem.rst
|
||||||
|
network_basics.rst
|
||||||
|
network_tcp.rst
|
||||||
|
pins.rst
|
||||||
|
pwm.rst
|
||||||
|
adc.rst
|
||||||
|
powerctrl.rst
|
||||||
|
onewire.rst
|
||||||
|
neopixel.rst
|
||||||
|
nextsteps.rst
|
||||||
|
95
docs/esp8266/tutorial/intro.rst
Normal file
95
docs/esp8266/tutorial/intro.rst
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
Introduction to MicroPython on the ESP8266
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
Using MicroPython is a great way to get the most of your ESP8266 board. And
|
||||||
|
vice versa, the ESP8266 chip is a great platform for using MicroPython. This
|
||||||
|
tutorial will guide you through setting up MicroPython, getting a prompt, using
|
||||||
|
WebREPL, connecting to the network and communicating with the Internet, using
|
||||||
|
the hardware peripherals, and controlling some external components.
|
||||||
|
|
||||||
|
Let's get started!
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
The first thing you need is a board with an ESP8266 chip. The MicroPython
|
||||||
|
software supports the ESP8266 chip itself and any board should work. The main
|
||||||
|
characteristic of a board is how much flash it has, how the GPIO pins are
|
||||||
|
connected to the outside world, and whether it includes a built-in USB-serial
|
||||||
|
convertor to make the UART available to your PC.
|
||||||
|
|
||||||
|
The minimum requirement for flash size is 512k. A board with this amount of
|
||||||
|
flash will not have room for a filesystem, but otherwise is fully functional.
|
||||||
|
If your board has 1Mbyte or more of flash then it will support a filesystem.
|
||||||
|
|
||||||
|
Names of pins will be given in this tutorial using the chip names (eg GPIO0)
|
||||||
|
and it should be straightforward to find which pin this corresponds to on your
|
||||||
|
particular board.
|
||||||
|
|
||||||
|
Powering the board
|
||||||
|
------------------
|
||||||
|
|
||||||
|
If your board has a USB connector on it then most likely it is powered through
|
||||||
|
this when connected to your PC. Otherwise you will need to power it directly.
|
||||||
|
Please refer to the documentation for your board for further details.
|
||||||
|
|
||||||
|
Deploying the firmware
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The very first thing you need to do is put the MicroPython firmware (compiled
|
||||||
|
code) on your ESP8266 device. There are two main steps to do this: first you
|
||||||
|
need to put your device in boot-loader mode, and second you need to copy across
|
||||||
|
the firmware. The exact procedure for these steps is highly dependent on the
|
||||||
|
particular board and you will need to refer to its documentation for details.
|
||||||
|
|
||||||
|
If you have a board that has a USB connector, a USB-serial convertor, and has
|
||||||
|
the DTR and RTS pins wired in a special way then deploying the firmware should
|
||||||
|
be easy as all steps can be done automatically. Boards that have such features
|
||||||
|
include the Adafruit Feather HUZZAH and NodeMCU boards.
|
||||||
|
|
||||||
|
For best results it is recommended to first erase the entire flash of your
|
||||||
|
device before putting on new MicroPython firmware.
|
||||||
|
|
||||||
|
Currently we only support esptool.py to copy across the firmware. You can find
|
||||||
|
this tool here: `<https://github.com/themadinventor/esptool/>`__ . Any other
|
||||||
|
flashing program should work, so feel free to try them out, or refer to the
|
||||||
|
documentation for your board to see its recommendations.
|
||||||
|
|
||||||
|
Using esptool.py you can erase the flash with the command::
|
||||||
|
|
||||||
|
esptool.py --port /dev/ttyUSB0 erase_flash
|
||||||
|
|
||||||
|
And then deploy the new firmware using::
|
||||||
|
|
||||||
|
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 mp-esp8266-firmware.bin
|
||||||
|
|
||||||
|
You might need to change the "port" setting to something else relevant for your
|
||||||
|
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||||
|
(eg down to 115200).
|
||||||
|
|
||||||
|
If you have a NodeMCU board, you may need to use the following command to deploy
|
||||||
|
the firmware (note the "-fm dio" option)::
|
||||||
|
|
||||||
|
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m -fm dio 0 mp-esp8266-firmware.bin
|
||||||
|
|
||||||
|
If the above commands run without error then MicroPython should be installed on
|
||||||
|
your board!
|
||||||
|
|
||||||
|
Serial prompt
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Once you have the firmware on the device you can access the REPL (Python prompt)
|
||||||
|
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
||||||
|
convertor, depending on your board. The baudrate is 115200. The next part of
|
||||||
|
the tutorial will discuss the prompt in more detail.
|
||||||
|
|
||||||
|
WiFi
|
||||||
|
----
|
||||||
|
|
||||||
|
After a fresh install and boot the device configures itself as a WiFi access
|
||||||
|
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx
|
||||||
|
where the x's are replaced with part of the MAC address of your device (so will
|
||||||
|
be the same everytime, and most likely different for all ESP8266 chips). The
|
||||||
|
password for the WiFi is micropythoN (note the upper-case N). Its IP address
|
||||||
|
will be 192.168.4.1 once you connect to its network. WiFi configuration will
|
||||||
|
be discussed in more detail later in the tutorial.
|
70
docs/esp8266/tutorial/neopixel.rst
Normal file
70
docs/esp8266/tutorial/neopixel.rst
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
Controlling NeoPixels
|
||||||
|
=====================
|
||||||
|
|
||||||
|
NeoPixels, also known as WS2812 LEDs, are full-colour LEDs that are connected in
|
||||||
|
serial, are individually addressable, and can have their red, green and blue
|
||||||
|
components set between 0 and 255. They require precise timing to control them
|
||||||
|
and there is a special neopixel module to do just this.
|
||||||
|
|
||||||
|
To create a NeoPixel object do the following::
|
||||||
|
|
||||||
|
>>> import machine, neopixel
|
||||||
|
>>> np = neopixel.NeoPixel(machine.Pin(4), 8)
|
||||||
|
|
||||||
|
This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the
|
||||||
|
"4" (pin number) and the "8" (number of pixel) to suit your set up.
|
||||||
|
|
||||||
|
To set the colour of pixels use::
|
||||||
|
|
||||||
|
>>> np[0] = (255, 0, 0) # set to red, full brightness
|
||||||
|
>>> np[1] = (0, 128, 0) # set to green, half brightness
|
||||||
|
>>> np[2] = (0, 0, 64) # set to blue, quarter brightness
|
||||||
|
|
||||||
|
Then use the ``write()`` method to output the colours to the LEDs::
|
||||||
|
|
||||||
|
>>> np.write()
|
||||||
|
|
||||||
|
The following demo function makes a fancy show on the LEDs::
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
def demo(np):
|
||||||
|
n = np.n
|
||||||
|
|
||||||
|
# cycle
|
||||||
|
for i in range(4 * n):
|
||||||
|
for j in range(n):
|
||||||
|
np[j] = (0, 0, 0)
|
||||||
|
np[i % n] = (255, 255, 255)
|
||||||
|
np.write()
|
||||||
|
time.sleep_ms(25)
|
||||||
|
|
||||||
|
# bounce
|
||||||
|
for i in range(4 * n):
|
||||||
|
for j in range(n):
|
||||||
|
np[j] = (0, 0, 128)
|
||||||
|
if (i // n) % 2 == 0:
|
||||||
|
np[i % n] = (0, 0, 0)
|
||||||
|
else:
|
||||||
|
np[n - 1 - (i % n)] = (0, 0, 0)
|
||||||
|
np.write()
|
||||||
|
time.sleep_ms(60)
|
||||||
|
|
||||||
|
# fade in/out
|
||||||
|
for i in range(0, 4 * 256, 8):
|
||||||
|
for j in range(n):
|
||||||
|
if (i // 256) % 2 == 0:
|
||||||
|
val = i & 0xff
|
||||||
|
else:
|
||||||
|
val = 255 - (i & 0xff)
|
||||||
|
np[j] = (val, 0, 0)
|
||||||
|
np.write()
|
||||||
|
|
||||||
|
# clear
|
||||||
|
for i in range(n):
|
||||||
|
np[i] = (0, 0, 0)
|
||||||
|
np.write()
|
||||||
|
|
||||||
|
Execute it using::
|
||||||
|
|
||||||
|
>>> demo(np)
|
81
docs/esp8266/tutorial/network_basics.rst
Normal file
81
docs/esp8266/tutorial/network_basics.rst
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
Network basics
|
||||||
|
==============
|
||||||
|
|
||||||
|
The network module is used to configure the WiFi connection. There are two WiFi
|
||||||
|
interfaces, one for the station (when the ESP8266 connects to a router) and one
|
||||||
|
for the access point (for other devices to connect to the ESP8266). Create
|
||||||
|
instances of these objects using::
|
||||||
|
|
||||||
|
>>> import network
|
||||||
|
>>> sta_if = network.WLAN(network.STA_IF)
|
||||||
|
>>> ap_if = network.WLAN(network.AP_IF)
|
||||||
|
|
||||||
|
You can check if the interfaces are active by::
|
||||||
|
|
||||||
|
>>> sta_if.active()
|
||||||
|
False
|
||||||
|
>>> ap_if.active()
|
||||||
|
True
|
||||||
|
|
||||||
|
You can also check the network settings of the interface by::
|
||||||
|
|
||||||
|
>>> ap.ifconfig()
|
||||||
|
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
|
||||||
|
|
||||||
|
The returned values are: IP address, netmask, gateway, DNS.
|
||||||
|
|
||||||
|
Configuration of the WiFi
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Upon a fresh install the ESP8266 is configured in access point mode, so the
|
||||||
|
AP_IF interface is active and the STA_IF interface is inactive. You can
|
||||||
|
configure the module to connect to your own network using the STA_IF interface.
|
||||||
|
|
||||||
|
First activate the station interface::
|
||||||
|
|
||||||
|
>>> sta_if.active(True)
|
||||||
|
|
||||||
|
Then connect to your WiFi network::
|
||||||
|
|
||||||
|
>>> sta_if.connect('<your ESSID>', '<your password>')
|
||||||
|
|
||||||
|
To check if the connection is established use::
|
||||||
|
|
||||||
|
>>> sta_if.isconnected()
|
||||||
|
|
||||||
|
Once established you can check the IP address::
|
||||||
|
|
||||||
|
>>> sta_if.ifconfig()
|
||||||
|
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
|
||||||
|
|
||||||
|
You can then disable the access-point interface if you no longer need it::
|
||||||
|
|
||||||
|
>>> ap_if.active(False)
|
||||||
|
|
||||||
|
Here is a function you can run (or put in your boot.py file) to automatically
|
||||||
|
connect to your WiFi network::
|
||||||
|
|
||||||
|
def do_connect():
|
||||||
|
import network
|
||||||
|
sta_if = network.WLAN(network.STA_IF)
|
||||||
|
if not sta_if.isconnected():
|
||||||
|
print('connecting to network...')
|
||||||
|
sta_if.active(True)
|
||||||
|
sta_if.connect('<essid>', '<password>')
|
||||||
|
while not network.isconnected():
|
||||||
|
pass
|
||||||
|
print('network config:', sta_if.ifconfig())
|
||||||
|
|
||||||
|
Sockets
|
||||||
|
-------
|
||||||
|
|
||||||
|
Once the WiFi is set up the way to access the network is by using sockets.
|
||||||
|
A socket represents an endpoint on a network device, and when two sockets are
|
||||||
|
connected together communication can proceed.
|
||||||
|
Internet protocols are built on top of sockets, such as email (SMTP), the web
|
||||||
|
(HTTP), telnet, ssh, among many others. Each of these protocols is assigned
|
||||||
|
a specific port, which is just an integer. Given an IP address and a port
|
||||||
|
number you can connect to a remote device and start talking with it.
|
||||||
|
|
||||||
|
The next part of the tutorial discusses how to use sockets to do some common
|
||||||
|
and useful network tasks.
|
121
docs/esp8266/tutorial/network_tcp.rst
Normal file
121
docs/esp8266/tutorial/network_tcp.rst
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
Network - TCP sockets
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The building block of most of the internet is the TCP socket. These sockets
|
||||||
|
provide a reliable stream of bytes between the connected network devices.
|
||||||
|
This part of the tutorial will show how to use TCP sockets in a few different
|
||||||
|
cases.
|
||||||
|
|
||||||
|
Star Wars Asciimation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The simplest thing to do is to download data from the internet. In this case
|
||||||
|
we will use the Star Wars Asciimation service provided by the blinkenlights.nl
|
||||||
|
website. It uses the telnet protocol on port 23 to stream data to anyone that
|
||||||
|
connects. It's very simple to use because it doesn't require you to
|
||||||
|
authenticate (give a username or password), you can just start downloading data
|
||||||
|
straight away.
|
||||||
|
|
||||||
|
The first thing to do is make sure we have the socket module available::
|
||||||
|
|
||||||
|
>>> import socket
|
||||||
|
|
||||||
|
Then get the IP address of the server::
|
||||||
|
|
||||||
|
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
|
||||||
|
|
||||||
|
The ``getaddrinfo`` function actually returns a list of addresses, and each
|
||||||
|
address has more information than we need. We want to get just the first valid
|
||||||
|
address, and then just the IP address and port of the server. To do this use::
|
||||||
|
|
||||||
|
>>> addr = addr_info[0][-1]
|
||||||
|
|
||||||
|
If you type ``addr_info`` and ``addr`` at the prompt you will see exactly what
|
||||||
|
information they hold.
|
||||||
|
|
||||||
|
Using the IP address we can make a socket and connect to the server::
|
||||||
|
|
||||||
|
>>> s = socket.socket()
|
||||||
|
>>> s.connect(addr[0][-1])
|
||||||
|
|
||||||
|
Now that we are connected we can download and display the data::
|
||||||
|
|
||||||
|
>>> while True:
|
||||||
|
... data = s.recv(500)
|
||||||
|
... print(str(data, 'utf8'), end='')
|
||||||
|
...
|
||||||
|
|
||||||
|
When this loop executes it should start showing the animation (use ctrl-C to
|
||||||
|
interrupt it).
|
||||||
|
|
||||||
|
You should also be able to run this same code on your PC using normal Python if
|
||||||
|
you want to try it out there.
|
||||||
|
|
||||||
|
HTTP GET request
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The next example shows how to download a webpage. HTTP uses port 80 and you
|
||||||
|
first need to send a "GET" request before you can download anything. As part
|
||||||
|
of the request you need to specify the page to retrieve.
|
||||||
|
|
||||||
|
Let's define a function that can download and print a URL::
|
||||||
|
|
||||||
|
def http_get(url):
|
||||||
|
_, _, host, path = url.split('/', 3)
|
||||||
|
addr = socket.getaddrinfo(host, 80)[0][-1]
|
||||||
|
s = socket.socket()
|
||||||
|
s.connect(addr)
|
||||||
|
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
|
||||||
|
while True:
|
||||||
|
data = s.recv(100)
|
||||||
|
if data:
|
||||||
|
print(str(data, 'utf8'), end='')
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
Make sure that you import the socket module before running this function. Then
|
||||||
|
you can try::
|
||||||
|
|
||||||
|
>>> http_get('http://micropython.org/ks/test.html')
|
||||||
|
|
||||||
|
This should retrieve the webpage and print the HTML to the console.
|
||||||
|
|
||||||
|
Simple HTTP server
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The following code creates an simple HTTP server which serves a single webpage
|
||||||
|
that contains a table with the state of all the GPIO pins::
|
||||||
|
|
||||||
|
import machine
|
||||||
|
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)]
|
||||||
|
|
||||||
|
html = """<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head> <title>ESP8266 Pins</title> </head>
|
||||||
|
<body> <h1>ESP8266 Pins</h1>
|
||||||
|
<table border="1"> <tr><th>Pin</th><th>Value</th></tr> %s </table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
import socket
|
||||||
|
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||||
|
|
||||||
|
s = socket.socket()
|
||||||
|
s.bind(addr)
|
||||||
|
s.listen(1)
|
||||||
|
|
||||||
|
print('listening on', addr)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
cl, addr = s.accept()
|
||||||
|
print('client connected from', addr)
|
||||||
|
cl_file = cl.makefile('rwb', 0)
|
||||||
|
while True:
|
||||||
|
line = cl_file.readline()
|
||||||
|
if not line or line == b'\r\n':
|
||||||
|
break
|
||||||
|
rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
|
||||||
|
response = html % '\n'.join(rows)
|
||||||
|
cl.send(response)
|
||||||
|
cl.close()
|
12
docs/esp8266/tutorial/nextsteps.rst
Normal file
12
docs/esp8266/tutorial/nextsteps.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Next steps
|
||||||
|
==========
|
||||||
|
|
||||||
|
That brings us to the end of the tutorial! Hopefully by now you have a good
|
||||||
|
feel for the capabilities of MicroPython on the ESP8266 and understand how to
|
||||||
|
control both the WiFi and IO aspects of the chip.
|
||||||
|
|
||||||
|
There are many features that were not covered in this tutorial. The best way
|
||||||
|
to learn about them is to read the full documentation of the modules, and to
|
||||||
|
experiment!
|
||||||
|
|
||||||
|
Good luck creating your Internet of Things devices!
|
37
docs/esp8266/tutorial/onewire.rst
Normal file
37
docs/esp8266/tutorial/onewire.rst
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
Controlling 1-wire devices
|
||||||
|
==========================
|
||||||
|
|
||||||
|
The 1-wire bus is a serial bus that uses just a single wire for communication
|
||||||
|
(in addition to wires for ground and power). The DS18B20 temperature sensor
|
||||||
|
is a very popular 1-wire device, and here we show how to use the onewire module
|
||||||
|
to read from such a device.
|
||||||
|
|
||||||
|
For the following code to work you need to have at least one DS18B20 temperature
|
||||||
|
sensor with its data line connected to GPIO12. You must also power the sensors
|
||||||
|
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
|
||||||
|
|
||||||
|
import time
|
||||||
|
import machine
|
||||||
|
import onewire
|
||||||
|
|
||||||
|
# the device is on GPIO12
|
||||||
|
dat = machine.Pin(12)
|
||||||
|
|
||||||
|
# create the onewire object
|
||||||
|
ds = onewire.DS18B20(onewire.OneWire(dat))
|
||||||
|
|
||||||
|
# scan for devices on the bus
|
||||||
|
roms = ds.scan()
|
||||||
|
print('found devices:', roms)
|
||||||
|
|
||||||
|
# loop 10 times and print all temperatures
|
||||||
|
for i in range(10):
|
||||||
|
print('temperatures:', end=' ')
|
||||||
|
ds.convert_temp()
|
||||||
|
time.sleep_ms(750)
|
||||||
|
for rom in roms:
|
||||||
|
print(ds.read_temp(rom), end=' ')
|
||||||
|
print()
|
||||||
|
|
||||||
|
Note that you must execute the ``convert_temp()`` function to initiate a
|
||||||
|
temperature reading, then wait at least 750ms before reading the value.
|
75
docs/esp8266/tutorial/pins.rst
Normal file
75
docs/esp8266/tutorial/pins.rst
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
GPIO Pins
|
||||||
|
=========
|
||||||
|
|
||||||
|
The way to connect your board to the external world, and control other
|
||||||
|
components, is through the GPIO pins. Not all pins are available to use,
|
||||||
|
in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used.
|
||||||
|
|
||||||
|
The pins are available in the machine module, so make sure you import that
|
||||||
|
first. Then you can create a pin using::
|
||||||
|
|
||||||
|
>>> pin = machine.Pin(0)
|
||||||
|
|
||||||
|
Here, the "0" is the pin that you want to access. Usually you want to
|
||||||
|
configure the pin to be input or output, and you do this when constructing
|
||||||
|
it. To make an input pin use::
|
||||||
|
|
||||||
|
>>> pin = machine.Pin(0, machine.Pin.OUT, machine.Pin.PULL_UP)
|
||||||
|
|
||||||
|
You can either use PULL_UP or PULL_NONE for the input pull-mode. If it's
|
||||||
|
not specified then it defaults to PULL_NONE. You can read the value on
|
||||||
|
the pin using::
|
||||||
|
|
||||||
|
>>> pin.value()
|
||||||
|
0
|
||||||
|
|
||||||
|
The pin on your board may return 0 or 1 here, depending on what it's connected
|
||||||
|
to. To make an output pin use::
|
||||||
|
|
||||||
|
>>> pin = machine.Pin(0, machine.Pin.OUT)
|
||||||
|
|
||||||
|
Then set its value using::
|
||||||
|
|
||||||
|
>>> pin.value(0)
|
||||||
|
>>> pin.value(1)
|
||||||
|
|
||||||
|
Or::
|
||||||
|
|
||||||
|
>>> pin.low()
|
||||||
|
>>> pin.high()
|
||||||
|
|
||||||
|
External interrupts
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
All pins except number 16 can be configured to trigger a hard interrupt if their
|
||||||
|
input changes. You can set code (a callback function) to be executed on the
|
||||||
|
trigger.
|
||||||
|
|
||||||
|
Let's first define a callback function, which must take a single argument,
|
||||||
|
being the pin that triggered the function. We will make the function just print
|
||||||
|
the pin::
|
||||||
|
|
||||||
|
>>> def callback(p):
|
||||||
|
... print('pin change', p)
|
||||||
|
|
||||||
|
Next we will create two pins and configure them as inputs::
|
||||||
|
|
||||||
|
>>> from machine import Pin
|
||||||
|
>>> p0 = Pin(0, Pin.IN)
|
||||||
|
>>> p2 = Pin(2, Pin.IN)
|
||||||
|
|
||||||
|
An finally we need to tell the pins when to trigger, and the function to call
|
||||||
|
when they detect an event::
|
||||||
|
|
||||||
|
>>> p0.irq(Pin.IRQ_FALLING, callback)
|
||||||
|
>>> p2.irq(Pin.IRQ_RISING | Pin.IRQ_FALLING, callback)
|
||||||
|
|
||||||
|
We set pin 0 to trigger only on a falling edge of the input (when it goes from
|
||||||
|
high to low), and set pin 2 to trigger on both a rising and falling edge. After
|
||||||
|
entering this code you can apply high and low voltages to pins 0 and 2 to see
|
||||||
|
the interrupt being executed.
|
||||||
|
|
||||||
|
A hard interrupt will trigger as soon as the event occurs and will interrupt any
|
||||||
|
running code, including Python code. As such your callback functions are
|
||||||
|
limited in what they can do (they cannot allocate memory, for example) and
|
||||||
|
should be as short and simple as possible.
|
61
docs/esp8266/tutorial/powerctrl.rst
Normal file
61
docs/esp8266/tutorial/powerctrl.rst
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
Power control
|
||||||
|
=============
|
||||||
|
|
||||||
|
The ESP8266 provides the ability to change the CPU frequency on the fly, and
|
||||||
|
enter a deep-sleep state. Both can be used to manage power consumption.
|
||||||
|
|
||||||
|
Changing the CPU frequency
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The machine module has a function to get and set the CPU frequency. To get the
|
||||||
|
current frequency use::
|
||||||
|
|
||||||
|
>>> import machine
|
||||||
|
>>> machine.freq()
|
||||||
|
80000000
|
||||||
|
|
||||||
|
By default the CPU runs at 80MHz. It can be change to 160MHz if you need more
|
||||||
|
processing power, at the expense of current consumption::
|
||||||
|
|
||||||
|
>>> machine.freq(160000000)
|
||||||
|
>>> machine.freq()
|
||||||
|
160000000
|
||||||
|
|
||||||
|
You can change to the higher frequency just while your code does the heavy
|
||||||
|
processing and then change back when its finished.
|
||||||
|
|
||||||
|
Deep-sleep mode
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The deep-sleep mode will shut down the ESP8266 and all its peripherals,
|
||||||
|
including the WiFi (but not including the real-time-clock, which is used to wake
|
||||||
|
the chip). This drastically reduces current consumption and is a good way to
|
||||||
|
make devices that can run for a while on a battery.
|
||||||
|
|
||||||
|
To be able to use the deep-sleep feature you must connect GPIO16 to the reset
|
||||||
|
pin (RST on the Adafruit Feather HUZZAH board). Then the following code can be
|
||||||
|
used to sleep and wake the device::
|
||||||
|
|
||||||
|
import machine
|
||||||
|
|
||||||
|
# configure RTC.ALARM0 to be able to wake the device
|
||||||
|
rtc = machine.RTC()
|
||||||
|
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
|
||||||
|
|
||||||
|
# set RTC.ALARM0 to fire after 10 seconds (waking the device)
|
||||||
|
rtc.alarm(rtc.ALARM0, 10000)
|
||||||
|
|
||||||
|
# put the device to sleep
|
||||||
|
machine.deepsleep()
|
||||||
|
|
||||||
|
Note that when the chip wakes from a deep-sleep it is completely reset,
|
||||||
|
including all of the memory. The boot scripts will run as usual and you can
|
||||||
|
put code in them to check the reset cause to perhaps do something different if
|
||||||
|
the device just woke from a deep-sleep. For example, to print the reset cause
|
||||||
|
you can use::
|
||||||
|
|
||||||
|
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
|
||||||
|
print('woke from a deep sleep')
|
||||||
|
else:
|
||||||
|
print('power on or hard reset')
|
||||||
|
|
87
docs/esp8266/tutorial/pwm.rst
Normal file
87
docs/esp8266/tutorial/pwm.rst
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
Pulse Width Modulation
|
||||||
|
======================
|
||||||
|
|
||||||
|
Pulse width modulation (PWM) is a way to get an artificial analog output on a
|
||||||
|
digital pin. It achieves this by rapidly toggling the pin from low to high.
|
||||||
|
There are two parameters associated with this: the frequency of the toggling,
|
||||||
|
and the duty cycle. The duty cycle is defined to be how long the pin is high
|
||||||
|
compared with the length of a single period (low plus high time). Maximum
|
||||||
|
duty cycle is when the pin is high all of the time, and minimum is when it is
|
||||||
|
low all of the time.
|
||||||
|
|
||||||
|
On the ESP8266 the pins 0, 2, 4, 5, 12, 13, 14 and 15 all support PWM. The
|
||||||
|
limitation is that they must all be at the same frequency, and the frequency
|
||||||
|
must be between 1Hz and 1kHz.
|
||||||
|
|
||||||
|
To use PWM on a pin you must first create the pin object, for example::
|
||||||
|
|
||||||
|
>>> import machine
|
||||||
|
>>> p12 = machine.Pin(12)
|
||||||
|
|
||||||
|
Then create the PWM object using::
|
||||||
|
|
||||||
|
>>> pwm12 = machine.PWM(p12)
|
||||||
|
|
||||||
|
You can set the frequency and duty cycle using::
|
||||||
|
|
||||||
|
>>> pwm12.freq(500)
|
||||||
|
>>> pwm12.duty(512)
|
||||||
|
|
||||||
|
Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512
|
||||||
|
being a 50% duty. If you print the PWM object then it will tell you its current
|
||||||
|
configuration::
|
||||||
|
|
||||||
|
>>> pwm12
|
||||||
|
PWM(12, freq=500, duty=512)
|
||||||
|
|
||||||
|
You can also call the ``freq()`` and ``duty()`` methods with no arguments to
|
||||||
|
get their current values.
|
||||||
|
|
||||||
|
The pin will continue to be in PWM mode until you deinitialise it using::
|
||||||
|
|
||||||
|
>>> pwm12.deinit()
|
||||||
|
|
||||||
|
Fading an LED
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Let's use the PWM feature to fade an LED. Assuming your board has an LED
|
||||||
|
connected to pin 2 (ESP-12 modules do) we can create an LED-PWM object using::
|
||||||
|
|
||||||
|
>>> led = machine.PWM(machine.Pin(2), freq=1000)
|
||||||
|
|
||||||
|
Notice that we can set the frequency in the PWM constructor.
|
||||||
|
|
||||||
|
For the next part we will use timing and some math, so import these modules::
|
||||||
|
|
||||||
|
>>> import time, math
|
||||||
|
|
||||||
|
Then create a function to pulse the LED::
|
||||||
|
|
||||||
|
>>> def pulse(l, t):
|
||||||
|
... for i in range(20):
|
||||||
|
... l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
|
||||||
|
... time.sleep_ms(t)
|
||||||
|
|
||||||
|
You can try this function out using::
|
||||||
|
|
||||||
|
>>> pulse(led, 50)
|
||||||
|
|
||||||
|
For a nice effect you can pulse many times in a row::
|
||||||
|
|
||||||
|
>>> for i in range(10):
|
||||||
|
... pulse(led, 20)
|
||||||
|
|
||||||
|
Remember you can use ctrl-C to interrupt the code.
|
||||||
|
|
||||||
|
Control a hobby servo
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Hobby servo motors can be controlled using PWM. They require a frequency of
|
||||||
|
50Hz and then a duty between about 40 and 115, with 77 being the centre value.
|
||||||
|
If you connect a servo to the power and ground pins, and then the signal line
|
||||||
|
to pin 12 (other pins will work just as well), you can control the motor using::
|
||||||
|
|
||||||
|
>>> servo = machine.PWM(machine.Pin(12), freq=50)
|
||||||
|
>>> servo.duty(40)
|
||||||
|
>>> servo.duty(115)
|
||||||
|
>>> servo.duty(77)
|
205
docs/esp8266/tutorial/repl.rst
Normal file
205
docs/esp8266/tutorial/repl.rst
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
Getting a MicroPython REPL prompt
|
||||||
|
=================================
|
||||||
|
|
||||||
|
REPL stands for Read Evaluate Print Loop, and is the name given to the
|
||||||
|
interactive MicroPython prompt that you can access on the ESP8266. Using the
|
||||||
|
REPL is by far the easiest way to test out your code and run commands.
|
||||||
|
|
||||||
|
There are two ways to access the REPL: either via a wired connection through the
|
||||||
|
UART serial port, or via WiFi.
|
||||||
|
|
||||||
|
REPL over the serial port
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The REPL is always available on the UART0 serial peripheral, which is connected
|
||||||
|
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200.
|
||||||
|
If your board has a USB-serial convertor on it then you should be able to access
|
||||||
|
the REPL directly from your PC. Otherwise you will need to have a way of
|
||||||
|
communicating with the UART.
|
||||||
|
|
||||||
|
To access the prompt over USB-serial you need to use a terminal emulator program.
|
||||||
|
On Windows TeraTerm is a good choice, on Mac you can use the built-in screen
|
||||||
|
program, and Linux has picocom and minicom. Of course, there are many other
|
||||||
|
terminal programs that will work, so pick your favourite!
|
||||||
|
|
||||||
|
For example, on Linux you can try running::
|
||||||
|
|
||||||
|
picocom /dev/ttyUSB0
|
||||||
|
|
||||||
|
Once you have made the connection over the serial port you can test if it is
|
||||||
|
working by hitting enter a few times. You should see the Python REPL prompt,
|
||||||
|
indicated by ``>>>``.
|
||||||
|
|
||||||
|
WebREPL - a prompt over WiFi
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
WebREPL allows you to use the Python prompt over WiFi, connecting through a
|
||||||
|
browser.
|
||||||
|
|
||||||
|
The first thing you need to do is get the WebREPL client loaded in your
|
||||||
|
favourite browser. The client can be found in the GitHub repository
|
||||||
|
`<https://github.com/micropython/webrepl>`__ . It is called webrepl.html.
|
||||||
|
The latest versions of Firefox and Chrome are supported.
|
||||||
|
|
||||||
|
To use WebREPL connect your computer to the ESP8266's access point
|
||||||
|
(MicroPython-xxxxxx, see the previous section about this). If you have
|
||||||
|
already reconfigured your ESP8266 to connect to a router then you can
|
||||||
|
skip this part.
|
||||||
|
|
||||||
|
Once you are on the same network as the ESP8266 you should then open
|
||||||
|
open webrepl.html in your browser and click the "Connect" button (if
|
||||||
|
you are connecting via a router then you may need to change the IP address,
|
||||||
|
by default the IP address is correct when connected to the ESP8266's access
|
||||||
|
point). If the connection succeeds then you should see a welcome message.
|
||||||
|
|
||||||
|
On the first connection you need to set a password. Make sure that the
|
||||||
|
terminal widget is selected by clicking on it, and then type it your password
|
||||||
|
twice (they should match each other). Then ESP8266 will then reboot with
|
||||||
|
the password applied (the WiFi will go down but come back up again).
|
||||||
|
|
||||||
|
You should then click the "Connect" button again, and enter your password
|
||||||
|
to connect. If you type in the correct password you should get a prompt
|
||||||
|
looking like ``>>>``. You can now start typing Python commands!
|
||||||
|
|
||||||
|
Using the REPL
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Once you have a prompt you can start experimenting! Anything you type at the
|
||||||
|
prompt will be executed after you press the Enter key. MicroPython will run
|
||||||
|
the code that you enter and print the result (if there is one). If there is an
|
||||||
|
error with the text that you enter then an error message is printed.
|
||||||
|
|
||||||
|
Try typing the following at the prompt::
|
||||||
|
|
||||||
|
>>> print('hello esp8266!')
|
||||||
|
hello esp8266!
|
||||||
|
|
||||||
|
Note that you shouldn't type the ``>>>`` arrows, they are there to indicate that
|
||||||
|
you should type the text after it at the prompt. And then the line following is
|
||||||
|
what the device should respond with. In the end, once you have entered the text
|
||||||
|
``print("hello esp8266!")`` and pressed the Enter key, the output on your screen
|
||||||
|
should look exactly like it does above.
|
||||||
|
|
||||||
|
If you already know some python you can now try some basic commands here. For
|
||||||
|
example::
|
||||||
|
|
||||||
|
>>> 1 + 2
|
||||||
|
3
|
||||||
|
>>> 1 / 2
|
||||||
|
0.5
|
||||||
|
>>> 12**34
|
||||||
|
4922235242952026704037113243122008064
|
||||||
|
|
||||||
|
If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can
|
||||||
|
turn it on and off using the following code::
|
||||||
|
|
||||||
|
>>> import machine
|
||||||
|
>>> pin = machine.Pin(2, machine.Pin.OUT)
|
||||||
|
>>> pin.high()
|
||||||
|
>>> pin.low()
|
||||||
|
|
||||||
|
Note that ``high`` might turn the LED off and ``low`` might turn it on (or vice
|
||||||
|
versa), depending on how the LED is wired on your board.
|
||||||
|
|
||||||
|
Line editing
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
You can edit the current line that you are entering using the left and right
|
||||||
|
arrow keys to move the cursor, as well as the delete and backspace keys. Also,
|
||||||
|
pressing Home or ctrl-A moves the cursor to the start of the line, and pressing
|
||||||
|
End or ctrl-E moves to the end of the line.
|
||||||
|
|
||||||
|
Input history
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The REPL remembers a certain number of previous lines of text that you entered
|
||||||
|
(up to 8 on the ESP8266). To recall previous lines use the up and down arrow
|
||||||
|
keys.
|
||||||
|
|
||||||
|
Tab completion
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Pressing the Tab key will do an auto-completion of the current word that you are
|
||||||
|
entering. This can be very useful to find out functions and methods that a
|
||||||
|
module or object has. Try it out by typing "ma" and then pressing Tab. It
|
||||||
|
should complete to "machine" (assuming you imported machine in the above
|
||||||
|
example). Then type "." and press Tab again to see a list of all the functions
|
||||||
|
that the machine module has.
|
||||||
|
|
||||||
|
Line continuation and auto-indent
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Certain things that you type will need "continuing", that is, will need more
|
||||||
|
lines of text to make a proper Python statement. In this case the prompt will
|
||||||
|
change to ``...`` and the cursor will auto-indent the correct amount so you can
|
||||||
|
start typing the next line straight away. Try this by defining the following
|
||||||
|
function::
|
||||||
|
|
||||||
|
>>> def toggle(p):
|
||||||
|
... p.value(not p.value())
|
||||||
|
...
|
||||||
|
...
|
||||||
|
...
|
||||||
|
>>>
|
||||||
|
|
||||||
|
In the above, you needed to press the Enter key three times in a row to finish
|
||||||
|
the compound statement (that's the three lines with just dots on them). The
|
||||||
|
other way to finish a compound statement is to press backspace to get to the
|
||||||
|
start of the line, then press the Enter key. (If you did something wrong and
|
||||||
|
want to escape the continuation mode then press ctrl-C; all lines will be
|
||||||
|
ignored.)
|
||||||
|
|
||||||
|
The function you just defined allows you to toggle a pin. The pin object you
|
||||||
|
created earlier should still exist (recreate it if it doesn't) and you can
|
||||||
|
toggle the LED using::
|
||||||
|
|
||||||
|
>>> toggle(pin)
|
||||||
|
|
||||||
|
Let's now toggle the LED in a loop (if you don't have an LED then you can just
|
||||||
|
print some text instead of calling toggle, to see the effect)::
|
||||||
|
|
||||||
|
>>> import time
|
||||||
|
>>> while True:
|
||||||
|
... toggle(pin)
|
||||||
|
... time.sleep_ms(500)
|
||||||
|
...
|
||||||
|
...
|
||||||
|
...
|
||||||
|
>>>
|
||||||
|
|
||||||
|
This will toggle the LED at 1Hz (half a second on, half a second off). To stop
|
||||||
|
the toggling press ctrl-C, which will raise a KeyboardInterrupt exception and
|
||||||
|
break out of the loop.
|
||||||
|
|
||||||
|
The time module provides some useful functions for making delays and doing
|
||||||
|
timing. Use tab completion to find out what they are and play around with them!
|
||||||
|
|
||||||
|
Paste mode
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Pressing ctrl-E will enter a special paste mode. This allows you to copy and
|
||||||
|
paste a chunk of text into the REPL. If you press ctrl-E you will see the
|
||||||
|
paste-mode prompt::
|
||||||
|
|
||||||
|
paste mode; Ctrl-C to cancel, Ctrl-D to finish
|
||||||
|
===
|
||||||
|
|
||||||
|
You can then paste (or type) your text in. Note that none of the special keys
|
||||||
|
or commands work in paste mode (eg Tab or backspace), they are just accepted
|
||||||
|
as-is. Press ctrl-D to finish entering the text and execute it.
|
||||||
|
|
||||||
|
Other control commands
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
There are four other control commands:
|
||||||
|
|
||||||
|
* Ctrl-A on a blank line will enter raw REPL mode. This is like a permanent
|
||||||
|
paste mode, except that characters are not echoed back.
|
||||||
|
|
||||||
|
* Ctrl-B on a blank like goes to normal REPL mode.
|
||||||
|
|
||||||
|
* Ctrl-C cancels any input, or interrupts the currently running code.
|
||||||
|
|
||||||
|
* Ctrl-D on a blank line will do a soft reset.
|
||||||
|
|
||||||
|
Note that ctrl-A and ctrl-D do not work with WebREPL.
|
Loading…
Reference in New Issue
Block a user