docs/esp8266: Add ESP8266 tutorial.
This commit is contained in:
parent
5e94f0b43a
commit
879bc4197a
|
@ -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.
|
|
@ -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
|
||||
================================
|
||||
|
||||
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
|
||||
|
|
|
@ -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.
|
|
@ -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)
|
|
@ -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.
|
|
@ -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()
|
|
@ -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!
|
|
@ -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.
|
|
@ -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.
|
|
@ -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')
|
||||
|
|
@ -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)
|
|
@ -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