diff options
Diffstat (limited to 'docs')
41 files changed, 2013 insertions, 392 deletions
diff --git a/docs/Makefile b/docs/Makefile index 7da33e9a3e..9756fab286 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = -BUILDDIR = build +BUILDDIR = build/$(MICROPY_PORT) # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) diff --git a/docs/README.md b/docs/README.md index d3e1e8d69e..c594030999 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,7 +21,7 @@ preferably in a virtualenv: In `micropython/docs`, build the docs: - make MICROPY_PORT=<port_name> BUILDDIR=build/<port_name> html + make MICROPY_PORT=<port_name> html Where `<port_name>` can be `unix`, `pyboard`, `wipy` or `esp8266`. diff --git a/docs/conf.py b/docs/conf.py index 3eb13460fe..9163e04c79 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,10 +26,10 @@ from collections import OrderedDict micropy_port = os.getenv('MICROPY_PORT') or 'pyboard' tags.add('port_' + micropy_port) ports = OrderedDict(( - ('unix', ('unix', 'unix')), - ('pyboard', ('pyboard', 'the pyboard')), - ('wipy', ('WiPy', 'the WiPy')), - ('esp8266', ('ESP8266', 'the ESP8266')), + ('unix', 'unix'), + ('pyboard', 'the pyboard'), + ('wipy', 'the WiPy'), + ('esp8266', 'the ESP8266'), )) # The members of the html_context dict are available inside topindex.html @@ -38,11 +38,10 @@ micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',' url_pattern = '%s/en/%%s/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',) html_context = { 'port':micropy_port, - 'port_short_name':ports[micropy_port][0], - 'port_name':ports[micropy_port][1], + 'port_name':ports[micropy_port], 'port_version':micropy_version, 'all_ports':[ - (port_name[0], url_pattern % (micropy_version, port_id)) + (port_id, url_pattern % (micropy_version, port_id)) for port_id, port_name in ports.items() ], 'all_versions':[ @@ -92,9 +91,9 @@ copyright = '2014-2016, Damien P. George and contributors' # built documents. # # The short X.Y version. -version = '1.7' +version = '1.8' # The full version, including alpha/beta/rc tags. -release = '1.7' +release = '1.8' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst new file mode 100644 index 0000000000..f996068d09 --- /dev/null +++ b/docs/esp8266/general.rst @@ -0,0 +1,93 @@ +General information about the ESP8266 port +========================================== + +ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems. + +Multitude of boards +------------------- + +There are multitude of modules and boards from different sources which carry +ESP8266 chip. MicroPython tries to provide a generic port which would run on +as many boards/modules as possible, but there may be limitations. Adafruit +Feather HUZZAH board is taken as a reference board for the port (for example, +testing is performed on it). If you have another board, please make sure you +have datasheet, schematics and other reference materials for your board +handy to look up various aspects of your board functioning. + +To make a generic ESP8266 port and support as many boards as possible, +following design and implementation decision were made: + +* GPIO pin numbering is based on ESP8266 chip numbering, not some "logical" + numbering of a particular board. Please have manual/pin diagram of your board + handy to find correspondce between your board pins and actual ESP8266 pins. + We also encourage users of various boards to share this mapping via MicroPython + forum, with the idea to collect community-maintained reference materials + eventually. +* All pins which make sense to support, are supported by MicroPython + (for example, we don't expose pins which are used to connect SPI flash + are not exposed, as they're unlikely useful for anything else, and + operating on them will lead to board lock-up). However, any particular + board may expose only subset of pins. Consult your board reference manual. +* Some boards may lack external pins/internal connectivity to support + ESP8266 deepsleep mode. + + +Technical specifications and SoC datasheets +------------------------------------------- + +The datasheets and other reference material for ESP8266 chip are available +from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 . +The are primary reference for the chip technical specifications, capabilities, +operating modes, internal functioning, etc. + +For your convinience, some of technical specifications are provided below: + +* Architecture: Xtensa lx106 +* CPU frequency: 80MHz overclockable to 160MHz +* Total RAM available: 96KB (part of it reserved for system) +* BootROM: 64KB +* Internal FlashROM: None +* External FlashROM: code and data, via SPI Flash. Normal sizes 512KB-4MB. +* GPIO: 16 + 1 (GPIOs are multiplexed with other functions, including + external FlashROM, UART, deep sleep wake-up, etc.) +* UART: One RX/TX UART (no hardware handshaking), one TX-only UART. +* SPI: 2 SPI interfaces (one used for FlashROM). +* I2C: No native extenal I2C (bitbang implementation available on any pins). +* I2S: 1. +* Programming: using BootROM bootloader from UART. Due to external FlashROM + and always-available BootROM bootloader, ESP8266 is not brickable. + + +Boot process +------------ + +On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal +frozen modules. It mounts filesystem in FlashROM, or if it's not available, +performs first-time setup of the module and creates the filesystem. This +part of boot process is considered fixed, and not available for customization +for end users (even if you build from source, please refrain from changes to +it; customization of early boot process is available only to advanced users +and developers, who can diagnose themselves any issues arising from +modifying the standard process). + +Once filesystem is mounted, ``boot.py`` is executed from it. The standard +version of this file is created during first-time module set up and by +defaults starts up a WebREPL daemon to handle incoming connections. This +file is customizable by end users (for example, you may want to disable +WebREPL for extra security, or add other services which should be run on +module start-up). But keep in mind that incorrect modifications to boot.py +may still lead to boot loops or lock ups, requiring to reflash a module +from scratch. + +As a final step of boot procedure, ``main.py`` is executed from filesystem, +if exists. This file is a hook to start up a user application each time +on boot (instead of going to REPL). For small test applications, you may +name them directly as ``main.py``, and upload to module, but instead it's +recommended to keep your application(s) in separate files, and have just +the following in ``main.py``:: + + import my_app + my_app.main() + +This will allow to keep structure of your application clear, as well as +allow to install multiple applications on a board, and switch among them. diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index febad37366..bfded9bea1 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -202,6 +202,28 @@ The I2C driver is implemented in software and works on all pins:: i2c.readfrom(0x3a, 4, stop=False) # don't send a stop bit after reading i2c.writeto(0x3a, buf, stop=False) # don't send a stop bit after writing +Deep-sleep mode +--------------- + +Connect GPIO16 to the reset pin (RST on HUZZAH). Then the following code +can be used to sleep, wake and check the reset cause:: + + import machine + + # configure RTC.ALARM0 to be able to wake the device + rtc = machine.RTC() + rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) + + # check if the device woke from a deep sleep + if machine.reset_cause() == machine.DEEPSLEEP_RESET: + print('woke from a deep sleep') + + # set RTC.ALARM0 to fire after 10 seconds (waking the device) + rtc.alarm(rtc.ALARM0, 10000) + + # put the device to sleep + machine.deepsleep() + OneWire driver -------------- @@ -213,10 +235,10 @@ The OneWire driver is implemented in software and works on all pins:: ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 ow.scan() # return a list of devices on the bus ow.reset() # reset the bus - ow.read_byte() # read a byte - ow.read_bytes(5) # read 5 bytes - ow.write_byte(0x12) # write a byte on the bus - ow.write_bytes('123') # write bytes on the bus + ow.readbyte() # read a byte + ow.read(5) # read 5 bytes + ow.writebyte(0x12) # write a byte on the bus + ow.write('123') # write bytes on the bus ow.select_rom(b'12345678') # select a specific device by its ROM code There is a specific driver for DS18B20 devices:: @@ -224,12 +246,14 @@ There is a specific driver for DS18B20 devices:: import time ds = onewire.DS18B20(ow) roms = ds.scan() - ds.start_measure() + ds.convert_temp() time.sleep_ms(750) for rom in roms: - print(ds.get_temp(rom)) + print(ds.read_temp(rom)) -Be sure to put a 4.7k pull-up resistor on the data line. +Be sure to put a 4.7k pull-up resistor on the data line. Note that +the ``convert_temp()`` method must be called each time you want to +sample the temperature. NeoPixel driver --------------- @@ -245,10 +269,36 @@ Use the ``neopixel`` module:: np.write() # write data to all pixels r, g, b = np[0] # get first pixel colour - import neopixel - neopixel.demo(np) # run a demo - For low-level driving of a NeoPixel:: import esp esp.neopixel_write(pin, grb_buf, is800khz) + +WebREPL (web browser interactive prompt) +---------------------------------------- + +WebREPL (REPL over WebSockets, accessible via a web browser) is an +experimental feature available in ESP8266 port. Download web client +from https://github.com/micropython/webrepl , and start daemon using:: + + import webrepl + webrepl.start() + +(Release version will have it started on boot by default.) + +On a first connection, you will be prompted to set password for future +sessions to use. + +The supported way to use WebREPL is by connecting to ESP8266 access point, +but the daemon is also started on STA interface if it is active, so if your +routers is set up and works correctly, you may also use it while connecting +to your normal Internet access point (use ESP8266 AP connection method if +face any issues). + +WebREPL is an experimental feature and a work in progress, and has known +issues. There's also provision to transfer (both upload and download) +files over WebREPL connection, but it has unstable status (be ready to +reboot a module in case of issues). It still may be a practical way to +get script files onto ESP8266, so give it a try using ``webrepl_cli.py`` +from the repository above. See forum for other community-supported +alternatives to transfer files to ESP8266. diff --git a/docs/esp8266/tutorial/adc.rst b/docs/esp8266/tutorial/adc.rst new file mode 100644 index 0000000000..fa6fdaba73 --- /dev/null +++ b/docs/esp8266/tutorial/adc.rst @@ -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. diff --git a/docs/esp8266/tutorial/filesystem.rst b/docs/esp8266/tutorial/filesystem.rst new file mode 100644 index 0000000000..9033a8576f --- /dev/null +++ b/docs/esp8266/tutorial/filesystem.rst @@ -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. diff --git a/docs/esp8266/tutorial/index.rst b/docs/esp8266/tutorial/index.rst new file mode 100644 index 0000000000..1a00afd853 --- /dev/null +++ b/docs/esp8266/tutorial/index.rst @@ -0,0 +1,32 @@ +.. _tutorial-index: + +MicroPython tutorial for ESP8266 +================================ + +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 diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst new file mode 100644 index 0000000000..a2c5d1838e --- /dev/null +++ b/docs/esp8266/tutorial/intro.rst @@ -0,0 +1,102 @@ +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/>`__, or install it +using pip:: + + pip install esptool + +It requires Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in +the command above. 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 esp8266-2016-05-03-v1.8.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). The filename of the firmware should also match the file +that you have. + +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 esp8266-2016-05-03-v1.8.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. diff --git a/docs/esp8266/tutorial/neopixel.rst b/docs/esp8266/tutorial/neopixel.rst new file mode 100644 index 0000000000..245aed6d46 --- /dev/null +++ b/docs/esp8266/tutorial/neopixel.rst @@ -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) diff --git a/docs/esp8266/tutorial/network_basics.rst b/docs/esp8266/tutorial/network_basics.rst new file mode 100644 index 0000000000..02a7054858 --- /dev/null +++ b/docs/esp8266/tutorial/network_basics.rst @@ -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. diff --git a/docs/esp8266/tutorial/network_tcp.rst b/docs/esp8266/tutorial/network_tcp.rst new file mode 100644 index 0000000000..0a1cca4457 --- /dev/null +++ b/docs/esp8266/tutorial/network_tcp.rst @@ -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() diff --git a/docs/esp8266/tutorial/nextsteps.rst b/docs/esp8266/tutorial/nextsteps.rst new file mode 100644 index 0000000000..318bd7ddf8 --- /dev/null +++ b/docs/esp8266/tutorial/nextsteps.rst @@ -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! diff --git a/docs/esp8266/tutorial/onewire.rst b/docs/esp8266/tutorial/onewire.rst new file mode 100644 index 0000000000..c90044b7a8 --- /dev/null +++ b/docs/esp8266/tutorial/onewire.rst @@ -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. diff --git a/docs/esp8266/tutorial/pins.rst b/docs/esp8266/tutorial/pins.rst new file mode 100644 index 0000000000..639267d2ee --- /dev/null +++ b/docs/esp8266/tutorial/pins.rst @@ -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 None for the input pull-mode. If it's +not specified then it defaults to None, which is no pull resistor. +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(trigger=Pin.IRQ_FALLING, handler=callback) + >>> p2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=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. diff --git a/docs/esp8266/tutorial/powerctrl.rst b/docs/esp8266/tutorial/powerctrl.rst new file mode 100644 index 0000000000..9e44339c86 --- /dev/null +++ b/docs/esp8266/tutorial/powerctrl.rst @@ -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') + diff --git a/docs/esp8266/tutorial/pwm.rst b/docs/esp8266/tutorial/pwm.rst new file mode 100644 index 0000000000..8de509427c --- /dev/null +++ b/docs/esp8266/tutorial/pwm.rst @@ -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) diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst new file mode 100644 index 0000000000..078f31357c --- /dev/null +++ b/docs/esp8266/tutorial/repl.rst @@ -0,0 +1,207 @@ +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 latest versions of Firefox and Chrome are supported. + +For your convinience, WebREPL client is hosted at +`<http://micropython.org/webrepl>`__ . Alternatively, you can install it +locally from the the GitHub repository +`<https://github.com/micropython/webrepl>`__ . + +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 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 follow prompts to +type in 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). Note that some modules may have troubles rebooting +automatically and need reset button press or power cycle (do this if +you don't see ESP8266 access point appearing in a minute or so). + +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. diff --git a/docs/esp8266_contents.rst b/docs/esp8266_contents.rst index 20a51c3dcc..30def3df2b 100644 --- a/docs/esp8266_contents.rst +++ b/docs/esp8266_contents.rst @@ -4,6 +4,8 @@ MicroPython documentation contents .. toctree:: esp8266/quickref.rst + esp8266/general.rst + esp8266/tutorial/index.rst library/index.rst reference/index.rst license.rst diff --git a/docs/library/esp.rst b/docs/library/esp.rst index 040d62f769..34d3c278d9 100644 --- a/docs/library/esp.rst +++ b/docs/library/esp.rst @@ -39,3 +39,9 @@ Functions .. function:: flash_id() Read the device ID of the flash memory. + +.. function:: flash_read(byte_offset, length_or_buffer) + +.. function:: flash_write(byte_offset, bytes) + +.. function:: flash_erase(sector_no) diff --git a/docs/library/index.rst b/docs/library/index.rst index 47cd2eeb8e..03e6502d95 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -1,59 +1,88 @@ MicroPython libraries ===================== -Functionality specific to the MicroPython implementation is available in -the following library. +The following standard Python libraries are built in to MicroPython. -.. toctree:: - :maxdepth: 1 +For additional libraries, please download them from the `micropython-lib repository +<https://github.com/micropython/micropython-lib>`_. - micropython.rst +Python standard libraries and micro-libraries +--------------------------------------------- -Python standard libraries -------------------------- +The following standard Python libraries have been "micro-ified" to fit in with +the philosophy of MicroPython. They provide the core functionality of that +module and are intended to be a drop-in replacement for the standard Python +library. -The following standard Python libraries are built in to MicroPython. +.. only:: not port_unix -For additional libraries, please download them from the `micropython-lib repository -<https://github.com/micropython/micropython-lib>`_. + The modules are available by their u-name, and also by their non-u-name. The + non-u-name can be overridden by a file of that name in your package path. + For example, ``import json`` will first search for a file ``json.py`` or + directory ``json`` and load that package if it is found. If nothing is found, + it will fallback to loading the built-in ``ujson`` module. .. only:: port_unix .. toctree:: :maxdepth: 1 - + cmath.rst gc.rst math.rst - os.rst - struct.rst + select.rst sys.rst - time.rst + ubinascii.rst + ucollections.rst + uhashlib.rst + uheapq.rst + uio.rst + ujson.rst + uos.rst + ure.rst + usocket.rst + ustruct.rst + utime.rst + uzlib.rst .. only:: port_pyboard .. toctree:: :maxdepth: 1 - + cmath.rst gc.rst math.rst - os.rst select.rst - struct.rst sys.rst - time.rst + ubinascii.rst + ucollections.rst + uhashlib.rst + uheapq.rst + uio.rst + ujson.rst + uos.rst + ure.rst + usocket.rst + ustruct.rst + utime.rst + uzlib.rst .. only:: port_wipy .. toctree:: :maxdepth: 1 - + gc.rst - os.rst select.rst sys.rst - time.rst + ubinascii.rst + ujson.rst + uos.rst + ure.rst + usocket.rst + ussl.rst + utime.rst .. only:: port_esp8266 @@ -62,52 +91,35 @@ For additional libraries, please download them from the `micropython-lib reposit gc.rst math.rst - struct.rst sys.rst - time.rst - -Python micro-libraries ----------------------- + ubinascii.rst + ucollections.rst + uhashlib.rst + uheapq.rst + uio.rst + ujson.rst + uos.rst + ure.rst + usocket.rst + ustruct.rst + utime.rst + uzlib.rst + + +MicroPython-specific libraries +------------------------------ -The following standard Python libraries have been "micro-ified" to fit in with -the philosophy of MicroPython. They provide the core functionality of that -module and are intended to be a drop-in replacement for the standard Python -library. - -.. only:: not port_unix - - The modules are available by their u-name, and also by their non-u-name. The - non-u-name can be overridden by a file of that name in your package path. - For example, ``import json`` will first search for a file ``json.py`` or - directory ``json`` and load that package if it is found. If nothing is found, - it will fallback to loading the built-in ``ujson`` module. - -.. only:: port_pyboard or port_unix - - .. toctree:: - :maxdepth: 1 - - ubinascii.rst - uctypes.rst - uhashlib.rst - uheapq.rst - ujson.rst - ure.rst - usocket.rst - uzlib.rst +Functionality specific to the MicroPython implementation is available in +the following libraries. -.. only:: port_esp8266 +.. toctree:: + :maxdepth: 1 - .. toctree:: - :maxdepth: 1 + machine.rst + micropython.rst + network.rst + uctypes.rst - ubinascii.rst - uctypes.rst - uhashlib.rst - uheapq.rst - ujson.rst - ure.rst - uzlib.rst .. only:: port_pyboard @@ -120,18 +132,6 @@ library. :maxdepth: 2 pyb.rst - network.rst - -.. only:: port_wipy - - .. toctree:: - :maxdepth: 1 - - ubinascii.rst - ujson.rst - ure.rst - usocket.rst - ussl.rst .. only:: port_wipy @@ -143,8 +143,6 @@ library. .. toctree:: :maxdepth: 2 - machine.rst - network.rst wipy.rst @@ -158,6 +156,4 @@ library. .. toctree:: :maxdepth: 2 - network.rst esp.rst - machine.rst diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index aa1caed209..a7e90ca39b 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -49,12 +49,15 @@ Constructors Construct an I2C object on the given bus. `bus` can only be 0. If the bus is not given, the default one will be selected (0). -Methods -------- +.. only:: port_esp8266 -.. method:: i2c.deinit() + .. class:: machine.I2C(scl, sda, \*, freq=400000) - Turn off the I2C bus. + Construct and return a new I2C object. + See the init method below for a description of the arguments. + +General Methods +--------------- .. only:: port_wipy @@ -66,48 +69,131 @@ Methods - ``baudrate`` is the SCL clock rate - ``pins`` is an optional tuple with the pins to assign to the I2C bus. - .. method:: i2c.readfrom(addr, nbytes) +.. only:: port_esp8266 + + .. method:: i2c.init(scl, sda, \*, freq=400000) + + Initialise the I2C bus with the given arguments: - Read ``nbytes`` from the slave specified by ``addr``. - Returns a ``bytes`` object with the data read. + - `scl` is a pin object for the SCL line + - `sda` is a pin object for the SDA line + - `freq` is the SCL clock rate - .. method:: i2c.readfrom_into(addr, buf) +.. method:: i2c.deinit() - Read into ``buf`` from the slave specified by ``addr``. - Returns the number of bytes read. + Turn off the I2C bus. - .. method:: i2c.writeto(addr, buf, \*, stop=True) + Availability: WiPy. - Write ``buf`` to the slave specified by ``addr``. Set ``stop`` to ``False`` - if the transfer should be continued. - Returns the number of bytes written. +.. method:: i2c.scan() - .. method:: i2c.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) + Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of + those that respond. A device responds if it pulls the SDA line low after + its address (including a read bit) is sent on the bus. - Read ``nbytes`` from the slave specified by ``addr`` starting from the memory - address specified by ``memaddr``. - Param ``addrsize`` specifies the address size in bits. - Returns a ``bytes`` object with the data read. + Note: on WiPy the I2C object must be in master mode for this method to be valid. - .. method:: i2c.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) +Primitive I2C operations +------------------------ - Read into ``buf`` from the slave specified by ``addr`` starting from the memory - address specified by ``memaddr``. - Param ``addrsize`` specifies the address size in bits. - Returns the number of bytes read. +The following methods implement the primitive I2C master bus operations and can +be combined to make any I2C transaction. They are provided if you need more +control over the bus, otherwise the standard methods (see below) can be used. - .. method:: i2c.writeto_mem(addr, memaddr, buf, \*, addrsize=8) +.. method:: i2c.start() - Write ``buf`` to the slave specified by ``addr`` starting from the - memory address specified by ``memaddr``. Param ``addrsize`` specifies the - address size in bits. - Set ``stop`` to ``False`` if the transfer should be continued. - Returns the number of bytes written. + Send a start bit on the bus (SDA transitions to low while SCL is high). -.. method:: i2c.scan() + Availability: ESP8266. + +.. method:: i2c.stop() + + Send a stop bit on the bus (SDA transitions to high while SCL is high). + + Availability: ESP8266. + +.. method:: i2c.readinto(buf) + + Reads bytes from the bus and stores them into `buf`. The number of bytes + read is the length of `buf`. An ACK will be sent on the bus after + receiving all but the last byte, and a NACK will be sent following the last + byte. + + Availability: ESP8266. + +.. method:: i2c.write(buf) + + Write all the bytes from `buf` to the bus. Checks that an ACK is received + after each byte and raises an OSError if not. + + Availability: ESP8266. + +Standard bus operations +----------------------- + +The following methods implement the standard I2C master read and write +operations that target a given slave device. - Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. - Only valid when in master mode. +.. method:: i2c.readfrom(addr, nbytes) + + Read `nbytes` from the slave specified by `addr`. + Returns a `bytes` object with the data read. + +.. method:: i2c.readfrom_into(addr, buf) + + Read into `buf` from the slave specified by `addr`. + The number of bytes read will be the length of `buf`. + + On WiPy the return value is the number of bytes read. Otherwise the + return value is `None`. + +.. method:: i2c.writeto(addr, buf, \*, stop=True) + + Write the bytes from `buf` to the slave specified by `addr`. + + The `stop` argument (only available on WiPy) tells if a stop bit should be + sent at the end of the transfer. If `False` the transfer should be + continued later on. + + On WiPy the return value is the number of bytes written. Otherwise the + return value is `None`. + +Memory operations +----------------- + +Some I2C devices act as a memory device (or set of registers) that can be read +from and written to. In this case there are two addresses associated with an +I2C transaction: the slave address and the memory address. The following +methods are convenience functions to communicate with such devices. + +.. method:: i2c.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) + + Read `nbytes` from the slave specified by `addr` starting from the memory + address specified by `memaddr`. + The argument `addrsize` specifies the address size in bits (on ESP8266 + this argument is not recognised and the address size is always 8 bits). + Returns a `bytes` object with the data read. + +.. method:: i2c.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) + + Read into `buf` from the slave specified by `addr` starting from the + memory address specified by `memaddr`. The number of bytes read is the + length of `buf`. + The argument `addrsize` specifies the address size in bits (on ESP8266 + this argument is not recognised and the address size is always 8 bits). + + On WiPy the return value is the number of bytes read. Otherwise the + return value is `None`. + +.. method:: i2c.writeto_mem(addr, memaddr, buf, \*, addrsize=8) + + Write `buf` to the slave specified by `addr` starting from the + memory address specified by `memaddr`. + The argument `addrsize` specifies the address size in bits (on ESP8266 + this argument is not recognised and the address size is always 8 bits). + + On WiPy the return value is the number of bytes written. Otherwise the + return value is `None`. Constants --------- @@ -115,3 +201,5 @@ Constants .. data:: I2C.MASTER for initialising the bus to master mode + + Availability: WiPy. diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst index 6fa2b170e8..a2e97c87c2 100644 --- a/docs/library/machine.Pin.rst +++ b/docs/library/machine.Pin.rst @@ -39,6 +39,21 @@ Usage Model: All pin objects go through the pin mapper to come up with one of the gpio pins. +.. only:: port_esp8266 + + :: + + from machine import Pin + + # create an output pin on GPIO0 + p0 = Pin(0, Pin.OUT) + p0.value(0) + p0.value(1) + + # create an input pin on GPIO2 + p2 = Pin(2, Pin.IN, Pin.PULL_UP) + print(p2.value()) + Constructors ------------ @@ -86,6 +101,25 @@ Methods Get the pin id. +.. only:: port_esp8266 + + .. method:: pin.init(mode, pull=None, \*, value) + + Initialise the pin: + + - `mode` can be one of: + + - ``Pin.IN`` - input pin. + - ``Pin.OUT`` - output pin in push-pull mode. + + - `pull` can be one of: + + - ``None`` - no pull up or down resistor. + - ``Pin.PULL_UP`` - pull up resistor enabled. + + - if `value` is given then it is the output value to set the pin + if it is in output mode. + .. method:: pin.value([value]) Get or set the digital logic level of the pin: @@ -95,17 +129,19 @@ Methods anything that converts to a boolean. If it converts to ``True``, the pin is set high, otherwise it is set low. +.. method:: pin([value]) + + Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin. + See **pin.value** for more details. + .. method:: pin.alt_list() Returns a list of the alternate functions supported by the pin. List items are a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)`` -.. only:: port_wipy - - .. method:: pin([value]) + Availability: WiPy. - Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin. - See **pin.value** for more details. +.. only:: port_wipy .. method:: pin.toggle() @@ -155,6 +191,23 @@ Methods Returns a callback object. +.. only:: port_esp8266 + + .. method:: pin.irq(\*, trigger, handler=None) + + Create a callback to be triggered when the input level at the pin changes. + + - ``trigger`` configures the pin level which can generate an interrupt. Possible values are: + + - ``Pin.IRQ_FALLING`` interrupt on falling edge. + - ``Pin.IRQ_RISING`` interrupt on rising edge. + + The values can be OR'ed together to trigger on multiple events. + + - ``handler`` is an optional function to be called when the interrupt triggers. + + Returns a callback object. + Attributes ---------- @@ -166,44 +219,36 @@ Attributes led = Pin(Pin.board.GP25, mode=Pin.OUT) Pin.board.GP2.alt_list() + Availability: WiPy. Constants --------- -.. only:: port_wipy - - .. data:: Pin.IN - - .. data:: Pin.OUT - - .. data:: Pin.OPEN_DRAIN - - .. data:: Pin.ALT - - .. data:: Pin.ALT_OPEN_DRAIN - - Selects the pin mode. - - .. data:: Pin.PULL_UP - - .. data:: Pin.PULL_DOWN - - Selectes the wether there's pull up/down resistor. - - .. data:: Pin.LOW_POWER +The following constants are used to configure the pin objects. Note that +not all constants are available on all ports. - .. data:: Pin.MED_POWER +.. data:: IN + OUT + OPEN_DRAIN + ALT + ALT_OPEN_DRAIN - .. data:: Pin.HIGH_POWER + Selects the pin mode. - Selects the drive strength. +.. data:: PULL_UP + PULL_DOWN - .. data:: Pin.IRQ_FALLING + Selects the whether there is a pull up/down resistor. - .. data:: Pin.IRQ_RISING +.. data:: LOW_POWER + MED_POWER + HIGH_POWER - .. data:: Pin.IRQ_LOW_LEVEL + Selects the pin drive strength. - .. data:: Pin.IRQ_HIGH_LEVEL +.. data:: IRQ_FALLING + IRQ_RISING + IRQ_LOW_LEVEL + IRQ_HIGH_LEVEL - Selects the IRQ trigger type. + Selects the IRQ trigger type. diff --git a/docs/library/machine.rst b/docs/library/machine.rst index dacfe737b9..14d75cb466 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -18,76 +18,90 @@ Reset related functions Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values. -Interrupt related functions ---------------------------- +.. only:: port_wipy -.. function:: disable_irq() + Interrupt related functions + --------------------------- - Disable interrupt requests. - Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs - respectively. This return value can be passed to enable_irq to restore - the IRQ to its original state. + .. function:: disable_irq() -.. function:: enable_irq(state=True) + Disable interrupt requests. + Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs + respectively. This return value can be passed to enable_irq to restore + the IRQ to its original state. - Enable interrupt requests. - If ``state`` is ``True`` (the default value) then IRQs are enabled. - If ``state`` is ``False`` then IRQs are disabled. The most common use of - this function is to pass it the value returned by ``disable_irq`` to - exit a critical section. + .. function:: enable_irq(state=True) + + Enable interrupt requests. + If ``state`` is ``True`` (the default value) then IRQs are enabled. + If ``state`` is ``False`` then IRQs are disabled. The most common use of + this function is to pass it the value returned by ``disable_irq`` to + exit a critical section. Power related functions ----------------------- .. function:: freq() - Returns a tuple of clock frequencies: ``(sysclk,)`` - These correspond to: + .. only:: not port_wipy + + Returns CPU frequency in hertz. + + .. only:: port_wipy - - sysclk: frequency of the CPU + Returns a tuple of clock frequencies: ``(sysclk,)`` + These correspond to: + + - sysclk: frequency of the CPU .. function:: idle() Gates the clock to the CPU, useful to reduce power consumption at any time during short or long periods. Peripherals continue working and execution resumes as soon - as any interrupt is triggered (including the systick which has a period of 1ms). - Current consumption is reduced to ~12mA (in WLAN STA mode) + as any interrupt is triggered (on many ports this includes system timer + interrupt occuring at regular intervals on the order of millisecond). .. function:: sleep() Stops the CPU and disables all peripherals except for WLAN. Execution is resumed from - the point where the sleep was requested. Wake sources are ``Pin``, ``RTC`` and ``WLAN``. - Current consumption is reduced to 950uA (in WLAN STA mode). + the point where the sleep was requested. For wake up to actually happen, wake sources + should be configured first. .. function:: deepsleep() - Stops the CPU and all peripherals including WLAN. Execution is resumed from main, just - as with a reset. The reset cause can be checked to know that we are coming from - from ``machine.DEEPSLEEP``. Wake sources are ``Pin`` and ``RTC``. Current consumption - is reduced to ~5uA. + Stops the CPU and all peripherals (including networking interfaces, if any). Execution + is resumed from the main script, just as with a reset. The reset cause can be checked + to know that we are coming from ``machine.DEEPSLEEP``. For wake up to actually happen, + wake sources should be configured first, like ``Pin`` change or ``RTC`` timeout. + +.. only:: port_wipy -.. function:: wake_reason() + .. function:: wake_reason() - Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values. + Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values. Miscellaneous functions ----------------------- -.. function:: main(filename) +.. only:: port_wipy + + .. function:: main(filename) - Set the filename of the main script to run after boot.py is finished. If - this function is not called then the default file main.py will be executed. + Set the filename of the main script to run after boot.py is finished. If + this function is not called then the default file main.py will be executed. - It only makes sense to call this function from within boot.py. + It only makes sense to call this function from within boot.py. -.. function:: rng() + .. function:: rng() - Return a 24-bit software generated random number. + Return a 24-bit software generated random number. .. function:: unique_id() - Returns a string of 6 bytes (48 bits), which is the unique ID of the MCU. - This also corresponds to the network ``MAC address``. + Returns a byte string with a unique idenifier of a board/SoC. It will vary + from a board/SoC instance to another, if underlying hardware allows. Length + varies by hardware (so use substring of a full value if you expect a short + ID). In some MicroPython ports, ID corresponds to the network MAC address. .. _machine_constants: diff --git a/docs/library/network.rst b/docs/library/network.rst index 49e7e53bf8..fe4eaa7525 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -283,14 +283,6 @@ For example:: Disconnect from the currently connected wireless network. - .. method:: wlan.mac([address]) - - Get or set the network interface MAC address. - - If the ``address`` parameter is provided, sets the address to its - value, which should be bytes object of length 6. If the function - is called wihout parameters, returns the current address. - .. method:: wlan.scan() Scan for the available wireless networks. @@ -300,6 +292,9 @@ For example:: (ssid, bssid, channel, RSSI, authmode, hidden) + `bssid` is hardware address of an access point, in binary form, returned as + bytes object. You can use ``ubinascii.hexlify()`` to convert it to ASCII form. + There are five values for authmode: * 0 -- open @@ -332,6 +327,46 @@ For example:: point and has a valid IP address. In AP mode returns ``True`` when a station is connected. Returns ``False`` otherwise. + .. method:: wlan.ifconfig([(ip, subnet, gateway, dns)]) + + Get/set IP-level network interface paremeters: IP address, subnet mask, + gateway and DNS server. When called with no arguments, this method returns + a 4-tuple with the above information. To set the above values, pass a + 4-tuple with the required information. For example:: + + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + + .. method:: wlan.config('param') + .. method:: wlan.config(param=value, ...) + + Get or set general network interface parameters. These methods allow to work + with additional parameters beyond standard IP configuration (as dealt with by + ``wlan.ifconfig()``). These include network-specific and hardware-specific + parameters. For setting parameters, keyword argument syntax should be used, + multiple parameters can be set at once. For querying, paremeters name should + be quoted as a string, and only one paramter can be queries at time:: + + # Set WiFi access point name (formally known as ESSID) and WiFi channel + ap.config(essid='My AP', channel=11) + # Queey params one by one + print(ap.config('essid')) + print(ap.config('channel')) + + Following are commonly supported parameters (availability of a specific parameter + depends on network technology type, driver, and MicroPython port). + + ========= =========== + Parameter Description + ========= =========== + mac MAC address (bytes) + essid WiFi access point name (string) + channel WiFi channel (integer) + hidden Whether ESSID is hidden (boolean) + authmode Authentication mode supported (enumeration, see module constants) + password Access password (string) + ========= =========== + + .. only:: port_wipy diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index 5fc5b22a5a..536b6f467d 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -40,7 +40,8 @@ using the standard stream methods:: To check if there is anything to be read, use:: - uart.any() # returns True if any characters waiting + uart.any() # returns the number of characters waiting + *Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. Earlier versions use ``uart.send`` and ``uart.recv``. @@ -57,7 +58,7 @@ Constructors initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. See ``init`` for parameters of initialisation. - + The physical pins of the UART busses are: - ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)`` @@ -66,12 +67,16 @@ Constructors - ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)`` - ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)`` + The Pyboard Lite supports UART(1), UART(2) and UART(6) only. Pins are as above except: + + - ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)`` + Methods ------- .. only:: port_pyboard - .. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=None, timeout_char=0, read_buf_len=64) + .. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=0, timeout_char=0, read_buf_len=64) Initialise the UART bus with the given parameters: @@ -79,7 +84,7 @@ Methods - ``bits`` is the number of bits per character, 7, 8 or 9. - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). - ``stop`` is the number of stop bits, 1 or 2. - - ``flow`` sets the flow control type. Can be None, ``UART.RTS``, ``UART.CTS`` + - ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS`` or ``UART.RTS | UART.CTS``. - ``timeout`` is the timeout in milliseconds to wait for the first character. - ``timeout_char`` is the timeout in milliseconds to wait between characters. @@ -103,16 +108,18 @@ Methods .. method:: uart.any() - Returns the number of characters waiting (may be 0). + Returns the number of bytes waiting (may be 0). .. method:: uart.writechar(char) Write a single character on the bus. ``char`` is an integer to write. - Return value: ``None``. + Return value: ``None``. See note below if CTS flow control is used. .. method:: uart.read([nbytes]) Read characters. If ``nbytes`` is specified then read at most that many bytes. + If ``nbytes`` are available in the buffer, returns immediately, otherwise returns + when sufficient characters arrive or the timeout elapses. .. only:: port_pyboard @@ -124,9 +131,9 @@ Methods .. method:: uart.readall() - Read as much data as possible. + Read as much data as possible. Returns after the timeout has elapsed. - Return value: a bytes object or ``None`` on timeout. + Return value: a bytes object or ``None`` if timeout prevents any data being read. .. method:: uart.readchar() @@ -144,9 +151,11 @@ Methods .. method:: uart.readline() - Read a line, ending in a newline character. + Read a line, ending in a newline character. If such a line exists, return is + immediate. If the timeout elapses, all available data is returned regardless + of whether a newline exists. - Return value: the line read or ``None`` on timeout. + Return value: the line read or ``None`` on timeout if no data is available. .. method:: uart.write(buf) @@ -157,7 +166,8 @@ Methods bytes are used for each character (little endian), and ``buf`` must contain an even number of bytes. - Return value: number of bytes written or ``None`` on timeout. + Return value: number of bytes written. If a timeout occurs and no bytes + were written returns ``None``. .. method:: uart.sendbreak() @@ -173,4 +183,63 @@ Constants .. data:: UART.RTS .. data:: UART.CTS - to select the flow control type + to select the flow control type. + +Flow Control +------------ + +.. only:: port_pyboard + + On Pyboards V1 and V1.1 ``UART(2)`` and ``UART(3)`` support RTS/CTS hardware flow control + using the following pins: + + - ``UART(2)`` is on: ``(TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)`` + - ``UART(3)`` is on :``(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)`` + + On the Pyboard Lite only ``UART(2)`` supports flow control on these pins: + + ``(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)`` + + In the following paragraphs the term "target" refers to the device connected to + the UART. + + When the UART's ``init()`` method is called with ``flow`` set to one or both of + ``UART.RTS`` and ``UART.CTS`` the relevant flow control pins are configured. + ``nRTS`` is an active low output, ``nCTS`` is an active low input with pullup + enabled. To achieve flow control the Pyboard's ``nCTS`` signal should be connected + to the target's ``nRTS`` and the Pyboard's ``nRTS`` to the target's ``nCTS``. + + CTS: target controls Pyboard transmitter + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + If CTS flow control is enabled the write behaviour is as follows: + + If the Pyboard's ``uart.write(buf)`` method is called, transmission will stall for + any periods when ``nCTS`` is ``False``. This will result in a timeout if the entire + buffer was not transmitted in the timeout period. The method returns the number of + bytes written, enabling the user to write the remainder of the data if required. In + the event of a timeout, a character will remain in the UART pending ``nCTS``. The + number of bytes composing this character will be included in the return value. + + If ``uart.writechar()`` is called when ``nCTS`` is ``False`` the method will time + out unless the target asserts ``nCTS`` in time. If it times out ``OSError 116`` + will be raised. The character will be transmitted as soon as the target asserts ``nCTS``. + + RTS: Pyboard controls target's transmitter + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + If RTS flow control is enabled, behaviour is as follows: + + If buffered input is used (``read_buf_len`` > 0), incoming characters are buffered. + If the buffer becomes full, the next character to arrive will cause ``nRTS`` to go + ``False``: the target should cease transmission. ``nRTS`` will go ``True`` when + characters are read from the buffer. + + Note that the ``any()`` method returns the number of bytes in the buffer. Assume a + buffer length of ``N`` bytes. If the buffer becomes full, and another character arrives, + ``nRTS`` will be set False, and ``any()`` will return the count ``N``. When + characters are read the additional character will be placed in the buffer and will + be included in the result of a subsequent ``any()`` call. + + If buffered input is not used (``read_buf_len`` == 0) the arrival of a character will + cause ``nRTS`` to go ``False`` until the character is read. diff --git a/docs/library/struct.rst b/docs/library/struct.rst deleted file mode 100644 index 71ee5c9b70..0000000000 --- a/docs/library/struct.rst +++ /dev/null @@ -1,25 +0,0 @@ -:mod:`struct` -- pack and unpack primitive data types -===================================================== - -.. module:: struct - :synopsis: pack and unpack primitive data types - -See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more -information. - -Functions ---------- - -.. function:: calcsize(fmt) - - Return the number of bytes needed to store the given ``fmt``. - -.. function:: pack(fmt, v1, v2, ...) - - Pack the values ``v1``, ``v2``, ... according to the format string ``fmt``. - The return value is a bytes object encoding the values. - -.. function:: unpack(fmt, data) - - Unpack from the ``data`` according to the format string ``fmt``. - The return value is a tuple of the unpacked values. diff --git a/docs/library/sys.rst b/docs/library/sys.rst index b3e52c40c4..b5a9138c07 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -7,14 +7,15 @@ Functions --------- -.. function:: exit([retval]) +.. function:: exit(retval=0) - Raise a ``SystemExit`` exception. If an argument is given, it is the - value given to ``SystemExit``. + Terminate current program with a given exit code. Underlyingly, this + function raise as ``SystemExit`` exception. If an argument is given, its + value given as an argument to ``SystemExit``. -.. function:: print_exception(exc, [file]) +.. function:: print_exception(exc, file=sys.stdout) - Print exception with a traceback to a file-like object ``file`` (or + Print exception with a traceback to a file-like object `file` (or ``sys.stdout`` by default). .. admonition:: Difference to CPython @@ -27,38 +28,89 @@ Constants .. data:: argv - a mutable list of arguments this program started with + A mutable list of arguments the current program was started with. .. data:: byteorder - the byte order of the system ("little" or "big") + The byte order of the system ("little" or "big"). + +.. data:: implementation + + Object with information about the current Python implementation. For + MicroPython, it has following attributes: + + * `name` - string "micropython" + * `version` - tuple (major, minor, micro), e.g. (1, 7, 0) + + This object is the recommended way to distinguish MicroPython from other + Python implementations (note that it still may not exist in the very + minimal ports). + + .. admonition:: Difference to CPython + :class: attention + + CPython mandates more attributes for this object, but the actual useful + bare minimum is implemented in MicroPython. + +.. data:: maxsize + + Maximum value which a native integer type can hold on the current platform, + or maximum value representable by MicroPython integer type, if it's smaller + than platform max value (that is the case for MicroPython ports without + long int support). + + This attribute is useful for detecting "bitness" of a platform (32-bit vs + 64-bit, etc.). It's recommended to not compare this attribute to some + value directly, but instead count number of bits in it:: + + bits = 0 + v = sys.maxsize + while v: + bits += 1 + v >>= 1 + if bits > 32: + # 64-bit (or more) platform + ... + else: + # 32-bit (or less) platform + # Note that on 32-bit platform, value of bits may be less than 32 + # (e.g. 31) due to peculiarities described above, so use "> 16", + # "> 32", "> 64" style of comparisons. + +.. data:: modules + + Dictionary of loaded modules. On some ports, it may not include builtin + modules. .. data:: path - a mutable list of directories to search for imported modules + A mutable list of directories to search for imported modules. .. data:: platform - The platform that MicroPython is running on. This is "pyboard" on the - pyboard and provides a robust way of determining if a script is running - on the pyboard or not. + The platform that MicroPython is running on. For OS/RTOS ports, this is + usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it + is an identifier of a board, e.g. "pyboard" for the original MicroPython + reference board. It thus can be used to distinguish one board from another. + If you need to check whether your program runs on MicroPython (vs other + Python implementation), use ``sys.implementation`` instead. .. data:: stderr - standard error (connected to USB VCP, and optional UART object) + Standard error stream. .. data:: stdin - standard input (connected to USB VCP, and optional UART object) + Standard input stream. .. data:: stdout - standard output (connected to USB VCP, and optional UART object) + Standard output stream. .. data:: version - Python language version that this implementation conforms to, as a string + Python language version that this implementation conforms to, as a string. .. data:: version_info - Python language version that this implementation conforms to, as a tuple of ints + Python language version that this implementation conforms to, as a tuple of ints. diff --git a/docs/library/time.rst b/docs/library/time.rst deleted file mode 100644 index 9a35f4f66a..0000000000 --- a/docs/library/time.rst +++ /dev/null @@ -1,89 +0,0 @@ -:mod:`time` -- time related functions -===================================== - -.. module:: time - :synopsis: time related functions - -The ``time`` module provides functions for getting the current time and date, -and for sleeping. - -Functions ---------- - -.. function:: localtime([secs]) - - Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which - contains: (year, month, mday, hour, minute, second, weekday, yearday) - If secs is not provided or None, then the current time from the RTC is used. - year includes the century (for example 2014). - - * month is 1-12 - * mday is 1-31 - * hour is 0-23 - * minute is 0-59 - * second is 0-59 - * weekday is 0-6 for Mon-Sun - * yearday is 1-366 - -.. function:: mktime() - - This is inverse function of localtime. It's argument is a full 8-tuple - which expresses a time as per localtime. It returns an integer which is - the number of seconds since Jan 1, 2000. - -.. only:: port_pyboard - - .. function:: sleep(seconds) - - Sleep for the given number of seconds. Seconds can be a floating-point number to - sleep for a fractional number of seconds. - -.. only:: port_esp8266 or port_wipy - - .. function:: sleep(seconds) - - Sleep for the given number of seconds. - -.. only:: port_wipy or port_pyboard - - .. function:: sleep_ms(ms) - - Delay for given number of milliseconds, should be positive or 0. - - .. function:: sleep_us(us) - - Delay for given number of microseconds, should be positive or 0 - - .. function:: ticks_ms() - - Returns an increasing millisecond counter with arbitrary reference point, - that wraps after some (unspecified) value. The value should be treated as - opaque, suitable for use only with ticks_diff(). - - .. function:: ticks_us() - - Just like ``ticks_ms`` above, but in microseconds. - - .. function:: ticks_cpu() - - Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks). - - .. function:: ticks_diff(old, new) - - Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu(). - The value returned by these functions may wrap around at any time, so directly - subtracting them is not supported. ticks_diff() should be used instead. "old" value should - actually precede "new" value in time, or result is undefined. This function should not be - used to measure arbitrarily long periods of time (because ticks_*() functions wrap around - and usually would have short period). The expected usage pattern is implementing event - polling with timeout:: - - # Wait for GPIO pin to be asserted, but at most 500us - start = time.ticks_us() - while pin.value() == 0: - if time.ticks_diff(start, time.ticks_us()) > 500: - raise TimeoutError - -.. function:: time() - - Returns the number of seconds, as an integer, since 1/1/2000. diff --git a/docs/library/ubinascii.rst b/docs/library/ubinascii.rst index e7967c5113..0a9adb50d4 100644 --- a/docs/library/ubinascii.rst +++ b/docs/library/ubinascii.rst @@ -12,7 +12,7 @@ Functions .. function:: hexlify(data, [sep]) - Convert binary data to hexadecimal representation. Return bytes string. + Convert binary data to hexadecimal representation. Returns bytes string. .. admonition:: Difference to CPython :class: attention @@ -22,13 +22,13 @@ Functions .. function:: unhexlify(data) - Convert hexadecimal data to binary representation. Return bytes string. + Convert hexadecimal data to binary representation. Returns bytes string. (i.e. inverse of hexlify) .. function:: a2b_base64(data) - Convert Base64-encoded data to binary representation. Return bytes string. + Convert Base64-encoded data to binary representation. Returns bytes string. .. function:: b2a_base64(data) - Encode binary data in Base64 format. Return string. + Encode binary data in Base64 format. Returns string. diff --git a/docs/library/ucollections.rst b/docs/library/ucollections.rst new file mode 100644 index 0000000000..c7ed068c7e --- /dev/null +++ b/docs/library/ucollections.rst @@ -0,0 +1,53 @@ +:mod:`ucollections` -- collection and container types +===================================================== + +.. module:: ucollections + :synopsis: collection and container types + +This module implements advanced collection and container types to +hold/accumulate various objects. + +Classes +------- + +.. function:: namedtuple(name, fields) + + This is factory function to create a new namedtuple type with a specific + name and set of fields. A namedtyple is a subclass of tuple which allows + to access its fields not just by numeric index, but also with an attribute + access syntax using symbolic field names. Fields is a sequence of strings + specifying field names. For compatibily with CPython it can also be a + a string with space-separated field named (but this is less efficient). + Example of use:: + + from ucollections import namedtuple + + MyTuple = namedtuple("MyTuple", ("id", "name")) + t1 = MyTuple(1, "foo") + t2 = MyTuple(2, "bar") + print(t1.name) + assert t2.name == t2[1] + +.. function:: OrderedDict(...) + + ``dict`` type subclass which remembers and preserves the order of keys + added. When ordered dict is iterated over, keys/items are returned in + the order they were added:: + + from ucollections import OrderedDict + + # To make benefit of ordered keys, OrderedDict should be initialized + # from sequence of (key, value) pairs. + d = OrderedDict([("z", 1), ("a", 2)]) + # More items can be added as usual + d["w"] = 5 + d["b"] = 3 + for k, v in d.items(): + print(k, v) + + Output:: + + z 1 + a 2 + w 5 + b 3 diff --git a/docs/library/uio.rst b/docs/library/uio.rst new file mode 100644 index 0000000000..1b3e2a0822 --- /dev/null +++ b/docs/library/uio.rst @@ -0,0 +1,46 @@ +:mod:`uio` -- input/output streams +================================== + +.. module:: uio + :synopsis: input/output streams + +This module contains additional types of stream (file-like) objects +and helper functions. + +Functions +--------- + +.. function:: open(name, mode='r', **kwargs) + + Open a file. Builtin ``open()`` function is alised to this function. + All ports (which provide access to file system) are required to support + `mode` parameter, but support for other arguments vary by port. + +Classes +------- + +.. class:: FileIO(...) + + This is type of a file open in binary mode, e.g. using ``open(name, "rb")``. + You should not instantiate this class directly. + +.. class:: TextIOWrapper(...) + + This is type of a file open in text mode, e.g. using ``open(name, "rt")``. + You should not instantiate this class directly. + +.. class:: StringIO([string]) +.. class:: BytesIO([string]) + + In-memory file-like objects for input/output. `StringIO` is used for + text-mode I/O (similar to a normal file opened with "t" modifier). + `BytesIO` is used for binary-mode I/O (similar to a normal file + opened with "b" modifier). Initial contents of file-like objects + can be specified with `string` parameter (should be normal string + for `StringIO` or bytes object for `BytesIO`). All the usual file + methods like ``read()``, ``write()``, ``close()`` are available on + these objects, and additionally, following method: + + .. method:: getvalue() + + Get the current contents of the underlying buffer which holds data. diff --git a/docs/library/os.rst b/docs/library/uos.rst index e6777147ac..bb95107c04 100644 --- a/docs/library/os.rst +++ b/docs/library/uos.rst @@ -1,7 +1,7 @@ -:mod:`os` -- basic "operating system" services -============================================== +:mod:`uos` -- basic "operating system" services +=============================================== -.. module:: os +.. module:: uos :synopsis: basic "operating system" services The ``os`` module contains functions for filesystem access and ``urandom`` diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index a83a87d2e0..d31e4d2fc9 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -7,6 +7,18 @@ This module provides access to the BSD socket interface. +See corresponding `CPython module <https://docs.python.org/3/library/socket.html>`_ for +comparison. + +Socket address format(s) +------------------------ + +Functions below which expect a network address, accept it in the format of +`(ipv4_address, port)`, where `ipv4_address` is a string with dot-notation numeric +IPv4 address, e.g. ``"8.8.8.8"``, and port is integer port number in the range +1-65535. Note the domain names are not accepted as `ipv4_address`, they should be +resolved first using ``socket.getaddrinfo()``. + Functions --------- @@ -37,13 +49,15 @@ Functions The following example shows how to connect to a given url:: s = socket.socket() - s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][4]) + s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1]) + +.. only:: port_wipy -Exceptions ----------- + Exceptions + ---------- -.. data:: socket.error -.. data:: socket.timeout + .. data:: socket.error + .. data:: socket.timeout Constants --------- @@ -59,9 +73,10 @@ Constants .. data:: socket.IPPROTO_UDP .. data:: socket.IPPROTO_TCP -.. data:: socket.IPPROTO_SEC +.. only:: port_wipy + .. data:: socket.IPPROTO_SEC - protocol numbers + protocol numbers class socket ============ @@ -79,8 +94,7 @@ Methods .. method:: socket.bind(address) - Bind the socket to address. The socket must not already be bound. The format of ``address`` - is: ``(ipv4 address, port)`` + Bind the socket to address. The socket must not already be bound. .. method:: socket.listen([backlog]) @@ -98,7 +112,7 @@ Methods .. method:: socket.connect(address) - Connect to a remote socket at address. The format of address is: ``(ipv4 address, port)`` + Connect to a remote socket at address. .. method:: socket.send(bytes) @@ -116,8 +130,7 @@ Methods .. method:: socket.sendto(bytes, address) Send data to the socket. The socket should not be connected to a remote socket, since the - destination socket is specified by address. The ``address`` has the same format as the - rest of the methods, see above. + destination socket is specified by `address`. .. method:: socket.recvfrom(bufsize) @@ -158,9 +171,10 @@ Methods The socket must be in blocking mode; it can have a timeout, but the file object’s internal buffer may end up in a inconsistent state if a timeout occurs. - .. note:: + .. admonition:: Difference to CPython + :class: attention - **CPython difference:** closing the file object returned by makefile() WILL close the + Closing the file object returned by makefile() WILL close the original socket as well. .. method:: socket.read(size) diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst index 60be894107..b66e23b2c8 100644 --- a/docs/library/ussl.rst +++ b/docs/library/ussl.rst @@ -21,7 +21,7 @@ Functions import ssl s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) ss = ssl.wrap_socket(s) - ss.connect(socket.getaddrinfo('www.google.com', 443)[0][4]) + ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1]) Certificates must be used in order to validate the other side of the connection, and also to authenticate ourselves with the other end. Such certificates must be stored as files using the @@ -44,7 +44,7 @@ Functions import ssl s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem') - ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][4]) + ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1]) SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module. diff --git a/docs/library/ustruct.rst b/docs/library/ustruct.rst new file mode 100644 index 0000000000..ae5b1be003 --- /dev/null +++ b/docs/library/ustruct.rst @@ -0,0 +1,37 @@ +:mod:`ustruct` -- pack and unpack primitive data types +====================================================== + +.. module:: ustruct + :synopsis: pack and unpack primitive data types + +See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more +information. + +Functions +--------- + +.. function:: calcsize(fmt) + + Return the number of bytes needed to store the given `fmt`. + +.. function:: pack(fmt, v1, v2, ...) + + Pack the values `v1`, `v2`, ... according to the format string `fmt`. + The return value is a bytes object encoding the values. + +.. function:: pack_into(fmt, buffer, offset, v1, v2, ...) + + Pack the values `v1`, `v2`, ... according to the format string `fmt` + into a `buffer` starting at `offset`. `offset` may be negative to count + from the end of `buffer`. + +.. function:: unpack(fmt, data) + + Unpack from the `data` according to the format string `fmt`. + The return value is a tuple of the unpacked values. + +.. function:: unpack_from(fmt, data, offset=0) + + Unpack from the `data` starting at `offset` according to the format string + `fmt`. `offset` may be negative to count from the end of `buffer`. The return + value is a tuple of the unpacked values. diff --git a/docs/library/utime.rst b/docs/library/utime.rst new file mode 100644 index 0000000000..0bca4692ac --- /dev/null +++ b/docs/library/utime.rst @@ -0,0 +1,139 @@ +:mod:`utime` -- time related functions +====================================== + +.. module:: utime + :synopsis: time related functions + +The ``utime`` module provides functions for getting the current time and date, +measuring time intervals, and for delays. + +**Time Epoch**: Unix port uses standard for POSIX systems epoch of +1970-01-01 00:00:00 UTC. However, embedded ports use epoch of +2000-01-01 00:00:00 UTC. + +**Maintaining actual calendar date/time**: This requires a +Real Time Clock (RTC). On systems with underlying OS (including some +RTOS), an RTC may be implicit. Setting and maintaining actual calendar +time is responsibility of OS/RTOS and is done outside of MicroPython, +it just uses OS API to query date/time. On baremetal ports however +system time depends on ``machine.RTC()`` object. The current calendar time +may be set using ``machine.RTC().datetime(tuple)`` function, and maintained +by following means: + +* By a backup battery (which may be an additional, optional component for + a particular board). +* Using networked time protocol (requires setup by a port/user). +* Set manually by a user on each power-up (many boards then maintain + RTC time across hard resets, though some may require setting it again + in such case). + +If actual calendar time is not maintained with a system/MicroPython RTC, +functions below which require reference to current absolute time may +behave not as expected. + +Functions +--------- + +.. function:: localtime([secs]) + + Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which + contains: (year, month, mday, hour, minute, second, weekday, yearday) + If secs is not provided or None, then the current time from the RTC is used. + + * year includes the century (for example 2014). + * month is 1-12 + * mday is 1-31 + * hour is 0-23 + * minute is 0-59 + * second is 0-59 + * weekday is 0-6 for Mon-Sun + * yearday is 1-366 + +.. function:: mktime() + + This is inverse function of localtime. It's argument is a full 8-tuple + which expresses a time as per localtime. It returns an integer which is + the number of seconds since Jan 1, 2000. + +.. only:: port_unix or port_pyboard or port_esp8266 + + .. function:: sleep(seconds) + + Sleep for the given number of seconds. Seconds can be a floating-point number to + sleep for a fractional number of seconds. Note that other MicroPython ports may + not accept floating-point argument, for compatibility with them use ``sleep_ms()`` + and ``sleep_us()`` functions. + +.. only:: port_wipy + + .. function:: sleep(seconds) + + Sleep for the given number of seconds. + +.. only:: port_unix or port_pyboard or port_wipy or port_esp8266 + + .. function:: sleep_ms(ms) + + Delay for given number of milliseconds, should be positive or 0. + + .. function:: sleep_us(us) + + Delay for given number of microseconds, should be positive or 0 + + .. function:: ticks_ms() + + Returns an increasing millisecond counter with arbitrary reference point, + that wraps after some (unspecified) value. The value should be treated as + opaque, suitable for use only with ticks_diff(). + + .. function:: ticks_us() + + Just like ``ticks_ms`` above, but in microseconds. + +.. only:: port_wipy or port_pyboard + + .. function:: ticks_cpu() + + Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks). + +.. only:: port_unix or port_pyboard or port_wipy or port_esp8266 + + .. function:: ticks_diff(old, new) + + Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu(). + The value returned by these functions may wrap around at any time, so directly + subtracting them is not supported. ticks_diff() should be used instead. "old" value should + actually precede "new" value in time, or result is undefined. This function should not be + used to measure arbitrarily long periods of time (because ticks_*() functions wrap around + and usually would have short period). The expected usage pattern is implementing event + polling with timeout:: + + # Wait for GPIO pin to be asserted, but at most 500us + start = time.ticks_us() + while pin.value() == 0: + if time.ticks_diff(start, time.ticks_us()) > 500: + raise TimeoutError + +.. function:: time() + + Returns the number of seconds, as an integer, since the Epoch, assuming that underlying + RTC is set and maintained as decsribed above. If an RTC is not set, this function returns + number of seconds since a port-specific reference point in time (for embedded boards without + a battery-backed RTC, usually since power up or reset). If you want to develop portable + MicroPython application, you should not rely on this function to provide higher than second + precision. If you need higher precision, use ``ticks_ms()`` and ``ticks_us()`` functions, + if you need calendar time, ``localtime()`` without an argument is a better choice. + + .. admonition:: Difference to CPython + :class: attention + + In CPython, this function returns number of + seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, + usually having microsecond precision. With MicroPython, only Unix port + uses the same Epoch, and if floating-point precision allows, + returns sub-second precision. Embedded hardware usually doesn't have + floating-point precision to represent both long time ranges and subsecond + precision, so they use integer value with second precision. Some embedded + hardware also lacks battery-powered RTC, so returns number of seconds + since last power-up or from other relative, hardware-specific point + (e.g. reset). diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index 4792a6fa97..2f1d16cea1 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -59,20 +59,21 @@ An example of the above is the common case where a buffer is required, such as o used for communication with a device. A typical driver will create the buffer in the constructor and use it in its I/O methods which will be called repeatedly. -The MicroPython libraries typically provide optional support for pre-allocated buffers. -For example the ``uart.readinto()`` method allows two options for its argument, an integer -or a buffer. If an integer is supplied it will read up to that number of bytes and -return the outcome: this implies that a buffer is created with a corresponding -memory allocation. Providing a pre-allocated buffer as the argument avoids this. See -the code fragment in :ref:`Caching object references <Caching>` below. +The MicroPython libraries typically provide support for pre-allocated buffers. For +example, objects which support stream interface (e.g., file or UART) provide ``read()`` +method which allocate new buffer for read data, but also a ``readinto()`` method +to read data into an existing buffer. Floating Point ~~~~~~~~~~~~~~ -For the most speed critical sections of code it is worth noting that performing -any kind of floating point operation involves heap allocation. Where possible use -integer operations and restrict the use of floating point to sections of the code -where performance is not paramount. +Some MicroPython ports allocate floating point numbers on heap. Some other ports +may lack dedicated floating-point coprocessor, and perform arithmetic operations +on them in "software" at considerably lower speed than on integers. Where +performance is important, use integer operations and restrict the use of floating +point to sections of the code where performance is not paramount. For example, +capture ADC readings as integers values to an array in one quick go, and only then +convert them to floating-point numbers for signal processing. Arrays ~~~~~~ @@ -84,18 +85,31 @@ elements in contiguous memory locations. Once again to avoid memory allocation i code these should be pre-allocated and passed as arguments or as bound objects. When passing slices of objects such as ``bytearray`` instances, Python creates -a copy which involves allocation. This can be avoided using a ``memoryview`` -object: +a copy which involves allocation of the size proportional to the size of slice. +This can be alleviated using a ``memoryview`` object. ``memoryview`` itself +is allocated on heap, but is a small, fixed-size object, regardless of the size +of slice it points too. .. code:: python - ba = bytearray(100) - func(ba[3:10]) # a copy is passed - mv = memoryview(ba) - func(mv[3:10]) # a pointer to memory is passed + ba = bytearray(10000) # big array + func(ba[30:2000]) # a copy is passed, ~2K new allocation + mv = memoryview(ba) # small object is allocated + func(mv[30:2000]) # a pointer to memory is passed A ``memoryview`` can only be applied to objects supporting the buffer protocol - this -includes arrays but not lists. +includes arrays but not lists. Small caveat is that while memoryview object is live, +it also keeps alive the original buffer object. So, a memoryview isn't a universal +panacea. For instance, in the example above, if you are done with 10K buffer and +just need those bytes 30:2000 from it, it may be better to make a slice, and let +the 10K buffer go (be ready for garbage collection), instead of making a +long-living memoryview and keeping 10K blocked for GC. + +Nonetheless, ``memoryview`` is indispensable for advanced preallocated buffer +management. ``.readinto()`` method discussed above puts data at the beginning +of buffer and fills in entire buffer. What if you need to put data in the +middle of existing buffer? Just create a memoryview into the needed section +of buffer and pass it to ``.readinto()``. Identifying the slowest section of code --------------------------------------- diff --git a/docs/templates/versions.html b/docs/templates/versions.html index 977aefab11..6323024ecb 100644 --- a/docs/templates/versions.html +++ b/docs/templates/versions.html @@ -1,7 +1,7 @@ <div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions"> <span class="rst-current-version" data-toggle="rst-current-version"> <span class="fa fa-book"> Ports and Versions</span> - {{ port_short_name }} ({{ port_version }}) + {{ port }} ({{ port_version }}) <span class="fa fa-caret-down"></span> </span> <div class="rst-other-versions"> diff --git a/docs/topindex.html b/docs/topindex.html index be13cc2a8a..75039233ee 100644 --- a/docs/topindex.html +++ b/docs/topindex.html @@ -25,7 +25,7 @@ <table class="contentstable"><tr> <td width="40%" style="padding-left:2em;"> - {% if port == "pyboard" or port == "wipy" %} + {% if port in ("pyboard", "wipy", "esp8266") %} <p class="biglink"> <a class="biglink" href="{{ pathto(port + "/quickref") }}">Quick reference for {{ port_name }}</a><br/> <span class="linkdescr">pinout for {{ port_name }} and snippets of useful code</span> diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst index bcbbe53d7d..c1e9696601 100644 --- a/docs/wipy/general.rst +++ b/docs/wipy/general.rst @@ -170,3 +170,12 @@ There are currently 2 kinds of errors that you might see: 2. If the heartbeat LED stays on, then there was a hard fault, you cannot recover from this, the only way out is to press the reset switch. +Details on sleep modes +---------------------- + +* ``machine.idle()``: Power consumption: ~12mA (in WLAN STA mode). Wake sources: + any hardware interrupt (including systick with period of 1ms), no special + configuration required. +* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC`` + and ``WLAN`` +* ``machine.deepsleep()``: ~5uA. Wake sources are ``Pin`` and ``RTC``. |