diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 7b63f7549d46..6f84de6f60ea 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,6 @@ +# all: Fix spelling mistakes based on codespell check. +b1229efbd1509654dec6053865ab828d769e29db + # top: Update Python formatting to black "2023 stable style". 8b2748269244304854b3462cb8902952b4dcb892 diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md index 2bbfede6ce06..cfe4a4befdb1 100644 --- a/.github/ISSUE_TEMPLATE/security.md +++ b/.github/ISSUE_TEMPLATE/security.md @@ -1,6 +1,6 @@ --- name: Security report -about: Report a security issue or vunerability in MicroPython +about: Report a security issue or vulnerability in MicroPython title: '' labels: security assignees: '' diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index 542edd46cfa2..81a2715f1b33 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: true jobs: - build: + code-formatting: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 @@ -18,3 +18,13 @@ jobs: run: source tools/ci.sh && ci_code_formatting_run - name: Check code formatting run: git diff --exit-code + + code-spelling: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - name: Install packages + run: source tools/ci.sh && ci_code_spell_setup + - name: Run spell checker + run: source tools/ci.sh && ci_code_spell_run diff --git a/.github/workflows/mpremote.yml b/.github/workflows/mpremote.yml index 3cfb9d47d39f..14aef03e0773 100644 --- a/.github/workflows/mpremote.yml +++ b/.github/workflows/mpremote.yml @@ -13,11 +13,9 @@ jobs: steps: - uses: actions/checkout@v3 with: - # Version is determined from git, - # should be deep enough to get to latest tag - fetch-depth: '1000' - - run: | - git fetch --prune --unshallow --tags + # Setting this to zero means fetch all history and tags, + # which hatch-vcs can use to discover the version tag. + fetch-depth: 0 - uses: actions/setup-python@v4 - name: Install build tools run: pip install build diff --git a/.github/workflows/ports_esp32.yml b/.github/workflows/ports_esp32.yml index 6fc009d4fee8..2cc9f592bf23 100644 --- a/.github/workflows/ports_esp32.yml +++ b/.github/workflows/ports_esp32.yml @@ -18,20 +18,11 @@ concurrency: cancel-in-progress: true jobs: - build_idf402: + build_idf50: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - name: Install packages - run: source tools/ci.sh && ci_esp32_idf402_setup - - name: Build - run: source tools/ci.sh && ci_esp32_build - - build_idf44: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v3 - - name: Install packages - run: source tools/ci.sh && ci_esp32_idf44_setup + run: source tools/ci.sh && ci_esp32_idf50_setup - name: Build run: source tools/ci.sh && ci_esp32_build diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index fe25deb4ad51..87c58055b988 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -85,7 +85,7 @@ jobs: run: tests/run-tests.py --print-failures coverage_32bit: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386 steps: - uses: actions/checkout@v3 - name: Install packages @@ -103,7 +103,7 @@ jobs: run: tests/run-tests.py --print-failures nanbox: - runs-on: ubuntu-20.04 # use 20.04 to get python2 + runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386 steps: - uses: actions/checkout@v3 - name: Install packages diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 000000000000..b8e43dc78f17 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,10 @@ +# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python +name: Python code lint with ruff +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: pip install --user ruff + - run: ruff --format=github . diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 12f3d79c9353..e9815a4b2e64 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,7 @@ repos: language: python verbose: true stages: [commit-msg] + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.265 + hooks: + - id: ruff diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index 3b678bfeb800..d44b382b25ea 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -11,7 +11,7 @@ It's also ok to drop file extensions. Besides prefix, first line of a commit message should describe a change clearly and to the point, and be a grammatical sentence with -final full stop. First line should fit within 72 characters. Examples +final full stop. First line must fit within 72 characters. Examples of good first line of commit messages: py/objstr: Add splitlines() method. @@ -27,12 +27,9 @@ change beyond 5 lines would likely require such detailed description. To get good practical examples of good commits and their messages, browse the `git log` of the project. -When committing you are encouraged to sign-off your commit by adding -"Signed-off-by" lines and similar, eg using "git commit -s". If you don't -explicitly sign-off in this way then the commit message, which includes your -name and email address in the "Author" line, implies your sign-off. In either -case, of explicit or implicit sign-off, you are certifying and signing off -against the following: +When committing you must sign-off your commit by adding "Signed-off-by:" +line(s) at the end of the commit message, e.g. using `git commit -s`. You +are then certifying and signing off against the following: * That you wrote the change yourself, or took it from a project with a compatible license (in the latter case the commit message, and possibly @@ -49,10 +46,9 @@ against the following: * Your contribution including commit message will be publicly and indefinitely available for anyone to access, including redistribution under the terms of the project's license. -* Your signature for all of the above, which is the "Signed-off-by" line - or the "Author" line in the commit message, includes your full real name and - a valid and active email address by which you can be contacted in the - foreseeable future. +* Your signature for all of the above, which is the "Signed-off-by" line, + includes your full real name and a valid and active email address by + which you can be contacted in the foreseeable future. Code auto-formatting ==================== @@ -255,7 +251,7 @@ Documentation conventions ========================= MicroPython generally follows CPython in documentation process and -conventions. reStructuredText syntax is used for the documention. +conventions. reStructuredText syntax is used for the documentation. Specific conventions/suggestions: diff --git a/LICENSE b/LICENSE index 5a91df195fd4..07c88b0a0323 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2022 Damien P. George +Copyright (c) 2013-2023 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -36,7 +36,6 @@ used during the build process and is not part of the compiled source code. / (MIT) /drivers /cc3100 (BSD-3-clause) - /wiznet5k (BSD-3-clause) /lib /asf4 (Apache-2.0) /axtls (BSD-3-clause) @@ -61,12 +60,15 @@ used during the build process and is not part of the compiled source code. /tinytest (BSD-3-clause) /tinyusb (MIT) /uzlib (Zlib) + /wiznet5k (MIT) /logo (uses OFL-1.1) /ports /cc3200 /hal (BSD-3-clause) /simplelink (BSD-3-clause) /FreeRTOS (GPL-2.0 with FreeRTOS exception) + /esp32 + /ppp_set_auth.* (Apache-2.0) /stm32 /usbd*.c (MCD-ST Liberty SW License Agreement V2) /stm32_it.* (MIT + BSD-3-clause) diff --git a/docs/conf.py b/docs/conf.py index ce5c037568ad..a966b3a02570 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -67,7 +67,7 @@ # General information about the project. project = 'MicroPython' -copyright = '- The MicroPython Documentation is Copyright © 2014-2022, Damien P. George, Paul Sokolovsky, and contributors' +copyright = '- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -233,7 +233,7 @@ # Additional stuff for the LaTeX preamble. #'preamble': '', # Include 3 levels of headers in PDF ToC -'preamble': '\setcounter{tocdepth}{2}', +'preamble': r'\setcounter{tocdepth}{2}', } # Grouping the document tree into LaTeX files. List of tuples diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index 6bc2f62ab4d5..75dbc953c06f 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -53,7 +53,7 @@ A MicroPython user C module is a directory with the following files: ``SRC_USERMOD_C`` or ``SRC_USERMOD_LIB_C`` variables. The former will be processed for ``MP_QSTR_`` and ``MP_REGISTER_MODULE`` definitions, the latter will not (e.g. helpers and library code that isn't MicroPython-specific). - These paths should include your expaned copy of ``$(USERMOD_DIR)``, e.g.:: + These paths should include your expanded copy of ``$(USERMOD_DIR)``, e.g.:: SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index 74974a39e1b4..63919b97a6cc 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -38,6 +38,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main. .. code-block:: c + #include "py/builtin.h" #include "py/compile.h" #include "py/gc.h" #include "py/mperrno.h" @@ -110,6 +111,9 @@ We also need a Makefile at this point for the port: shared/runtime/pyexec.c \ shared/runtime/stdout_helpers.c \ + # Define source files containung qstrs. + SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c + # Define the required object files. OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) @@ -147,9 +151,6 @@ The following is an example of an ``mpconfigport.h`` file: #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) - // Enable u-modules to be imported with their standard name, like sys. - #define MICROPY_MODULE_WEAK_LINKS (1) - // Fine control over Python builtins, classes, modules, etc. #define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_BUILTINS_SET (0) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index f74926c37460..5be737fa2d76 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -57,7 +57,6 @@ The :mod:`esp32` module:: import esp32 - esp32.hall_sensor() # read the internal hall sensor esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit esp32.ULP() # access to the Ultra-Low-Power Co-processor @@ -137,19 +136,11 @@ The keyword arguments for the constructor defining the PHY type and interface ar or output. Suitable values are Pin.IN and Pin.OUT. - ref_clk=pin-object # defines the Pin used for ref_clk. -The options ref_clk_mode and ref_clk require at least esp-idf version 4.4. For -earlier esp-idf versions, these parameters must be defined by kconfig board options. - These are working configurations for LAN interfaces of popular boards:: # Olimex ESP32-GATEWAY: power controlled by Pin(5) # Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12) - lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5), - phy_type=network.PHY_LAN8720, phy_addr=0) - - # or with dynamic ref_clk pin configuration - lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5), phy_type=network.PHY_LAN8720, phy_addr=0, ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT) @@ -159,21 +150,17 @@ These are working configurations for LAN interfaces of popular boards:: lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), phy_type=network.PHY_LAN8720, phy_addr=1, power=None) + # Wireless-Tag's WT32-ETH01 v1.4 + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), + phy_type=network.PHY_LAN8720, phy_addr=1, + power=machine.Pin(16)) + # Espressif ESP32-Ethernet-Kit_A_V1.2 lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5), phy_type=network.PHY_IP101, phy_addr=1) -A suitable definition of the PHY interface in a sdkconfig.board file is:: - - CONFIG_ETH_PHY_INTERFACE_RMII=y - CONFIG_ETH_RMII_CLK_OUTPUT=y - CONFIG_ETH_RMII_CLK_OUT_GPIO=17 - CONFIG_LWIP_LOCAL_HOSTNAME="ESP32_POE" - -The value assigned to CONFIG_ETH_RMII_CLK_OUT_GPIO may vary depending on the -board's wiring. - Delay and timing ---------------- @@ -305,8 +292,8 @@ Use the :ref:`machine.PWM ` class:: from machine import Pin, PWM - pwm0 = PWM(Pin(0)) # create PWM object from a pin - freq = pwm0.freq() # get current frequency (default 5kHz) + pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin + freq = pwm0.freq() # get current frequency pwm0.freq(1000) # set PWM frequency from 1Hz to 40MHz duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%) diff --git a/docs/esp32/tutorial/intro.rst b/docs/esp32/tutorial/intro.rst index 8ed42dbd3dc9..be09599871ce 100644 --- a/docs/esp32/tutorial/intro.rst +++ b/docs/esp32/tutorial/intro.rst @@ -17,7 +17,7 @@ Requirements The first thing you need is a board with an ESP32 chip. The MicroPython software supports the ESP32 chip itself and any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside -world, and whether it includes a built-in USB-serial convertor to make the +world, and whether it includes a built-in USB-serial converter to make the UART available to your PC. Names of pins will be given in this tutorial using the chip names (eg GPIO2) @@ -59,7 +59,7 @@ bootloader 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. -Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR +Fortunately, most boards have a USB connector, a USB-serial converter, and 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 HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO @@ -104,7 +104,7 @@ 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. +converter, depending on your board. The baudrate is 115200. From here you can now follow the ESP8266 tutorial, because these two Espressif chips are very similar when it comes to using MicroPython on them. The ESP8266 tutorial @@ -124,7 +124,7 @@ after it, here are troubleshooting recommendations: * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your - module/board, USB-UART convertor, cables, host OS, etc., the above baud + module/board, USB-UART converter, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. diff --git a/docs/esp32/tutorial/pwm.rst b/docs/esp32/tutorial/pwm.rst index 12d10a86b947..2650284d35f4 100644 --- a/docs/esp32/tutorial/pwm.rst +++ b/docs/esp32/tutorial/pwm.rst @@ -50,7 +50,7 @@ low all of the time. * Example of a smooth frequency change:: - from utime import sleep + from time import sleep from machine import Pin, PWM F_MIN = 500 @@ -75,7 +75,7 @@ low all of the time. * Example of a smooth duty change:: - from utime import sleep + from time import sleep from machine import Pin, PWM DUTY_MAX = 2**16 - 1 diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst index 75739bd6f96f..0d4bc42e2dab 100644 --- a/docs/esp8266/tutorial/intro.rst +++ b/docs/esp8266/tutorial/intro.rst @@ -18,7 +18,7 @@ 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. +converter to make the UART available to your PC. The minimum requirement for flash size is 1Mbyte. There is also a special build for boards with 512KB, but it is highly limited comparing to the @@ -70,7 +70,7 @@ 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 +If you have a board that has a USB connector, a USB-serial converter, 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. @@ -128,7 +128,7 @@ 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 +converter, depending on your board. The baudrate is 115200. The next part of the tutorial will discuss the prompt in more detail. WiFi @@ -137,7 +137,7 @@ 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 +be the same every time, 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. @@ -169,7 +169,7 @@ after it, here are troubleshooting recommendations: * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your - module/board, USB-UART convertor, cables, host OS, etc., the above baud + module/board, USB-UART converter, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst index 196541bd02cb..bc0142aaef5f 100644 --- a/docs/esp8266/tutorial/repl.rst +++ b/docs/esp8266/tutorial/repl.rst @@ -13,7 +13,7 @@ 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 +If your board has a USB-serial converter 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. diff --git a/docs/library/array.rst b/docs/library/array.rst index f94cece2b7cc..f417a7046e2f 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -75,7 +75,7 @@ Classes Returns the string representation of the array, called as ``str(a)`` or ``repr(a)``` (where ``a`` is an ``array``). Returns the string ``"array(, [])"``, where ```` is the type code letter for the array and ```` is a comma - seperated list of the elements of the array. + separated list of the elements of the array. **Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work. diff --git a/docs/library/uasyncio.rst b/docs/library/asyncio.rst similarity index 92% rename from docs/library/uasyncio.rst rename to docs/library/asyncio.rst index 4cbcfa9f98ad..9a2c14e7e015 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/asyncio.rst @@ -1,7 +1,7 @@ -:mod:`uasyncio` --- asynchronous I/O scheduler -============================================== +:mod:`asyncio` --- asynchronous I/O scheduler +============================================= -.. module:: uasyncio +.. module:: asyncio :synopsis: asynchronous I/O scheduler for writing concurrent code |see_cpython_module| @@ -9,27 +9,27 @@ Example:: - import uasyncio + import asyncio async def blink(led, period_ms): while True: led.on() - await uasyncio.sleep_ms(5) + await asyncio.sleep_ms(5) led.off() - await uasyncio.sleep_ms(period_ms) + await asyncio.sleep_ms(period_ms) async def main(led1, led2): - uasyncio.create_task(blink(led1, 700)) - uasyncio.create_task(blink(led2, 400)) - await uasyncio.sleep_ms(10_000) + asyncio.create_task(blink(led1, 700)) + asyncio.create_task(blink(led2, 400)) + await asyncio.sleep_ms(10_000) # Running on a pyboard from pyb import LED - uasyncio.run(main(LED(1), LED(2))) + asyncio.run(main(LED(1), LED(2))) # Running on a generic board from machine import Pin - uasyncio.run(main(Pin(1), Pin(2))) + asyncio.run(main(Pin(1), Pin(2))) Core functions -------------- @@ -71,9 +71,9 @@ Additional functions than *timeout* seconds. If *awaitable* is not a task then a task will be created from it. - If a timeout occurs, it cancels the task and raises ``uasyncio.TimeoutError``: + If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: this should be trapped by the caller. The task receives - ``uasyncio.CancelledError`` which may be ignored or trapped using ``try...except`` + ``asyncio.CancelledError`` which may be ignored or trapped using ``try...except`` or ``try...finally`` to run cleanup code. Returns the return value of *awaitable*. @@ -108,7 +108,7 @@ class Task .. method:: Task.cancel() - Cancel the task by injecting ``uasyncio.CancelledError`` into it. The task may + Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may ignore this exception. Cleanup code may be run by trapping it, or via ``try ... finally``. @@ -148,7 +148,7 @@ class ThreadSafeFlag .. class:: ThreadSafeFlag() Create a new flag which can be used to synchronise a task with code running - outside the uasyncio loop, such as other threads, IRQs, or scheduler + outside the asyncio loop, such as other threads, IRQs, or scheduler callbacks. Flags start in the cleared state. The class does not currently work under the Unix build of MicroPython. diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 8f7041e8d3fb..78cb4cc28148 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -44,7 +44,7 @@ Configuration Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is - queried at a time. To set values use the keyword syntax, and one ore more + queried at a time. To set values use the keyword syntax, and one or more parameter can be set at a time. Currently supported values are: @@ -183,12 +183,10 @@ Event Handling conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_READ_DONE: # A gattc_read() has completed. - # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_WRITE_DONE: # A gattc_write() has completed. - # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: @@ -514,19 +512,24 @@ writes from a client to a given characteristic, use Sends a notification request to a connected client. - If *data* is not ``None``, then that value is sent to the client as part of - the notification. The local value will not be modified. + If *data* is ``None`` (the default), then the current local value (as set + with :meth:`gatts_write `) will be sent. - Otherwise, if *data* is ``None``, then the current local value (as - set with :meth:`gatts_write `) will be sent. + Otherwise, if *data* is not ``None``, then that value is sent to the client + as part of the notification. The local value will not be modified. **Note:** The notification will be sent regardless of the subscription status of the client to this characteristic. -.. method:: BLE.gatts_indicate(conn_handle, value_handle, /) +.. method:: BLE.gatts_indicate(conn_handle, value_handle, data=None, /) - Sends an indication request containing the characteristic's current value to - a connected client. + Sends a indication request to a connected client. + + If *data* is ``None`` (the default), then the current local value (as set + with :meth:`gatts_write `) will be sent. + + Otherwise, if *data* is not ``None``, then that value is sent to the client + as part of the indication. The local value will not be modified. On acknowledgment (or failure, e.g. timeout), the ``_IRQ_GATTS_INDICATE_DONE`` event will be raised. diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index f0f0c8ef1f56..efdd6c1be289 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -44,10 +44,6 @@ Functions Read the raw value of the internal temperature sensor, returning an integer. -.. function:: hall_sensor() - - Read the raw value of the internal Hall sensor, returning an integer. - .. function:: idf_heap_info(capabilities) Returns information about the ESP-IDF heap memory regions. One of them contains @@ -126,7 +122,7 @@ methods to enable over-the-air (OTA) updates. and an ``OSError(-261)`` is raised if called on firmware that doesn't have the feature enabled. It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not - necessary when booting firmare that was loaded using esptool. + necessary when booting firmware that was loaded using esptool. Constants ~~~~~~~~~ @@ -279,6 +275,14 @@ For more details see Espressif's `ESP-IDF RMT documentation. Ultra-Low-Power co-processor ---------------------------- +This class gives access to the Ultra Low Power (ULP) co-processor on the ESP32, +ESP32-S2 and ESP32-S3 chips. + +.. warning:: + + This class does not provide access to the RISCV ULP co-processor available + on the ESP32-S2 and ESP32-S3 chips. + .. class:: ULP() This class provides access to the Ultra-Low-Power co-processor. diff --git a/docs/library/espnow.rst b/docs/library/espnow.rst new file mode 100644 index 000000000000..f344983700a1 --- /dev/null +++ b/docs/library/espnow.rst @@ -0,0 +1,936 @@ +:mod:`espnow` --- support for the ESP-NOW wireless protocol +=========================================================== + +.. module:: espnow + :synopsis: ESP-NOW wireless protocol support + +This module provides an interface to the `ESP-NOW `_ protocol provided by Espressif on +ESP32 and ESP8266 devices (`API docs `_). + +Table of Contents: +------------------ + + - `Introduction`_ + - `Configuration`_ + - `Sending and Receiving Data`_ + - `Peer Management`_ + - `Callback Methods`_ + - `Exceptions`_ + - `Constants`_ + - `Wifi Signal Strength (RSSI) - (ESP32 Only)`_ + - `Supporting asyncio`_ + - `Broadcast and Multicast`_ + - `ESPNow and Wifi Operation`_ + - `ESPNow and Sleep Modes`_ + +Introduction +------------ + +ESP-NOW is a connection-less wireless communication protocol supporting: + +- Direct communication between up to 20 registered peers: + + - Without the need for a wireless access point (AP), + +- Encrypted and unencrypted communication (up to 6 encrypted peers), + +- Message sizes up to 250 bytes, + +- Can operate alongside Wifi operation (:doc:`network.WLAN`) on + ESP32 and ESP8266 devices. + +It is especially useful for small IoT networks, latency sensitive or power +sensitive applications (such as battery operated devices) and for long-range +communication between devices (hundreds of metres). + +This module also supports tracking the Wifi signal strength (RSSI) of peer +devices. + +A simple example would be: + +**Sender:** :: + + import network + import espnow + + # A WLAN interface must be active to send()/recv() + sta = network.WLAN(network.STA_IF) # Or network.AP_IF + sta.active(True) + sta.disconnect() # For ESP8266 + + e = espnow.ESPNow() + e.active(True) + peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' # MAC address of peer's wifi interface + e.add_peer(peer) # Must add_peer() before send() + + e.send(peer, "Starting...") + for i in range(100): + e.send(peer, str(i)*20, True) + e.send(peer, b'end') + +**Receiver:** :: + + import network + import espnow + + # A WLAN interface must be active to send()/recv() + sta = network.WLAN(network.STA_IF) + sta.active(True) + sta.disconnect() # Because ESP8266 auto-connects to last Access Point + + e = espnow.ESPNow() + e.active(True) + + while True: + host, msg = e.recv() + if msg: # msg == None if timeout in recv() + print(host, msg) + if msg == b'end': + break + +class ESPNow +------------ + +Constructor +----------- + +.. class:: ESPNow() + + Returns the singleton ESPNow object. As this is a singleton, all calls to + `espnow.ESPNow()` return a reference to the same object. + + .. note:: + Some methods are available only on the ESP32 due to code size + restrictions on the ESP8266 and differences in the Espressif API. + +Configuration +------------- + +.. method:: ESPNow.active([flag]) + + Initialise or de-initialise the ESP-NOW communication protocol depending on + the value of the ``flag`` optional argument. + + .. data:: Arguments: + + - *flag*: Any python value which can be converted to a boolean type. + + - ``True``: Prepare the software and hardware for use of the ESP-NOW + communication protocol, including: + + - initialise the ESPNow data structures, + - allocate the recv data buffer, + - invoke esp_now_init() and + - register the send and recv callbacks. + + - ``False``: De-initialise the Espressif ESP-NOW software stack + (esp_now_deinit()), disable callbacks, deallocate the recv + data buffer and deregister all peers. + + If *flag* is not provided, return the current status of the ESPNow + interface. + + .. data:: Returns: + + ``True`` if interface is currently *active*, else ``False``. + +.. method:: ESPNow.config(param=value, ...) + ESPNow.config('param') (ESP32 only) + + Set or get configuration values of the ESPNow interface. To set values, use + the keyword syntax, and one or more parameters can be set at a time. To get + a value the parameter name should be quoted as a string, and just one + parameter is queried at a time. + + **Note:** *Getting* parameters is not supported on the ESP8266. + + .. data:: Options: + + *rxbuf*: (default=526) Get/set the size in bytes of the internal + buffer used to store incoming ESPNow packet data. The default size is + selected to fit two max-sized ESPNow packets (250 bytes) with associated + mac_address (6 bytes), a message byte count (1 byte) and RSSI data plus + buffer overhead. Increase this if you expect to receive a lot of large + packets or expect bursty incoming traffic. + + **Note:** The recv buffer is allocated by `ESPNow.active()`. Changing + this value will have no effect until the next call of + `ESPNow.active(True)`. + + *timeout_ms*: (default=300,000) Default timeout (in milliseconds) + for receiving ESPNow messages. If *timeout_ms* is less than zero, then + wait forever. The timeout can also be provided as arg to + `recv()`/`irecv()`/`recvinto()`. + + *rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for + ESPNow packets. Must be set to a number from the allowed numeric values + in `enum wifi_phy_rate_t + `_. + + .. data:: Returns: + + ``None`` or the value of the parameter being queried. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``ValueError()`` on invalid configuration options or values. + +Sending and Receiving Data +-------------------------- + +A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be +`active()` before messages can be sent or received, +but it is not necessary to connect or configure the WLAN interface. +For example:: + + import network + + sta = network.WLAN(network.STA_IF) + sta.active(True) + sta.disconnect() # For ESP8266 + +**Note:** The ESP8266 has a *feature* that causes it to automatically reconnect +to the last wifi Access Point when set `active(True)` (even +after reboot/reset). This reduces the reliability of receiving ESP-NOW messages +(see `ESPNow and Wifi Operation`_). You can avoid this by calling +`disconnect()` after +`active(True)`. + +.. method:: ESPNow.send(mac, msg[, sync]) + ESPNow.send(msg) (ESP32 only) + + Send the data contained in ``msg`` to the peer with given network ``mac`` + address. In the second form, ``mac=None`` and ``sync=True``. The peer must + be registered with `ESPNow.add_peer()` before the + message can be sent. + + .. data:: Arguments: + + - *mac*: byte string exactly ``espnow.ADDR_LEN`` (6 bytes) long or + ``None``. If *mac* is ``None`` (ESP32 only) the message will be sent + to all registered peers, except any broadcast or multicast MAC + addresses. + + - *msg*: string or byte-string up to ``espnow.MAX_DATA_LEN`` (250) + bytes long. + + - *sync*: + + - ``True``: (default) send ``msg`` to the peer(s) and wait for a + response (or not). + + - ``False`` send ``msg`` and return immediately. Responses from the + peers will be discarded. + + .. data:: Returns: + + ``True`` if ``sync=False`` or if ``sync=True`` and *all* peers respond, + else ``False``. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if peer is not registered. + - ``OSError(num, "ESP_ERR_ESPNOW_IF")`` the wifi interface is not + `active()`. + - ``OSError(num, "ESP_ERR_ESPNOW_NO_MEM")`` internal ESP-NOW buffers are + full. + - ``ValueError()`` on invalid values for the parameters. + + **Note**: A peer will respond with success if its wifi interface is + `active()` and set to the same channel as the sender, + regardless of whether it has initialised it's ESP-NOW system or is + actively listening for ESP-NOW traffic (see the Espressif ESP-NOW docs). + +.. method:: ESPNow.recv([timeout_ms]) + + Wait for an incoming message and return the ``mac`` address of the peer and + the message. **Note**: It is **not** necessary to register a peer (using + `add_peer()`) to receive a message from that peer. + + .. data:: Arguments: + + - *timeout_ms*: (Optional): May have the following values. + + - ``0``: No timeout. Return immediately if no data is available; + - ``> 0``: Specify a timeout value in milliseconds; + - ``< 0``: Do not timeout, ie. wait forever for new messages; or + - ``None`` (or not provided): Use the default timeout value set with + `ESPNow.config()`. + + .. data:: Returns: + + - ``(None, None)`` if timeout is reached before a message is received, or + + - ``[mac, msg]``: where: + + - ``mac`` is a bytestring containing the address of the device which + sent the message, and + - ``msg`` is a bytestring containing the message. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_IF")`` if the wifi interface is not + `active()`. + - ``ValueError()`` on invalid *timeout_ms* values. + + `ESPNow.recv()` will allocate new storage for the returned list and the + ``peer`` and ``msg`` bytestrings. This can lead to memory fragmentation if + the data rate is high. See `ESPNow.irecv()` for a memory-friendly + alternative. + + +.. method:: ESPNow.irecv([timeout_ms]) + + Works like `ESPNow.recv()` but will re-use internal bytearrays to store the + return values: ``[mac, msg]``, so that no new memory is allocated on each + call. + + .. data:: Arguments: + + *timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`). + + .. data:: Returns: + + - As for `ESPNow.recv()`, except that ``msg`` is a bytearray, instead of + a bytestring. On the ESP8266, ``mac`` will also be a bytearray. + + .. data:: Raises: + + - See `ESPNow.recv()`. + + **Note:** You may also read messages by iterating over the ESPNow object, + which will use the `irecv()` method for alloc-free reads, eg: :: + + import espnow + e = espnow.ESPNow(); e.active(True) + for mac, msg in e: + print(mac, msg) + if mac is None: # mac, msg will equal (None, None) on timeout + break + +.. method:: ESPNow.recvinto(data[, timeout_ms]) + + Wait for an incoming message and return the length of the message in bytes. + This is the low-level method used by both `recv()` and + `irecv()` to read messages. + + .. data:: Arguments: + + *data*: A list of at least two elements, ``[peer, msg]``. ``msg`` must + be a bytearray large enough to hold the message (250 bytes). On the + ESP8266, ``peer`` should be a bytearray of 6 bytes. The MAC address of + the sender and the message will be stored in these bytearrays (see Note + on ESP32 below). + + *timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`). + + .. data:: Returns: + + - Length of message in bytes or 0 if *timeout_ms* is reached before a + message is received. + + .. data:: Raises: + + - See `ESPNow.recv()`. + + **Note:** On the ESP32: + + - It is unnecessary to provide a bytearray in the first element of the + ``data`` list because it will be replaced by a reference to a unique + ``peer`` address in the **peer device table** (see `ESPNow.peers_table`). + - If the list is at least 4 elements long, the rssi and timestamp values + will be saved as the 3rd and 4th elements. + +.. method:: ESPNow.any() + + Check if data is available to be read with `ESPNow.recv()`. + + For more sophisticated querying of available characters use `select.poll()`:: + + import select + import espnow + + e = espnow.ESPNow() + poll = select.poll() + poll.register(e, select.POLLIN) + poll.poll(timeout) + + .. data:: Returns: + + ``True`` if data is available to be read, else ``False``. + +.. method:: ESPNow.stats() (ESP32 only) + + .. data:: Returns: + + A 5-tuple containing the number of packets sent/received/lost: + + ``(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)`` + + Incoming packets are *dropped* when the recv buffers are full. To reduce + packet loss, increase the ``rxbuf`` config parameters and ensure you are + reading messages as quickly as possible. + + **Note**: Dropped packets will still be acknowledged to the sender as + received. + +Peer Management +--------------- + +On ESP32 devices, the Espressif ESP-NOW software requires that other devices +(peers) must be *registered* using `add_peer()` before we can +`send()` them messages (this is *not* enforced on ESP8266 +devices). It is **not** necessary to register a peer to receive an +un-encrypted message from that peer. + +**Encrypted messages**: To receive an *encrypted* message, the receiving device +must first register the sender and use the same encryption keys as the sender +(PMK and LMK) (see `set_pmk()` and `add_peer()`. + +.. method:: ESPNow.set_pmk(pmk) + + Set the Primary Master Key (PMK) which is used to encrypt the Local Master + Keys (LMK) for encrypting messages. If this is not set, a default PMK is + used by the underlying Espressif ESP-NOW software stack. + + **Note:** messages will only be encrypted if *lmk* is also set in + `ESPNow.add_peer()` (see `Security + `_ in the Espressif API + docs). + + .. data:: Arguments: + + *pmk*: Must be a byte string, bytearray or string of length + `espnow.KEY_LEN` (16 bytes). + + .. data:: Returns: + + ``None`` + + .. data:: Raises: + + ``ValueError()`` on invalid *pmk* values. + +.. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt]) + ESPNow.add_peer(mac, param=value, ...) (ESP32 only) + + Add/register the provided *mac* address as a peer. Additional parameters may + also be specified as positional or keyword arguments (any parameter set to + ``None`` will be set to it's default value): + + .. data:: Arguments: + + - *mac*: The MAC address of the peer (as a 6-byte byte-string). + + - *lmk*: The Local Master Key (LMK) key used to encrypt data + transfers with this peer (unless the *encrypt* parameter is set to + ``False``). Must be: + + - a byte-string or bytearray or string of length ``espnow.KEY_LEN`` + (16 bytes), or + + - any non ``True`` python value (default= ``b''``), signifying an + *empty* key which will disable encryption. + + - *channel*: The wifi channel (2.4GHz) to communicate with this peer. + Must be an integer from 0 to 14. If channel is set to 0 the current + channel of the wifi device will be used. (default=0) + + - *ifidx*: (ESP32 only) Index of the wifi interface which will be + used to send data to this peer. Must be an integer set to + ``network.STA_IF`` (=0) or ``network.AP_IF`` (=1). + (default=0/``network.STA_IF``). See `ESPNow and Wifi Operation`_ + below for more information. + + - *encrypt*: (ESP32 only) If set to ``True`` data exchanged with + this peer will be encrypted with the PMK and LMK. (default = + ``True`` if *lmk* is set to a valid key, else ``False``) + + **ESP8266**: Keyword args may not be used on the ESP8266. + + **Note:** The maximum number of peers which may be registered is 20 + (`espnow.MAX_TOTAL_PEER_NUM`), with a maximum of 6 + (`espnow.MAX_ENCRYPT_PEER_NUM`) of those peers with encryption enabled + (see `ESP_NOW_MAX_ENCRYPT_PEER_NUM `_ in the Espressif API + docs). + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_EXIST")`` if *mac* is already + registered. + - ``OSError(num, "ESP_ERR_ESPNOW_FULL")`` if too many peers are + already registered. + - ``ValueError()`` on invalid keyword args or values. + +.. method:: ESPNow.del_peer(mac) + + Deregister the peer associated with the provided *mac* address. + + .. data:: Returns: + + ``None`` + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not + registered. + - ``ValueError()`` on invalid *mac* values. + +.. method:: ESPNow.get_peer(mac) (ESP32 only) + + Return information on a registered peer. + + .. data:: Returns: + + ``(mac, lmk, channel, ifidx, encrypt)``: a tuple of the "peer + info" associated with the given *mac* address. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not + registered. + - ``ValueError()`` on invalid *mac* values. + +.. method:: ESPNow.peer_count() (ESP32 only) + + Return the number of registered peers: + + - ``(peer_num, encrypt_num)``: where + + - ``peer_num`` is the number of peers which are registered, and + - ``encrypt_num`` is the number of encrypted peers. + +.. method:: ESPNow.get_peers() (ESP32 only) + + Return the "peer info" parameters for all the registered peers (as a tuple + of tuples). + +.. method:: ESPNow.mod_peer(mac, lmk, [channel], [ifidx], [encrypt]) (ESP32 only) + ESPNow.mod_peer(mac, 'param'=value, ...) (ESP32 only) + + Modify the parameters of the peer associated with the provided *mac* + address. Parameters may be provided as positional or keyword arguments + (see `ESPNow.add_peer()`). Any parameter that is not set (or set to + ``None``) will retain the existing value for that parameter. + +Callback Methods +---------------- + +.. method:: ESPNow.irq(callback) (ESP32 only) + + Set a callback function to be called *as soon as possible* after a message has + been received from another ESPNow device. The callback function will be called + with the `ESPNow` instance object as an argument. For more reliable operation, + it is recommended to read out as many messages as are available when the + callback is invoked and to set the read timeout to zero, eg: :: + + def recv_cb(e): + while True: # Read out all messages waiting in the buffer + mac, msg = e.irecv(0) # Don't wait if no messages left + if mac is None: + return + print(mac, msg) + e.irq(recv_cb) + + The `irq()` callback method is an alternative method for + processing incoming messages, especially if the data rate is moderate + and the device is *not too busy* but there are some caveats: + + - The scheduler stack *can* overflow and callbacks will be missed if + packets are arriving at a sufficient rate or if other MicroPython components + (eg, bluetooth, machine.Pin.irq(), machine.timer, i2s, ...) are exercising + the scheduler stack. This method may be less reliable for dealing with + bursts of messages, or high throughput or on a device which is busy dealing + with other hardware operations. + + - For more information on *scheduled* function callbacks see: + `micropython.schedule()`. + +Constants +--------- + +.. data:: espnow.MAX_DATA_LEN(=250) + espnow.KEY_LEN(=16) + espnow.ADDR_LEN(=6) + espnow.MAX_TOTAL_PEER_NUM(=20) + espnow.MAX_ENCRYPT_PEER_NUM(=6) + +Exceptions +---------- + +If the underlying Espressif ESP-NOW software stack returns an error code, +the MicroPython espnow module will raise an ``OSError(errnum, errstring)`` +exception where ``errstring`` is set to the name of one of the error codes +identified in the +`Espressif ESP-NOW docs +`_. For example:: + + try: + e.send(peer, 'Hello') + except OSError as err: + if len(err.args) < 2: + raise err + if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT': + e.active(True) + elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + e.add_peer(peer) + elif err.args[1] == 'ESP_ERR_ESPNOW_IF': + network.WLAN(network.STA_IF).active(True) + else: + raise err + +Wifi Signal Strength (RSSI) - (ESP32 only) +------------------------------------------ + +The ESPNow object maintains a **peer device table** which contains the signal +strength and timestamp of the last received message from all hosts. The **peer +device table** can be accessed using `ESPNow.peers_table` and can be used to +track device proximity and identify *nearest neighbours* in a network of peer +devices. This feature is **not** available on ESP8266 devices. + +.. data:: ESPNow.peers_table + + A reference to the **peer device table**: a dict of known peer devices + and rssi values:: + + {peer: [rssi, time_ms], ...} + + where: + + - ``peer`` is the peer MAC address (as `bytes`); + - ``rssi`` is the wifi signal strength in dBm (-127 to 0) of the last + message received from the peer; and + - ``time_ms`` is the time the message was received (in milliseconds since + system boot - wraps every 12 days). + + Example:: + + >>> e.peers_table + {b'\xaa\xaa\xaa\xaa\xaa\xaa': [-31, 18372], + b'\xbb\xbb\xbb\xbb\xbb\xbb': [-43, 12541]} + + **Note**: the ``mac`` addresses returned by `recv()` are references to + the ``peer`` key values in the **peer device table**. + + **Note**: RSSI and timestamp values in the device table are updated only + when the message is read by the application. + +Supporting asyncio +------------------ + +A supplementary module (`aioespnow`) is available to provide +:doc:`asyncio` support. + +**Note:** Asyncio support is available on all ESP32 targets as well as those +ESP8266 boards which include the asyncio module (ie. ESP8266 devices with at +least 2MB flash memory). + +A small async server example:: + + import network + import aioespnow + import asyncio + + # A WLAN interface must be active to send()/recv() + network.WLAN(network.STA_IF).active(True) + + e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support + e.active(True) + peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' + e.add_peer(peer) + + # Send a periodic ping to a peer + async def heartbeat(e, peer, period=30): + while True: + if not await e.asend(peer, b'ping'): + print("Heartbeat: peer not responding:", peer) + else: + print("Heartbeat: ping", peer) + await asyncio.sleep(period) + + # Echo any received messages back to the sender + async def echo_server(e): + async for mac, msg in e: + print("Echo:", msg) + try: + await e.asend(mac, msg) + except OSError as err: + if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + e.add_peer(mac) + await e.asend(mac, msg) + + async def main(e, peer, timeout, period): + asyncio.create_task(heartbeat(e, peer, period)) + asyncio.create_task(echo_server(e)) + await asyncio.sleep(timeout) + + asyncio.run(main(e, peer, 120, 10)) + +.. module:: aioespnow + :synopsis: ESP-NOW :doc:`asyncio` support + +.. class:: AIOESPNow() + + The `AIOESPNow` class inherits all the methods of `ESPNow` + and extends the interface with the following async methods. + +.. method:: async AIOESPNow.arecv() + + Asyncio support for `ESPNow.recv()`. Note that this method does not take a + timeout value as argument. + +.. method:: async AIOESPNow.airecv() + + Asyncio support for `ESPNow.irecv()`. Note that this method does not take a + timeout value as argument. + +.. method:: async AIOESPNow.asend(mac, msg, sync=True) + async AIOESPNow.asend(msg) + + Asyncio support for `ESPNow.send()`. + +.. method:: AIOESPNow._aiter__() / async AIOESPNow.__anext__() + + `AIOESPNow` also supports reading incoming messages by asynchronous + iteration using ``async for``; eg:: + + e = AIOESPNow() + e.active(True) + async def recv_till_halt(e): + async for mac, msg in e: + print(mac, msg) + if msg == b'halt': + break + asyncio.run(recv_till_halt(e)) + +Broadcast and Multicast +----------------------- + +All active ESPNow clients will receive messages sent to their MAC address and +all devices (**except ESP8266 devices**) will also receive messages sent to the +*broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast +MAC address. + +All ESPNow devices (including ESP8266 devices) can also send messages to the +broadcast MAC address or any multicast MAC address. + +To `send()` a broadcast message, the broadcast (or +multicast) MAC address must first be registered using +`add_peer()`. `send()` will always return +``True`` for broadcasts, regardless of whether any devices receive the +message. It is not permitted to encrypt messages sent to the broadcast +address or any multicast address. + +**Note**: `ESPNow.send(None, msg)` will send to all registered +peers *except* the broadcast address. To send a broadcast or multicast +message, you must specify the broadcast (or multicast) MAC address as the +peer. For example:: + + bcast = b'\xff' * 6 + e.add_peer(bcast) + e.send(bcast, "Hello World!") + +ESPNow and Wifi Operation +------------------------- + +ESPNow messages may be sent and received on any `active()` +`WLAN` interface (``network.STA_IF`` or ``network.AP_IF``), even +if that interface is also connected to a wifi network or configured as an access +point. When an ESP32 or ESP8266 device connects to a Wifi Access Point (see +`ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things +happen which affect ESPNow communications: + +1. Wifi Power-saving Mode (`network.WLAN.PM_PERFORMANCE`) + is automatically activated and +2. The radio on the esp device changes wifi ``channel`` to match the channel + used by the Access Point. + +**Wifi Power-saving Mode:** (see `Espressif Docs `_) The power saving mode causes the +device to turn off the radio periodically (typically for hundreds of +milliseconds), making it unreliable in receiving ESPNow messages. This can be +resolved by either of: + +1. Disabling the power-saving mode on the STA_IF interface; + + - Use ``sta.config(pm=sta.PM_NONE)`` + +2. Turning on the AP_IF interface, which will disable the power saving mode. + However, the device will then be advertising an active wifi access point. + + - You **may** also choose to send your messages via the AP_IF interface, but + this is not necessary. + - ESP8266 peers must send messages to this AP_IF interface (see below). + +3. Configuring ESPNow clients to retry sending messages. + +**Receiving messages from an ESP8266 device:** Strangely, an ESP32 device +connected to a wifi network using method 1 or 2 above, will receive ESPNow +messages sent to the STA_IF MAC address from another ESP32 device, but will +**reject** messages from an ESP8266 device!!!. To receive messages from an +ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and** +messages must be sent to the AP_IF MAC address. + +**Managing wifi channels:** Any other ESPNow devices wishing to communicate with +a device which is also connected to a Wifi Access Point MUST use the same +channel. A common scenario is where one ESPNow device is connected to a wifi +router and acts as a proxy for messages from a group of sensors connected via +ESPNow: + +**Proxy:** :: + + import network, time, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.connect('myssid', 'mypassword') + while not sta.isconnected(): # Wait until connected... + time.sleep(0.1) + sta.config(pm=sta.PM_NONE) # ..then disable power saving + + # Print the wifi channel used AFTER finished connecting to access point + print("Proxy running on channel:", sta.config("channel")) + e = espnow.ESPNow(); e.active(True) + for peer, msg in e: + # Receive espnow messages and forward them to MQTT broker over wifi + +**Sensor:** :: + + import network, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.config(channel=6) # Change to the channel used by the proxy above. + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of proxy + e = espnow.ESPNow(); e.active(True); + e.add_peer(peer) + while True: + msg = read_sensor() + e.send(peer, msg) + time.sleep(1) + +Other issues to take care with when using ESPNow with wifi are: + +- **Set WIFI to known state on startup:** MicroPython does not reset the wifi + peripheral after a soft reset. This can lead to unexpected behaviour. To + guarantee the wifi is reset to a known state after a soft reset make sure you + deactivate the STA_IF and AP_IF before setting them to the desired state at + startup, eg.:: + + import network, time + + def wifi_reset(): # Reset wifi to AP_IF off, STA_IF on and disconnected + sta = network.WLAN(network.STA_IF); sta.active(False) + ap = network.WLAN(network.AP_IF); ap.active(False) + sta.active(True) + while not sta.active(): + time.sleep(0.1) + sta.disconnect() # For ESP8266 + while sta.isconnected(): + time.sleep(0.1) + return sta, ap + + sta, ap = wifi_reset() + + Remember that a soft reset occurs every time you connect to the device REPL + and when you type ``ctrl-D``. + +- **STA_IF and AP_IF always operate on the same channel:** the AP_IF will change + channel when you connect to a wifi network; regardless of the channel you set + for the AP_IF (see `Attention Note 3 + `_ + ). After all, there is really only one wifi radio on the device, which is + shared by the STA_IF and AP_IF virtual devices. + +- **Disable automatic channel assignment on your wifi router:** If the wifi + router for your wifi network is configured to automatically assign the wifi + channel, it may change the channel for the network if it detects interference + from other wifi routers. When this occurs, the ESP devices connected to the + wifi network will also change channels to match the router, but other + ESPNow-only devices will remain on the previous channel and communication will + be lost. To mitigate this, either set your wifi router to use a fixed wifi + channel or configure your devices to re-scan the wifi channels if they are + unable to find their expected peers on the current channel. + +- **MicroPython re-scans wifi channels when trying to reconnect:** If the esp + device is connected to a Wifi Access Point that goes down, MicroPython will + automatically start scanning channels in an attempt to reconnect to the + Access Point. This means ESPNow messages will be lost while scanning for the + AP. This can be disabled by ``sta.config(reconnects=0)``, which will also + disable the automatic reconnection after losing connection. + +- Some versions of the ESP IDF only permit sending ESPNow packets from the + STA_IF interface to peers which have been registered on the same wifi + channel as the STA_IF:: + + ESPNOW: Peer channel is not equal to the home channel, send fail! + +ESPNow and Sleep Modes +---------------------- + +The `machine.lightsleep([time_ms])` and +`machine.deepsleep([time_ms])` functions can be used to put +the ESP32 and peripherals (including the WiFi and Bluetooth radios) to sleep. +This is useful in many applications to conserve battery power. However, +applications must disable the WLAN peripheral (using +`active(False)`) before entering light or deep sleep (see +`Sleep Modes `_). +Otherwise the WiFi radio may not be initialised properly after wake from +sleep. If the ``STA_IF`` and ``AP_IF`` interfaces have both been set +`active(True)` then both interfaces should be set +`active(False)` before entering any sleep mode. + +**Example:** deep sleep:: + + import network, machine, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer + e = espnow.ESPNow() + e.active(True) + e.add_peer(peer) # Register peer on STA_IF + + print('Sending ping...') + if not e.send(peer, b'ping'): + print('Ping failed!') + e.active(False) + sta.active(False) # Disable the wifi before sleep + print('Going to sleep...') + machine.deepsleep(10000) # Sleep for 10 seconds then reboot + +**Example:** light sleep:: + + import network, machine, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.config(channel=6) + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer + e = espnow.ESPNow() + e.active(True) + e.add_peer(peer) # Register peer on STA_IF + + while True: + print('Sending ping...') + if not e.send(peer, b'ping'): + print('Ping failed!') + sta.active(False) # Disable the wifi before sleep + print('Going to sleep...') + machine.lightsleep(10000) # Sleep for 10 seconds + sta.active(True) + sta.config(channel=6) # Wifi loses config after lightsleep() + diff --git a/docs/library/index.rst b/docs/library/index.rst index 59ed1127a783..69bc81ade5e1 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -8,15 +8,17 @@ MicroPython libraries Important summary of this section * MicroPython provides built-in modules that mirror the functionality of the - Python standard library (e.g. :mod:`os`, :mod:`time`), as well as - MicroPython-specific modules (e.g. :mod:`bluetooth`, :mod:`machine`). - * Most standard library modules implement a subset of the functionality of - the equivalent Python module, and in a few cases provide some - MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`) + :ref:`Python standard library ` (e.g. :mod:`os`, + :mod:`time`), as well as :ref:`MicroPython-specific modules ` + (e.g. :mod:`bluetooth`, :mod:`machine`). + * Most Python standard library modules implement a subset of the + functionality of the equivalent Python module, and in a few cases provide + some MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`) * Due to resource constraints or other limitations, some ports or firmware versions may not include all the functionality documented here. - * To allow for extensibility, the built-in modules can be extended from - Python code loaded onto the device. + * To allow for extensibility, some built-in modules can be + :ref:`extended from Python code ` loaded onto + the device filesystem. This chapter describes modules (function and class libraries) which are built into MicroPython. This documentation in general aspires to describe all modules @@ -41,6 +43,8 @@ Beyond the built-in libraries described in this documentation, many more modules from the Python standard library, as well as further MicroPython extensions to it, can be found in :term:`micropython-lib`. +.. _micropython_lib_python: + Python standard libraries and micro-libraries --------------------------------------------- @@ -53,6 +57,7 @@ library. :maxdepth: 1 array.rst + asyncio.rst binascii.rst builtins.rst cmath.rst @@ -73,10 +78,10 @@ library. struct.rst sys.rst time.rst - uasyncio.rst zlib.rst _thread.rst +.. _micropython_lib_micropython: MicroPython-specific libraries ------------------------------ @@ -155,6 +160,11 @@ The following libraries are specific to the ESP8266 and ESP32. esp.rst esp32.rst +.. toctree:: + :maxdepth: 1 + + espnow.rst + Libraries specific to the RP2040 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -176,23 +186,60 @@ The following libraries are specific to the Zephyr port. zephyr.rst +.. _micropython_lib_extending: + Extending built-in libraries from Python ---------------------------------------- -In most cases, the above modules are actually named ``umodule`` rather than -``module``, but MicroPython will alias any module prefixed with a ``u`` to the -non-``u`` version. However a file (or :term:`frozen module`) named -``module.py`` will take precedence over this alias. +A subset of the built-in modules are able to be extended by Python code by +providing a module of the same name in the filesystem. This extensibility +applies to the following Python standard library modules which are built-in to +the firmware: ``array``, ``binascii``, ``collections``, ``errno``, ``hashlib``, +``heapq``, ``io``, ``json``, ``os``, ``platform``, ``random``, ``re``, +``select``, ``socket``, ``ssl``, ``struct``, ``time`` ``zlib``, as well as the +MicroPython-specific ``machine`` module. All other built-in modules cannot be +extended from the filesystem. This allows the user to provide an extended implementation of a built-in library -(perhaps to provide additional CPython compatibility). The user-provided module -(in ``module.py``) can still use the built-in functionality by importing -``umodule`` directly. This is used extensively in :term:`micropython-lib`. See -:ref:`packages` for more information. - -This applies to both the Python standard libraries (e.g. ``os``, ``time``, etc), -but also the MicroPython libraries too (e.g. ``machine``, ``bluetooth``, etc). -The main exception is the port-specific libraries (``pyb``, ``esp``, etc). - -*Other than when you specifically want to force the use of the built-in module, -we recommend always using* ``import module`` *rather than* ``import umodule``. +(perhaps to provide additional CPython compatibility or missing functionality). +This is used extensively in :term:`micropython-lib`, see :ref:`packages` for +more information. The filesystem module will typically do a wildcard import of +the built-in module in order to inherit all the globals (classes, functions and +variables) from the built-in. + +In MicroPython v1.21.0 and higher, to prevent the filesystem module from +importing itself, it can force an import of the built-in module it by +temporarily clearing ``sys.path`` during the import. For example, to extend the +``time`` module from Python, a file named ``time.py`` on the filesystem would +do the following:: + + _path = sys.path + sys.path = () + try: + from time import * + finally: + sys.path = _path + del _path + + def extra_method(): + pass + +The result is that ``time.py`` contains all the globals of the built-in ``time`` +module, but adds ``extra_method``. + +In earlier versions of MicroPython, you can force an import of a built-in module +by appending a ``u`` to the start of its name. For example, ``import utime`` +instead of ``import time``. For example, ``time.py`` on the filesystem could +look like:: + + from utime import * + + def extra_method(): + pass + +This way is still supported, but the ``sys.path`` method described above is now +preferred as the ``u``-prefix will be removed from the names of built-in +modules in a future version of MicroPython. + +*Other than when it specifically needs to force the use of the built-in module, +code should always use* ``import module`` *rather than* ``import umodule``. diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADC.rst index eb538a4424f6..65225ea8788d 100644 --- a/docs/library/machine.ADC.rst +++ b/docs/library/machine.ADC.rst @@ -4,7 +4,7 @@ class ADC -- analog to digital conversion ========================================= -The ADC class provides an interface to analog-to-digital convertors, and +The ADC class provides an interface to analog-to-digital converters, and represents a single endpoint that can sample a continuous voltage and convert it to a discretised value. diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index 0eb1b67f586d..635d5873444b 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -52,7 +52,7 @@ Example usage:: Constructors ------------ -.. class:: I2C(id, *, scl, sda, freq=400000) +.. class:: I2C(id, *, scl, sda, freq=400000, timeout=50000) Construct and return a new I2C object using the following parameters: @@ -62,6 +62,8 @@ Constructors - *sda* should be a pin object specifying the pin to use for SDA. - *freq* should be an integer which sets the maximum frequency for SCL. + - *timeout* is the maximum time in microseconds to allow for I2C + transactions. This parameter is not allowed on some ports. Note that some ports/boards will have default values of *scl* and *sda* that can be changed in this constructor. Others will have fixed values @@ -92,7 +94,7 @@ General Methods - *freq* is the SCL clock rate In the case of hardware I2C the actual clock frequency may be lower than the - requested frequency. This is dependant on the platform hardware. The actual + requested frequency. This is dependent on the platform hardware. The actual rate may be determined by printing the I2C object. .. method:: I2C.deinit() diff --git a/docs/library/machine.I2S.rst b/docs/library/machine.I2S.rst index b602ac6504d3..84edb94e78db 100644 --- a/docs/library/machine.I2S.rst +++ b/docs/library/machine.I2S.rst @@ -47,7 +47,7 @@ I2S objects can be created and initialized using:: 3 modes of operation are supported: - blocking - non-blocking - - uasyncio + - asyncio blocking:: @@ -63,13 +63,13 @@ non-blocking:: audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled num_read = audio_in.readinto(buf) # returns immediately -uasyncio:: +asyncio:: - swriter = uasyncio.StreamWriter(audio_out) + swriter = asyncio.StreamWriter(audio_out) swriter.write(buf) await swriter.drain() - sreader = uasyncio.StreamReader(audio_in) + sreader = asyncio.StreamReader(audio_in) num_read = await sreader.readinto(buf) Some codec devices like the WM8960 or SGTL5000 require separate initialization @@ -103,7 +103,7 @@ Constructor - ``ibuf`` specifies internal buffer length (bytes) For all ports, DMA runs continuously in the background and allows user applications to perform other operations while - sample data is transfered between the internal buffer and the I2S peripheral unit. + sample data is transferred between the internal buffer and the I2S peripheral unit. Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method). diff --git a/docs/library/machine.PWM.rst b/docs/library/machine.PWM.rst index 4b7435577560..b9cf00240314 100644 --- a/docs/library/machine.PWM.rst +++ b/docs/library/machine.PWM.rst @@ -10,7 +10,8 @@ Example usage:: from machine import PWM - pwm = PWM(pin) # create a PWM object on a pin + pwm = PWM(pin, freq=50, duty_u16=8192) # create a PWM object on a pin + # and set freq and duty pwm.duty_u16(32768) # set duty to 50% # reinitialise with a period of 200us, duty of 5us @@ -23,7 +24,7 @@ Example usage:: Constructors ------------ -.. class:: PWM(dest, *, freq, duty_u16, duty_ns) +.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert) Construct and return a new PWM object using the following parameters: @@ -34,10 +35,12 @@ Constructors PWM cycle. - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``. - *duty_ns* sets the pulse width in nanoseconds. + - *invert* inverts the respective output if the value is True Setting *freq* may affect other PWM objects if the objects share the same underlying PWM generator (this is hardware specific). Only one of *duty_u16* and *duty_ns* should be specified at a time. + *invert* is not available at all ports. Methods ------- diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst index 7b0e8cf40689..7c3c4b583265 100644 --- a/docs/library/machine.SPI.rst +++ b/docs/library/machine.SPI.rst @@ -98,7 +98,7 @@ Methods specify them as a tuple of ``pins`` parameter. In the case of hardware SPI the actual clock frequency may be lower than the - requested baudrate. This is dependant on the platform hardware. The actual + requested baudrate. This is dependent on the platform hardware. The actual rate may be determined by printing the SPI object. .. method:: SPI.deinit() diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 48c023a11c34..44e659408055 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -73,7 +73,7 @@ Methods - ``callback`` - The callable to call upon expiration of the timer period. The callback must take one argument, which is passed the Timer object. The ``callback`` argument shall be specified. Otherwise an exception - will occurr upon timer expiration: + will occur upon timer expiration: ``TypeError: 'NoneType' object isn't callable`` .. method:: Timer.deinit() diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst index 95893cec36be..cf77df963208 100644 --- a/docs/library/machine.WDT.rst +++ b/docs/library/machine.WDT.rst @@ -25,9 +25,8 @@ Constructors Create a WDT object and start it. The timeout must be given in milliseconds. Once it is running the timeout cannot be changed and the WDT cannot be stopped either. - Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout - cannot be specified, it is determined by the underlying system. On rp2040 devices, - the maximum timeout is 8388 ms. + Notes: On the esp8266 a timeout cannot be specified, it is determined by the underlying system. + On rp2040 devices, the maximum timeout is 8388 ms. Methods ------- diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst index d1e620ef09f9..68cd49769aff 100644 --- a/docs/library/network.WLAN.rst +++ b/docs/library/network.WLAN.rst @@ -133,4 +133,20 @@ Methods hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP). (Deprecated, use :func:`network.hostname` instead) reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) txpower Maximum transmit power in dBm (integer or float) + pm WiFi Power Management setting (see below for allowed values) ============= =========== + +Constants +--------- + +.. data:: WLAN.PM_PERFORMANCE + WLAN.PM_POWERSAVE + WLAN.PM_NONE + + Allowed values for the ``WLAN.config(pm=...)`` network interface parameter: + + * ``PM_PERFORMANCE``: enable WiFi power management to balance power + savings and WiFi performance + * ``PM_POWERSAVE``: enable WiFi power management with additional power + savings and reduced WiFi performance + * ``PM_NONE``: disable wifi power management diff --git a/docs/library/os.rst b/docs/library/os.rst index 19652ee2bc5e..27a7d2d44a05 100644 --- a/docs/library/os.rst +++ b/docs/library/os.rst @@ -86,7 +86,7 @@ Filesystem access .. function:: statvfs(path) - Get the status of a fileystem. + Get the status of a filesystem. Returns a tuple with the filesystem information in the following order: diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst index 5ca00b65e5c5..57a85d54b771 100644 --- a/docs/library/pyb.CAN.rst +++ b/docs/library/pyb.CAN.rst @@ -272,7 +272,7 @@ Methods - *fdf* for CAN FD controllers, if set to True, the frame will have an FD frame format, which supports data payloads up to 64 bytes. - *brs* for CAN FD controllers, if set to True, the bitrate switching mode - is enabled, in which the data phase is transmitted at a differet bitrate. + is enabled, in which the data phase is transmitted at a different bitrate. See :meth:`CAN.init` for the data bit timing configuration parameters. If timeout is 0 the message is placed in a buffer in one of three hardware diff --git a/docs/library/pyb.I2C.rst b/docs/library/pyb.I2C.rst index 2c526854aa2e..71d043aa6d4f 100644 --- a/docs/library/pyb.I2C.rst +++ b/docs/library/pyb.I2C.rst @@ -97,7 +97,7 @@ Methods errors properly) The actual clock frequency may be lower than the requested frequency. - This is dependant on the platform hardware. The actual rate may be determined + This is dependent on the platform hardware. The actual rate may be determined by printing the I2C object. .. method:: I2C.is_ready(addr) diff --git a/docs/library/random.rst b/docs/library/random.rst index dd8b47c80f08..be56eb088eae 100644 --- a/docs/library/random.rst +++ b/docs/library/random.rst @@ -24,7 +24,7 @@ This module implements a pseudo-random number generator (PRNG). .. note:: The :func:`randrange`, :func:`randint` and :func:`choice` functions are only - available if the ``MICROPY_PY_URANDOM_EXTRA_FUNCS`` configuration option is + available if the ``MICROPY_PY_RANDOM_EXTRA_FUNCS`` configuration option is enabled. @@ -73,7 +73,7 @@ Other Functions supported by the port) initialise the PRNG with a true random number (usually a hardware generated random number). - The ``None`` case only works if ``MICROPY_PY_URANDOM_SEED_INIT_FUNC`` is + The ``None`` case only works if ``MICROPY_PY_RANDOM_SEED_INIT_FUNC`` is enabled by the port, otherwise it raises ``ValueError``. .. function:: choice(sequence) diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst index d39194e6ffbe..ee16ce3c513d 100644 --- a/docs/library/rp2.StateMachine.rst +++ b/docs/library/rp2.StateMachine.rst @@ -82,11 +82,18 @@ Methods .. method:: StateMachine.exec(instr) - Execute a single PIO instruction. Uses `asm_pio_encode` to encode the - instruction from the given string *instr*. + Execute a single PIO instruction. + + If *instr* is a string then uses `asm_pio_encode` to encode the instruction + from the given string. >>> sm.exec("set(0, 1)") + If *instr* is an integer then it is treated as an already encoded PIO + machine code instruction to be executed. + + >>> sm.exec(rp2.asm_pio_encode("out(y, 8)", 0)) + .. method:: StateMachine.get(buf=None, shift=0) Pull a word from the state machine's RX FIFO. diff --git a/docs/library/ssl.rst b/docs/library/ssl.rst index 924b03b3541b..e3dfa9d99366 100644 --- a/docs/library/ssl.rst +++ b/docs/library/ssl.rst @@ -15,36 +15,53 @@ Functions .. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True) + Wrap the given *sock* and return a new wrapped-socket object. The implementation + of this function is to first create an `SSLContext` and then call the `SSLContext.wrap_socket` + method on that context object. The arguments *sock*, *server_side* and *server_hostname* are + passed through unchanged to the method call. The argument *do_handshake* is passed through as + *do_handshake_on_connect*. The remaining arguments have the following behaviour: + + - *cert_reqs* determines whether the peer (server or client) must present a valid certificate. + Note that for mbedtls based ports, ``ssl.CERT_NONE`` and ``ssl.CERT_OPTIONAL`` will not + validate any certificate, only ``ssl.CERT_REQUIRED`` will. + + - *cadata* is a bytes object containing the CA certificate chain (in DER format) that will + validate the peer's certificate. Currently only a single DER-encoded certificate is supported. + + Depending on the underlying module implementation in a particular + :term:`MicroPython port`, some or all keyword arguments above may be not supported. + +class SSLContext +---------------- + +.. class:: SSLContext(protocol, /) + + Create a new SSLContext instance. The *protocol* argument must be one of the ``PROTOCOL_*`` + constants. + +.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None) + Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type), - and returns an instance of ssl.SSLSocket, which wraps the underlying stream in - an SSL context. Returned object has the usual `stream` interface methods like + and returns an instance of ssl.SSLSocket, wrapping the underlying stream. + The returned object has the usual `stream` interface methods like ``read()``, ``write()``, etc. - A server-side SSL socket should be created from a normal socket returned from - :meth:`~socket.socket.accept()` on a non-SSL listening server socket. - - *do_handshake* determines whether the handshake is done as part of the ``wrap_socket`` + - *server_side* selects whether the wrapped socket is on the server or client side. + A server-side SSL socket should be created from a normal socket returned from + :meth:`~socket.socket.accept()` on a non-SSL listening server socket. + + - *do_handshake_on_connect* determines whether the handshake is done as part of the ``wrap_socket`` or whether it is deferred to be done as part of the initial reads or writes - (there is no ``do_handshake`` method as in CPython). For blocking sockets doing the handshake immediately is standard. For non-blocking sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode) the handshake should generally be deferred because otherwise ``wrap_socket`` blocks until it completes. Note that in AXTLS the handshake can be deferred until the first read or write but it then blocks until completion. - - *cert_reqs* determines whether the peer (server or client) must present a valid certificate. - Note that for mbedtls based ports, ``ssl.CERT_NONE`` and ``ssl.CERT_OPTIONAL`` will not - validate any certificate, only ``ssl.CERT_REQUIRED`` will. - - - *cadata* is a bytes object containing the CA certificate chain (in DER format) that will - validate the peer's certificate. Currently only a single DER-encoded certificate is supported. - - *server_hostname* is for use as a client, and sets the hostname to check against the received server certificate. It also sets the name for Server Name Indication (SNI), allowing the server to present the proper certificate. - Depending on the underlying module implementation in a particular - :term:`MicroPython port`, some or all keyword arguments above may be not supported. - .. warning:: Some implementations of ``ssl`` module do NOT validate server certificates, @@ -55,6 +72,11 @@ Functions returns an object more similar to CPython's ``SSLObject`` which does not have these socket methods. +.. attribute:: SSLContext.verify_mode + + Set or get the behaviour for verification of peer certificates. Must be one of the + ``CERT_*`` constants. + Exceptions ---------- @@ -65,8 +87,14 @@ Exceptions Constants --------- +.. data:: ssl.PROTOCOL_TLS_CLIENT + ssl.PROTOCOL_TLS_SERVER + + Supported values for the *protocol* parameter. + .. data:: ssl.CERT_NONE ssl.CERT_OPTIONAL ssl.CERT_REQUIRED - Supported values for *cert_reqs* parameter. + Supported values for *cert_reqs* parameter, and the :attr:`SSLContext.verify_mode` + attribute. diff --git a/docs/library/sys.rst b/docs/library/sys.rst index 3efdce964ce0..c8eb4b5c502b 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -46,7 +46,7 @@ Functions .. function:: settrace(tracefunc) Enable tracing of bytecode execution. For details see the `CPython - documentaion `_. + documentation `_. This function requires a custom MicroPython build as it is typically not present in pre-built firmware (due to it affecting performance). The relevant diff --git a/docs/library/time.rst b/docs/library/time.rst index 3ab5caf248c6..8c1c1d4d6fb2 100644 --- a/docs/library/time.rst +++ b/docs/library/time.rst @@ -163,8 +163,8 @@ Functions However, values returned by `ticks_ms()`, etc. functions may wrap around, so directly using subtraction on them will produce incorrect result. That is why `ticks_diff()` is needed, it implements modular (or more specifically, ring) - arithmetics to produce correct result even for wrap-around values (as long as they not - too distant inbetween, see below). The function returns **signed** value in the range + arithmetic to produce correct result even for wrap-around values (as long as they not + too distant in between, see below). The function returns **signed** value in the range [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for two's-complement signed binary integers). If the result is negative, it means that *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that @@ -183,7 +183,7 @@ Functions has passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. "Too long sleep" metaphor also maps directly to application behaviour: don't let your application run any single task for too long. Run tasks - in steps, and do time-keeping inbetween. + in steps, and do time-keeping in between. `ticks_diff()` is designed to accommodate various usage patterns, among them: diff --git a/docs/library/zephyr.DiskAccess.rst b/docs/library/zephyr.DiskAccess.rst index d19d81a962e2..3e5fa9a3575a 100644 --- a/docs/library/zephyr.DiskAccess.rst +++ b/docs/library/zephyr.DiskAccess.rst @@ -34,5 +34,5 @@ Methods These methods implement the simple and extended :ref:`block protocol ` defined by - :class:`uos.AbstractBlockDev`. + :class:`os.AbstractBlockDev`. diff --git a/docs/library/zephyr.FlashArea.rst b/docs/library/zephyr.FlashArea.rst index 306347d449ea..9cd4dd59d685 100644 --- a/docs/library/zephyr.FlashArea.rst +++ b/docs/library/zephyr.FlashArea.rst @@ -37,4 +37,4 @@ Methods These methods implement the simple and extended :ref:`block protocol ` defined by - :class:`uos.AbstractBlockDev`. + :class:`os.AbstractBlockDev`. diff --git a/docs/library/zephyr.rst b/docs/library/zephyr.rst index da3d14a093ec..10676d908528 100644 --- a/docs/library/zephyr.rst +++ b/docs/library/zephyr.rst @@ -32,7 +32,7 @@ Functions * *CPU utilization is only printed if runtime statistics are configured via the ``CONFIG_THREAD_RUNTIME_STATS`` kconfig* This function can only be accessed if ``CONFIG_THREAD_ANALYZER`` is configured for the port in ``zephyr/prj.conf``. - For more infomation, see documentation for Zephyr `thread analyzer + For more information, see documentation for Zephyr `thread analyzer `_. .. function:: shell_exec(cmd_in) diff --git a/docs/mimxrt/pinout.rst b/docs/mimxrt/pinout.rst index ef53fa63bff2..b5a7fbbfe08c 100644 --- a/docs/mimxrt/pinout.rst +++ b/docs/mimxrt/pinout.rst @@ -14,9 +14,9 @@ The pin assignment of UARTs to pins is fixed. The UARTs are numbered 0..8. The rx/tx pins are assigned according to the tables below: -================ =========== =========== =========== =========== +================= =========== =========== =========== =========== Board / Pin UART0 UART1 UART2 UART3 -================ =========== =========== =========== =========== +================= =========== =========== =========== =========== Teensy 4.0 - 0/1 7/8 14/15 Teensy 4.1 - 0/1 7/8 14/15 MIMXRT1010-EVK Debug USB D0/D1 D7/D6 - @@ -27,9 +27,10 @@ MIMXRT1050-EVKB Debug USB D0/D1 D7/D6 D8/D9 MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9 MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9 MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13 +Adafruit Metro M7 - D0/D1 D7/D3 A1/A0 Olimex RT1010Py - RxD/TxD D5/D6 - -Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07 -================ =========== =========== =========== =========== +Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07 +================= =========== =========== =========== =========== | @@ -61,38 +62,38 @@ PWM pin assignment Pins are specified in the same way as for the Pin class. The following tables show the assignment of the board Pins to PWM modules: -=========== ========== ========== ====== ============== ====== -Pin/ MIMXRT 1010 1015 1020 1050/1060/1064 1170 -=========== ========== ========== ====== ============== ====== -D0 - Q1/1 F1/1/B - - -D1 - Q1/0 F1/1/A - - -D2 F1/3/B F1/3/A - F1/3/B - -D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A -D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2 -D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B -D6 - F1/2/B F2/0/A Q3/2 F1/0/A -D7 - - F1/0/A Q3/3 - -D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3 -D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B -D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B -D11 F1/2/A - F2/1/A F1/1/A (*) - -D12 F1/2/B - F2/1/B F1/1/B (*) - -D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A -D14 F1/0/B - - F2/3/B - -D15 F1/0/A - - F2/3/A - -A0 - - F1/2/A - - -A1 F1/3/X F1/3/B F1/2/B - - -A2 F1/2/X F1/3/A F1/3/A - - -A3 - F1/2/A F1/3/B - - -A4 - - - Q3/1 - -A5 - - - Q3/0 - -D31 - - - - F1/2/B -D32 - - - - F1/2/A -D33 - - - - F1/1/B -D34 - - - - F1/1/A -D35 - - - - F1/0/B -D36 - - - - F1/0/A -=========== ========== ========== ====== ============== ====== +=========== ========== ========== ====== ========== ====== ======== +Pin/ MIMXRT 1010 1015 1020 1050/60/64 1170 Metro M7 +=========== ========== ========== ====== ========== ====== ======== +D0 - Q1/1 F1/1/B - - - +D1 - Q1/0 F1/1/A - - - +D2 F1/3/B F1/3/A - F1/3/B - - +D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A - +D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2 F1/0/B +D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B F1/0/A +D6 - F1/2/B F2/0/A Q3/2 F1/0/A - +D7 - - F1/0/A Q3/3 - - +D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3 F1/3/A +D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B F1/3/B +D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B F1/2/A +D11 F1/2/A - F2/1/A F1/1/A (*) - F1/2/B +D12 F1/2/B - F2/1/B F1/1/B (*) - F1/1/A +D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A F1/1/B +D14 F1/0/B - - F2/3/B - F1/0/B +D15 F1/0/A - - F2/3/A - F1/0/A +A0 - - F1/2/A - - - +A1 F1/3/X F1/3/B F1/2/B - - - +A2 F1/2/X F1/3/A F1/3/A - - - +A3 - F1/2/A F1/3/B - - F1/3/B +A4 - - - Q3/1 - F1/2/X +A5 - - - Q3/0 - - +D31 - - - - F1/2/B - +D32 - - - - F1/2/A - +D33 - - - - F1/1/B - +D34 - - - - F1/1/A - +D35 - - - - F1/0/B - +D36 - - - - F1/0/A - +=========== ========== ========== ====== ========== ====== ======== Pins denoted with (*) are by default not wired at the board. @@ -318,6 +319,7 @@ MIXMXRT1050-EVKB D10/-/D11/D12/D13 (*) - - MIXMXRT1060-EVK D10/-/D11/D12/D13 (*) - - MIXMXRT1064-EVK D10/-/D11/D12/D13 (*) - - MIXMXRT1170-EVK D10/-/D11/D12/D13 D28/-/D25/D24/D26 -/-/D14/D15/D24 +Adafruit Metro M7 -/-/MOSI/MISO/SCK - - Olimex RT1010Py - CS0/-/SDO/SDI/SCK SDCARD with CS1 Seeed ARCH MIX J4_12/-/J4_14/J4_13/J4_15 J3_09/J3_05/J3_08_J3_11 ================= ========================= ======================= =============== @@ -350,6 +352,7 @@ MIXMXRT1050-EVKB A4/A5 D1/D0 - - - MIXMXRT1060-EVK A4/A5 D1/D0 - - - MIXMXRT1064-EVK A4/A5 D1/D0 - - - MIXMXRT1170-EVK D14/D15 D1/D0 A4/A5 D26/D25 D19/D18 +Adafruit Metro M7 D14/D15 D0/D1 Olimex RT1010Py - SDA1/SCL1 SDA2/SCL2 - - Seeed ARCH MIX J3_17/J3_16 J4_06/J4_07 J5_05/J5_04 - - ================= =========== =========== =========== ======= ======= @@ -364,18 +367,19 @@ Hardware I2S pin assignment Pin assignments for a few MIMXRT boards: -=============== == ===== ======== ======= ======= ======== ======= ======= -Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX -=============== == ===== ======== ======= ======= ======== ======= ======= -Teensy 4.0 1 23 26 27 7 21 20 8 -Teensy 4.0 2 33 4 3 2 - - 5 -Teensy 4.1 1 23 26 27 7 21 20 8 -Teensy 4.1 2 33 4 3 2 - - 5 -Seeed Arch MIX 1 J4_09 J4_14 J4_15 J14_13 J4_11 J4_10 J4_10 -Olimex RT1010Py 1 D8 D6 D7 D4 D1 D2 D3 -Olimex RT1010Py 3 - D10 D9 D11 - - - -MIMXRT_DEV 1 "MCK" "SCK_TX" "WS_TX" "SD_TX" "SCK_RX" "WS_RX" "SD_RX" -=============== == ===== ======== ======= ======= ======== ======= ======= +================= == ===== ======== ======= ======= ======== ======= ======= +Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX +================= == ===== ======== ======= ======= ======== ======= ======= +Teensy 4.0 1 23 26 27 7 21 20 8 +Teensy 4.0 2 33 4 3 2 - - 5 +Teensy 4.1 1 23 26 27 7 21 20 8 +Teensy 4.1 2 33 4 3 2 - - 5 +Seeed Arch MIX 1 J4_09 J4_14 J4_15 J14_13 J4_11 J4_10 J4_10 +Adafruit Metro M7 1 D8 D10 D9 D12 D14 D15 D13 +Olimex RT1010Py 1 D8 D6 D7 D4 D1 D2 D3 +Olimex RT1010Py 3 - D10 D9 D11 - - - +MIMXRT_DEV 1 "MCK" "SCK_TX" "WS_TX" "SD_TX" "SCK_RX" "WS_RX" "SD_RX" +================= == ===== ======== ======= ======= ======== ======= ======= Symbolic pin names are provided for the MIMXRT_10xx_DEV boards. -These are provided for the other boards as well. \ No newline at end of file +These are provided for the other boards as well. diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst index 06f91f7f5031..ab8bf8831bbb 100644 --- a/docs/mimxrt/quickref.rst +++ b/docs/mimxrt/quickref.rst @@ -145,11 +145,12 @@ handling signal groups. :: from machine import Pin, PWM - pwm2 = PWM(Pin(2)) # create PWM object from a pin - pwm2.freq() # get current frequency - pwm2.freq(1000) # set frequency - pwm2.duty_u16() # get current duty cycle, range 0-65535 - pwm2.duty_u16(200) # set duty cycle, range 0-65535 + # create PWM object from a pin and set the frequency and duty cycle + pwm2 = PWM(Pin(2), freq=2000, duty_u16=32768) + pwm2.freq() # get the current frequency + pwm2.freq(1000) # set/change the frequency + pwm2.duty_u16() # get the current duty cycle, range 0-65535 + pwm2.duty_u16(200) # set the duty cycle, range 0-65535 pwm2.deinit() # turn off PWM on the pin # create a complementary signal pair on Pin 2 and 3 pwm2 = PWM((2, 3), freq=2000, duty_ns=20000) @@ -206,8 +207,9 @@ PWM Constructor - *align*\=value. Shortcuts for the pulse center setting, causing the pulse either at the center of the frame (value=0), the leading edge at the begin (value=1) or the trailing edge at the end of a pulse period (value=2). - - *invert*\=True|False channel_mask. Setting a bit in the mask inverts the respective channel. - Bit 0 inverts the first specified channel, bit 2 the second. The default is 0. + - *invert*\=value channel_mask. Setting a bit in the mask inverts the respective channel. + Bit 0 inverts the first specified channel, bit 1 the second. The default is 0. For a + PWM object with a single channel, True and False may be used as values. - *sync*\=True|False. If a channel of a module's submodule 0 is already active, other submodules of the same module can be forced to be synchronous to submodule 0. Their pulse period start then at at same clock cycle. The default is False. diff --git a/docs/pyboard/tutorial/usb_mouse.rst b/docs/pyboard/tutorial/usb_mouse.rst index d05b16ed5c97..31b463668fba 100644 --- a/docs/pyboard/tutorial/usb_mouse.rst +++ b/docs/pyboard/tutorial/usb_mouse.rst @@ -120,7 +120,7 @@ minus sign in front of the y-coordinate in the ``hid.send()`` line above. Restoring your pyboard to normal -------------------------------- -If you leave your pyboard as-is, it'll behave as a mouse everytime you plug +If you leave your pyboard as-is, it'll behave as a mouse every time you plug it in. You probably want to change it back to normal. To do this you need to first enter safe mode (see above), and then edit the ``boot.py`` file. In the ``boot.py`` file, comment out (put a # in front of) the line with the diff --git a/docs/reference/asm_thumb2_compare.rst b/docs/reference/asm_thumb2_compare.rst index 521af69da3b3..525819550314 100644 --- a/docs/reference/asm_thumb2_compare.rst +++ b/docs/reference/asm_thumb2_compare.rst @@ -75,7 +75,7 @@ Execute the next instruction if is true: * ite() If then else -If is true, execute the next instruction, otherwise execute the +If is true, execute the next instruction, otherwise execute the subsequent one. Thus: :: @@ -86,5 +86,5 @@ subsequent one. Thus: mov(r0, 200) # runs if r0 != r1 # execution continues here -This may be extended to control the execution of upto four subsequent instructions: it[x[y[z]]] +This may be extended to control the execution of up to four subsequent instructions: it[x[y[z]]] where x,y,z=t/e; e.g. itt, itee, itete, ittte, itttt, iteee, etc. diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst index 2bcf9f7fb793..59c375159b2c 100644 --- a/docs/reference/constrained.rst +++ b/docs/reference/constrained.rst @@ -264,7 +264,7 @@ were a string. **Runtime compiler execution** -The Python funcitons `eval` and `exec` invoke the compiler at runtime, which +The Python functions `eval` and `exec` invoke the compiler at runtime, which requires significant amounts of RAM. Note that the ``pickle`` library from `micropython-lib` employs `exec`. It may be more RAM efficient to use the `json` library for object serialisation. @@ -403,7 +403,7 @@ Control of garbage collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A GC can be demanded at any time by issuing `gc.collect()`. It is advantageous -to do this at intervals, firstly to pre-empt fragmentation and secondly for +to do this at intervals, firstly to preempt fragmentation and secondly for performance. A GC can take several milliseconds but is quicker when there is little work to do (about 1ms on the Pyboard). An explicit call can minimise that delay while ensuring it occurs at points in the program when it is acceptable. diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index 74524b22fd4c..d039bf7132f3 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -120,7 +120,7 @@ Glossary `_ which provides implementations for many modules from CPython's standard library. - Some of the modules are are implemented in pure Python, and are able to + Some of the modules are implemented in pure Python, and are able to be used on all ports. However, the majority of these modules use :term:`FFI` to access operating system functionality, and as such can only be used on the :term:`MicroPython Unix port` (with limited support diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst index bdb838c59058..ea330acad3aa 100644 --- a/docs/reference/isr_rules.rst +++ b/docs/reference/isr_rules.rst @@ -219,20 +219,20 @@ Exceptions If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the exception is handled by the ISR code. -Interfacing to uasyncio ------------------------ +Interfacing to asyncio +---------------------- -When an ISR runs it can preempt the `uasyncio` scheduler. If the ISR performs a `uasyncio` +When an ISR runs it can preempt the `asyncio` scheduler. If the ISR performs a `asyncio` operation the scheduler's operation can be disrupted. This applies whether the interrupt is hard or soft and also applies if the ISR has passed execution to another function via `micropython.schedule`. In particular creating or cancelling tasks is invalid in an ISR context. -The safe way to interact with `uasyncio` is to implement a coroutine with synchronisation performed by -`uasyncio.ThreadSafeFlag`. The following fragment illustrates the creation of a task in response +The safe way to interact with `asyncio` is to implement a coroutine with synchronisation performed by +`asyncio.ThreadSafeFlag`. The following fragment illustrates the creation of a task in response to an interrupt: .. code:: python - tsf = uasyncio.ThreadSafeFlag() + tsf = asyncio.ThreadSafeFlag() def isr(_): # Interrupt handler tsf.set() @@ -240,7 +240,7 @@ to an interrupt: async def foo(): while True: await tsf.wait() - uasyncio.create_task(bar()) + asyncio.create_task(bar()) In this example there will be a variable amount of latency between the execution of the ISR and the execution of ``foo()``. This is inherent to cooperative scheduling. The maximum latency is application diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index 3225fc5f244b..b82672536025 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -4,46 +4,88 @@ MicroPython remote control: mpremote ==================================== The ``mpremote`` command line tool provides an integrated set of utilities to -remotely interact with and automate a MicroPython device over a serial -connection. +remotely interact with, manage the filesystem on, and automate a MicroPython +device over a serial connection. -To use mpremote install it via ``pip``: +To use mpremote, first install it via ``pip``: .. code-block:: bash - $ pip install mpremote + $ pip install --user mpremote + +Or via `pipx `_: + +.. code-block:: bash + + $ pipx install mpremote The simplest way to use this tool is just by invoking it without any arguments: .. code-block:: bash - mpremote + $ mpremote This command automatically detects and connects to the first available USB -serial device and provides an interactive REPL. Serial ports are opened in -exclusive mode, so running a second (or third, etc) instance of ``mpremote`` -will connect to subsequent serial devices, if any are available. +serial device and provides an interactive terminal that you can use to access +the REPL and your program's output. Serial ports are opened in exclusive mode, +so running a second (or third, etc) instance of ``mpremote`` will connect to +subsequent serial devices, if any are available. + +Additionally ``pipx`` also allows you to directly run ``mpremote`` without +installing first: + +.. code-block:: bash + $ pipx run mpremote ...args Commands -------- -For REPL access, running ``mpremote`` without any arguments is usually all that -is needed. ``mpremote`` also supports a set of commands given at the command -line which will perform various actions on remote MicroPython devices. +``mpremote`` supports being given a series of commands given at the command line +which will perform various actions in sequence on a remote MicroPython device. +See the :ref:`examples section ` below to get an idea of how +this works and for some common combinations of commands. -For commands that support multiple arguments (e.g. a list of files), the -argument list can be terminated with ``+``. +Each command is of the form `` [--options] [args...]``. For commands +that support multiple arguments (e.g. a list of files), the argument list can +be terminated with ``+``. -The full list of supported commands are: +If no command is specified, the default command is ``repl``. Additionally, if +any command needs to access the device, and no earlier ``connect`` has been +specified, then an implicit ``connect auto`` is added. -- connect to a specified device via a device-name shortcut: +In order to get the device into a known state for any action command +(except ``repl``), once connected ``mpremote`` will stop any running program +and soft-reset the device before running the first command. You can control +this behavior using the ``resume`` and ``soft-reset`` commands. +See :ref:`auto-connection and auto-soft-reset ` for more details. - .. code-block:: bash +Multiple commands can be specified and they will be run sequentially. - $ mpremote +The full list of supported commands are: -- connect to specified device via name: +- `connect ` +- `disconnect ` +- `resume ` +- `soft_reset ` +- `repl ` +- `eval ` +- `exec ` +- `run ` +- `fs ` +- `df ` +- `edit ` +- `mip ` +- `mount ` +- `unmount ` +- `rtc ` +- `sleep ` +- `reset ` +- `bootloader ` + +.. _mpremote_command_connect: + +- **connect** -- connect to specified device via name: .. code-block:: bash @@ -54,88 +96,182 @@ The full list of supported commands are: - ``list``: list available devices - ``auto``: connect to the first available USB serial port - ``id:``: connect to the device with USB serial number - ```` (the second entry in the output from the ``connect list`` - command) - - ``port:``: connect to the device with the given path + ```` (the second column from the ``connect list`` + command output) + - ``port:``: connect to the device with the given path (the first column + from the ``connect list`` command output - any valid device name/path, to connect to that device -- disconnect current device: + **Note:** Instead of using the ``connect`` command, there are several + :ref:`pre-defined shortcuts ` for common device paths. For + example the ``a0`` shortcut command is equivalent to + ``connect /dev/ttyACM0`` (Linux), or ``c0`` for ``COM0`` (Windows). + + **Note:** The ``auto`` option will only detect USB serial ports, i.e. a serial + port that has an associated USB VID/PID (i.e. CDC/ACM or FTDI-style + devices). Other types of serial ports + +.. _mpremote_command_disconnect: + +- **disconnect** -- disconnect current device: .. code-block:: bash $ mpremote disconnect - After a disconnect, auto soft-reset is enabled. + After a disconnect, :ref:`auto-soft-reset ` is enabled. + +.. _mpremote_command_resume: -- resume a previous ``mpremote`` session: +- **resume** -- maintain existing interpreter state for subsequent commands: .. code-block:: bash $ mpremote resume - This disables auto soft-reset. + This disables :ref:`auto-soft-reset `. This is useful if you + want to run a subsequent command on a board without first soft-resetting it. -- perform a soft-reset of the device: +.. _mpremote_command_soft_reset: + +- **soft-reset** -- perform a soft-reset of the device: .. code-block:: bash $ mpremote soft-reset This will clear out the Python heap and restart the interpreter. It also - disables auto soft-reset. + prevents the subsequent command from triggering :ref:`auto-soft-reset `. + +.. _mpremote_command_repl: -- enter the REPL on the connected device: +- **repl** -- enter the REPL on the connected device: .. code-block:: bash - $ mpremote repl [options] + $ mpremote repl [--options] Options are: + - ``--escape-non-printable``, to print non-printable bytes/characters as their hex code - ``--capture ``, to capture output of the REPL session to the given file - ``--inject-code ``, to specify characters to inject at the REPL when - Ctrl-J is pressed + ``Ctrl-J`` is pressed. This allows you to automate a common command. - ``--inject-file ``, to specify a file to inject at the REPL when - Ctrl-K is pressed + ``Ctrl-K`` is pressed. This allows you to run a file (e.g. containing some + useful setup code, or even the program you are currently working on). + + While the ``repl`` command running, you can use ``Ctrl-]`` or ``Ctrl-x`` to + exit. -- evaluate and print the result of a Python expression: + **Note:** The name "REPL" here reflects that the common usage of this command + to access the Read Eval Print Loop that is running on the MicroPython + device. Strictly, the ``repl`` command is just functioning as a terminal + (or "serial monitor") to access the device. Because this command does not + trigger the :ref:`auto-reset behavior `, this means that if + a program is currently running, you will first need to interrupt it with + ``Ctrl-C`` to get to the REPL, which will then allow you to access program + state. You can also use ``mpremote soft-reset repl`` to get a "clean" REPL + with all program state cleared. + +.. _mpremote_command_eval: + +- **eval** -- evaluate and print the result of a Python expression: .. code-block:: bash $ mpremote eval -- execute the given Python code: +.. _mpremote_command_exec: + +- **exec** -- execute the given Python code: .. code-block:: bash $ mpremote exec -- run a script from the local filesystem: + By default, ``mpremote exec`` will display any output from the expression until it + terminates. The ``--no-follow`` flag can be specified to return immediately and leave + the device running the expression in the background. + +.. _mpremote_command_run: + +- **run** -- run a script from the local filesystem: .. code-block:: bash - $ mpremote run + $ mpremote run + + This will execute the file directly from RAM on the device without copying it + to the filesystem. This is a very useful way to iterate on the development of + a single piece of code without having to worry about deploying it to the + filesystem. -- execute filesystem commands on the device: + By default, ``mpremote run`` will display any output from the script until it + terminates. The ``--no-follow`` flag can be specified to return immediately and leave + the device running the script in the background. + +.. _mpremote_command_fs: + +- **fs** -- execute filesystem commands on the device: .. code-block:: bash - $ mpremote fs + $ mpremote fs - ```` may be: + ```` may be: - ``cat `` to show the contents of a file or files on the device - ``ls`` to list the current directory - ``ls `` to list the given directories - - ``cp [-r] `` to copy files; use ":" as a prefix to specify - a file on the device + - ``cp [-r] `` to copy files - ``rm `` to remove files on the device - ``mkdir `` to create directories on the device - ``rmdir `` to remove directories on the device - ``touch `` to create the files (if they don't already exist) -- edit a file on the device: + The ``cp`` command uses a convention where a leading ``:`` represents a remote + path. Without a leading ``:`` means a local path. This is based on the + convention used by the `Secure Copy Protocol (scp) client + `_. All other commands + implicitly assume the path is a remote path, but the ``:`` can be optionally + used for clarity. + + So for example, ``mpremote fs cp main.py :main.py`` copies ``main.py`` from + the current local directory to the remote filesystem, whereas + ``mpremote fs cp :main.py main.py`` copies ``main.py`` from the device back + to the current directory. + + All of the filesystem sub-commands take multiple path arguments, so if there + is another command in the sequence, you must use ``+`` to terminate the + arguments, e.g. + + .. code-block:: bash + + $ mpremote fs cp main.py :main.py + repl + + This will copy the file to the device then enter the REPL. The ``+`` prevents + ``"repl"`` being interpreted as a path. + + **Note:** For convenience, all of the filesystem sub-commands are also + :ref:`aliased as regular commands `, i.e. you can write + ``mpremote cp ...`` instead of ``mpremote fs cp ...``. + +.. _mpremote_command_df: + +- **df** -- query device free/used space + + .. code-block:: bash + + $ mpremote df + + The ``df`` command will print size/used/free statistics for the device + filesystem, similar to the Unix ``df`` command. + +.. _mpremote_command_edit: + +- **edit** -- edit a file on the device: .. code-block:: bash @@ -146,7 +282,9 @@ The full list of supported commands are: variable ``$EDITOR``). If the editor exits successfully, the updated file will be copied back to the device. -- install packages from :term:`micropython-lib` (or GitHub) using the ``mip`` tool: +.. _mpremote_command_mip: + +- **mip** -- install packages from :term:`micropython-lib` (or GitHub) using the ``mip`` tool: .. code-block:: bash @@ -154,16 +292,34 @@ The full list of supported commands are: See :ref:`packages` for more information. -- mount the local directory on the remote device: +.. _mpremote_command_mount: + +- **mount** -- mount the local directory on the remote device: .. code-block:: bash $ mpremote mount [options] - During usage, Ctrl-D will soft-reboot and normally reconnect the mount automatically. - If the unit has a main.py running at startup however the remount cannot occur. - In this case a raw mode soft reboot can be used: Ctrl-A Ctrl-D to reboot, - then Ctrl-B to get back to normal repl at which point the mount will be ready. + This allows the remote device to see the local host directory as if it were + its own filesystem. This is useful for development, and avoids the need to + copy files to the device while you are working on them. + + The device installs a filesystem driver, which is then mounted in the + :ref:`device VFS ` as ``/remote``, which uses the serial + connection to ``mpremote`` as a side-channel to access files. The device + will have its current working directory (via ``os.chdir``) set to + ``/remote`` so that imports and file access will occur there instead of the + default filesystem path while the mount is active. + + **Note:** If the ``mount`` command is not followed by another action in the + sequence, a ``repl`` command will be implicitly added to the end of the + sequence. + + During usage, Ctrl-D will trigger a soft-reset as normal, but the mount will + automatically be re-connected. If the unit has a main.py running at startup + however the remount cannot occur. In this case a raw mode soft reboot can be + used: Ctrl-A Ctrl-D to reboot, then Ctrl-B to get back to normal repl at + which point the mount will be ready. Options are: @@ -172,22 +328,74 @@ The full list of supported commands are: local directory that is mounted. This option disables this check for symbolic links, allowing the device to follow symbolic links outside of the local directory. -- unmount the local directory from the remote device: +.. _mpremote_command_unmount: + +- **unmount** -- unmount the local directory from the remote device: .. code-block:: bash $ mpremote umount -Multiple commands can be specified and they will be run sequentially. + This happens automatically when ``mpremote`` terminates, but it can be used + in a sequence to unmount an earlier mount before subsequent command are run. + +.. _mpremote_command_rtc: + +- **rtc** -- set/get the device clock (RTC): + + .. code-block:: bash + + $ mpremote rtc + + This will query the device RTC for the current time and print it as a datetime + tuple. + + .. code-block:: bash + + $ mpremote rtc --set + + This will set the device RTC to the host PC's current time. + +.. _mpremote_command_sleep: + +- **sleep** -- sleep (delay) before executing the next command + + .. code-block:: bash + + $ mpremote sleep 0.5 + + This will pause execution of the command sequence for the specified duration + in seconds, e.g. to wait for the device to do something. + +.. _mpremote_command_reset: + +- **reset** -- hard reset the device + + .. code-block:: bash + + $ mpremote reset + + **Note:** hard reset is equivalent to :func:`machine.reset`. +.. _mpremote_command_bootloader: + +- **bootloader** enter the bootloader + + .. code-block:: bash + + $ mpremote bootloader + + This will make the device enter its bootloader. The bootloader is port- and + board-specific (e.g. DFU on stm32, UF2 on rp2040/Pico). + +.. _mpremote_reset: Auto connection and soft-reset ------------------------------ Connection and disconnection will be done automatically at the start and end of the execution of the tool, if such commands are not explicitly given. Automatic -connection will search for the first available USB serial device. If no action -is specified then the REPL will be entered. +connection will search for the first available USB serial device. Once connected to a device, ``mpremote`` will automatically soft-reset the device if needed. This clears the Python heap and restarts the interpreter, @@ -197,38 +405,60 @@ executed: ``mount``, ``eval``, ``exec``, ``run``, ``fs``. After doing a soft-reset for the first time, it will not be done again automatically, until a ``disconnect`` command is issued. -Auto soft-reset behaviour can be controlled by the ``resume`` command. And the -``soft-reset`` command can be used to perform an explicit soft reset. +Auto-soft-reset behaviour can be controlled by the ``resume`` command. This +might be useful to use the ``eval`` command to inspect the state of of the +device. The ``soft-reset`` command can be used to perform an explicit soft +reset in the middle of a sequence of commands. +.. _mpremote_shortcuts: Shortcuts --------- -Shortcuts can be defined using the macro system. Built-in shortcuts are:: +Shortcuts can be defined using the macro system. Built-in shortcuts are: -- ``devs``: list available devices (shortcut for ``connect list``) +- ``devs``: Alias for ``connect list`` -- ``a0``, ``a1``, ``a2``, ``a3``: connect to /dev/ttyACM? +- ``a0``, ``a1``, ``a2``, ``a3``: Aliases for ``connect /dev/ttyACMn`` -- ``u0``, ``u1``, ``u2``, ``u3``: connect to /dev/ttyUSB? +- ``u0``, ``u1``, ``u2``, ``u3``: Aliases for ``connect /dev/ttyUSBn`` -- ``c0``, ``c1``, ``c2``, ``c3``: connect to COM? +- ``c0``, ``c1``, ``c2``, ``c3``: Aliases for ``connect COMn`` -- ``cat``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``touch``, ``df``: - filesystem commands +- ``cat``, ``edit``, ``ls``, ``cp``, ``rm``, ``mkdir``, ``rmdir``, ``touch``: Aliases for ``fs `` -- ``reset``: reset the device +Additional shortcuts can be defined by in user-configuration files, which is +located at ``.config/mpremote/config.py``. This file should define a +dictionary named ``commands``. The keys of this dictionary are the shortcuts +and the values are either a string or a list-of-strings: -- ``bootloader``: make the device enter its bootloader +.. code-block:: python3 + + "c33": "connect id:334D335C3138", -Any user configuration, including user-defined shortcuts, can be placed in the file -``.config/mpremote/config.py``. For example: +The command ``c33`` is replaced by ``connect id:334D335C3138``. + +.. code-block:: python3 + + "test": ["mount", ".", "exec", "import test"], + +The command ``test`` is replaced by ``mount . exec "import test"``. + +Shortcuts can also accept arguments. For example: + +.. code-block:: python3 + + "multiply x=4 y=7": "eval x*y", + +Running ``mpremote times 3 7`` will set ``x`` and ``y`` as variables on the device, then evaluate the expression ``x*y``. + +An example ``config.py`` might look like: .. code-block:: python3 commands = { - "c33": "connect id:334D335C3138", - "bl": "bootloader", + "c33": "connect id:334D335C3138", # Connect to a specific device by ID. + "bl": "bootloader", # Shorter alias for bootloader. "double x=4": "eval x*2", # x is an argument, with default 4 "wl_scan": ["exec", """ import network @@ -236,10 +466,16 @@ Any user configuration, including user-defined shortcuts, can be placed in the f wl.active(1) for ap in wl.scan(): print(ap) - """,], - "test": ["mount", ".", "exec", "import test"], + """,], # Print out nearby WiFi networks. + "wl_ifconfig": [ + "exec", + "import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ifconfig())", + """,], # Print ip address of station interface. + "test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py. + "demo": ["run", "path/to/demo.py"], # Execute demo.py on the device. } +.. _mpremote_examples: Examples -------- @@ -248,38 +484,205 @@ Examples mpremote +Connect to the first available device and implicitly run the ``repl`` command. + +.. code-block:: bash + mpremote a1 - mpremote connect /dev/ttyUSB0 repl +Connect to the device at ``/dev/ttyACM1`` (Linux) and implicitly run the +``repl`` command. See :ref:`shortcuts ` above. + +.. code-block:: bash + + mpremote c1 + +Connect to the device at ``COM1`` (Windows) and implicitly run the ``repl`` +command. See :ref:`shortcuts ` above. + +.. code-block:: bash + + mpremote connect /dev/ttyUSB0 + +Explicitly specify which device to connect to, and as above, implicitly run the +``repl`` command. - mpremote ls +.. code-block:: bash mpremote a1 ls +Connect to the device at ``/dev/ttyACM0`` and then run the ``ls`` command. + +It is equivalent to ``mpremote connect /dev/ttyACM1 fs ls``. + +.. code-block:: bash + mpremote exec "import micropython; micropython.mem_info()" +Run the specified Python command and display any output. This is equivalent to +typing the command at the REPL prompt. + +.. code-block:: bash + mpremote eval 1/2 eval 3/4 +Evaluate each expression in turn and print the results. + +.. code-block:: bash + + mpremote a0 eval 1/2 a1 eval 3/4 + +Evaluate ``1/2`` on the device at ``/dev/ttyACM0``, then ``3/4`` on the +device at ``/dev/ttyACM1``, printing each result. + +.. code-block:: bash + + mpremote resume exec "print_state_info()" soft-reset + +Connect to the device without triggering a soft reset and execute the +``print_state_info()`` function (e.g. to find out information about the current +program state), then trigger a soft reset. + +.. code-block:: bash + + mpremote reset sleep 0.5 bootloader + +Hard-reset the device, wait 500ms for it to become available, then enter the +bootloader. + +.. code-block:: bash + + mpremote cp utils/driver.py :utils/driver.py + run test.py + +Update the copy of utils/driver.py on the device, then execute the local +``test.py`` script on the device. ``test.py`` is never copied to the device +filesystem, rather it is run from RAM. + +.. code-block:: bash + + mpremote cp utils/driver.py :utils/driver.py + exec "import app" + +Update the copy of utils/driver.py on the device, then execute app.py on the +device. + +This is a common development workflow to update a single file and then re-start +your program. In this scenario, your ``main.py`` on the device would also do +``import app``. + +.. code-block:: bash + + mpremote cp utils/driver.py :utils/driver.py + soft-reset repl + +Update the copy of utils/driver.py on the device, then trigger a soft-reset to +restart your program, and then monitor the output via the ``repl`` command. + +.. code-block:: bash + + mpremote cp -r utils/ :utils/ + soft-reset repl + +Same as above, but update the entire utils directory first. + +.. code-block:: bash + mpremote mount . - mpremote mount . exec "import local_script" +Mount the current local directory at ``/remote`` on the device and starts a +``repl`` session which will use ``/remote`` as the working directory. - mpremote ls +.. code-block:: bash + + mpremote mount . exec "import demo" + +After mounting the current local directory, executes ``demo.py`` from the +mounted directory. + +.. code-block:: bash + + mpremote mount app run test.py + +After mounting the local directory ``app`` as ``/remote`` on the device, +executes the local ``test.py`` from the host's current directory without +copying it to the filesystem. + +.. code-block:: bash + + mpremote mount . repl --inject-code "import demo" + +After mounting the current local directory, executes ``demo.py`` from the +mounted directory each time ``Ctrl-J`` is pressed. + +You will first need to press ``Ctrl-D`` to reset the interpreter state +(which will preserve the mount) before pressing ``Ctrl-J`` to re-import +``demo.py``. + +.. code-block:: bash + + mpremote mount app repl --inject-file demo.py + +Same as above, but executes the contents of the local file demo.py at the REPL +every time ``Ctrl-K`` is pressed. As above, use Ctrl-D to reset the interpreter +state first. + +.. code-block:: bash mpremote cat boot.py +Displays the contents of ``boot.py`` on the device. + +.. code-block:: bash + + mpremote edit utils/driver.py + +Edit ``utils/driver.py`` on the device using your local ``$EDITOR``. + +.. code-block:: bash + mpremote cp :main.py . +Copy ``main.py`` from the device to the local directory. + +.. code-block:: bash + mpremote cp main.py : +Copy ``main.py`` from the local directory to the device. + +.. code-block:: bash + mpremote cp :a.py :b.py +Copy ``a.py`` on the device to ``b.py`` on the device. + +.. code-block:: bash + mpremote cp -r dir/ : +Recursively copy the local directory ``dir`` to the remote device. + +.. code-block:: bash + mpremote cp a.py b.py : + repl +Copy ``a.py`` and ``b.py`` from the local directory to the device, then run the +``repl`` command. + +.. code-block:: bash + mpremote mip install aioble +Install the ``aioble`` package from :term:`micropython-lib` to the device. +See :ref:`packages`. + +.. code-block:: bash + mpremote mip install github:org/repo@branch +Install the package from the specified branch at org/repo on GitHub to the +device. See :ref:`packages`. + +.. code-block:: bash + mpremote mip install --target /flash/third-party functools + +Install the ``functools`` package from :term:`micropython-lib` to the +``/flash/third-party`` directory on the device. See :ref:`packages`. diff --git a/docs/reference/mpyfiles.rst b/docs/reference/mpyfiles.rst index d93a86383e98..1588eda57090 100644 --- a/docs/reference/mpyfiles.rst +++ b/docs/reference/mpyfiles.rst @@ -86,7 +86,8 @@ and .mpy version. =================== ============ MicroPython release .mpy version =================== ============ -v1.19 and up 6 +v1.20 and up 6.1 +v1.19.x 6 v1.12 - v1.18 5 v1.11 4 v1.9.3 - v1.10 3 @@ -100,6 +101,7 @@ MicroPython repository at which the .mpy version was changed. =================== ======================================== .mpy version change Git commit =================== ======================================== +6 to 6.1 d94141e1473aebae0d3c63aeaa8397651ad6fa01 5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5 4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517 3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e @@ -146,8 +148,8 @@ The .mpy header is: size field ====== ================================ byte value 0x4d (ASCII 'M') -byte .mpy version number -byte feature flags +byte .mpy major version number +byte native arch and minor version number (was feature flags in older versions) byte number of bits in a small int ====== ================================ diff --git a/docs/reference/packages.rst b/docs/reference/packages.rst index 1ddbecb582b4..c9deedea771c 100644 --- a/docs/reference/packages.rst +++ b/docs/reference/packages.rst @@ -53,7 +53,7 @@ can be downloaded by specifying the path to their ``package.json``. If no json file is specified, then "package.json" is implicitly added:: >>> mip.install("http://example.com/x/") - >>> mip.install("github:org/repo") + >>> mip.install("github:org/repo") # Uses default branch of that repo >>> mip.install("github:org/repo", version="branch-or-tag") @@ -108,9 +108,9 @@ https://github.com/micropython/micropython-lib for more information. To write a "self-hosted" package that can be downloaded by ``mip`` or ``mpremote``, you need a static webserver (or GitHub) to host either a -single .py file, or a package.json file alongside your .py files. +single .py file, or a ``package.json`` file alongside your .py files. -A typical package.json for an example ``mlx90640`` library looks like:: +A typical ``package.json`` for an example ``mlx90640`` library looks like:: { "urls": [ @@ -119,7 +119,8 @@ A typical package.json for an example ``mlx90640`` library looks like:: ], "deps": [ ["collections-defaultdict", "latest"], - ["os-path", "latest"] + ["os-path", "latest"], + ["github:org/micropython-additions", "main"] ], "version": "0.2" } @@ -127,7 +128,9 @@ A typical package.json for an example ``mlx90640`` library looks like:: This includes two files, hosted at a GitHub repo named ``org/micropython-mlx90640``, which install into the ``mlx90640`` directory on the device. It depends on ``collections-defaultdict`` and ``os-path`` which will -be installed automatically. +be installed automatically from the :term:`micropython-lib`. The third +dependency installs the content as defined by the ``package.json`` file of the +``main`` branch of the GitHub repo ``org/micropython-additions``. Freezing packages ----------------- diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index 834a53b0a7d7..0c68dd60bded 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -247,7 +247,6 @@ Python will interpret the result as 2**32 -1 rather than as -1. In addition to the restrictions imposed by the native emitter the following constraints apply: -* Functions may have up to four arguments. * Default argument values are not permitted. * Floating point may be used but is not optimised. diff --git a/docs/renesas-ra/general.rst b/docs/renesas-ra/general.rst index c8eea53f8bce..59bc2ef2062e 100644 --- a/docs/renesas-ra/general.rst +++ b/docs/renesas-ra/general.rst @@ -18,7 +18,7 @@ The following boards are officially supported. * RA4M1-CLICKER -For the manual and other references for the board and RA Family MCU, please refer to the web page: `EK-RA4M1 CLICKER `_ +For the manual and other references for the board and RA Family MCU, please refer to the web page: `RA4M1 CLICKER `_ * EK-RA6M2 diff --git a/docs/renesas-ra/tutorial/intro.rst b/docs/renesas-ra/tutorial/intro.rst index 6c41f43971cd..6003e7157553 100644 --- a/docs/renesas-ra/tutorial/intro.rst +++ b/docs/renesas-ra/tutorial/intro.rst @@ -62,6 +62,6 @@ Access the MicroPython REPL (the Python prompt) via USB serial or UART with 1152 You can see the MicroPython REPL prompt like below:: - MicroPython v1.18-293-g339aa09b8-dirty on 2022-03-26; RA6M2_EK with RA6M2 + MicroPython v1.20.0 on 2023-04-27; EK-RA6M2 with RA6M2 Type "help()" for more information. >>> diff --git a/docs/renesas-ra/tutorial/using_peripheral.rst b/docs/renesas-ra/tutorial/using_peripheral.rst index c50181b3d681..7296d8b3304f 100644 --- a/docs/renesas-ra/tutorial/using_peripheral.rst +++ b/docs/renesas-ra/tutorial/using_peripheral.rst @@ -12,9 +12,8 @@ To list supported modules, please enter:: help('modules') -Especially `machine` module and class :ref:`machine.Pin ` are very important for using -peripherals. Note that prefix 'u' is added to the module for MicroPython, -so you can see "umachine" in the list but you can use it like "import machine". +Especially `machine` module and class :ref:`machine.Pin ` are very +important for using peripherals. Using "from machine import Pin", Pin name is available corresponding to the RA MCU's pin name which are Pin.cpu.P000 and 'P000'. diff --git a/docs/rp2/general.rst b/docs/rp2/general.rst index 6a8958d172a8..05b44f051ee3 100644 --- a/docs/rp2/general.rst +++ b/docs/rp2/general.rst @@ -30,7 +30,7 @@ The peripherals include: * 2 UARTs * 2 SPI controllers -* 2 I2C contollers +* 2 I2C controllers * 16 PWM channels * USB 1.1 controller * 8 PIO state machines diff --git a/docs/rp2/quickref.rst b/docs/rp2/quickref.rst index 430c130c6e86..11a808c11027 100644 --- a/docs/rp2/quickref.rst +++ b/docs/rp2/quickref.rst @@ -96,7 +96,7 @@ Programmable IO (PIO) --------------------- PIO is useful to build low-level IO interfaces from scratch. See the :mod:`rp2` module -for detailed explaination of the assembly instructions. +for detailed explanation of the assembly instructions. Example using PIO to blink an LED at 1Hz:: @@ -146,19 +146,30 @@ See :ref:`machine.UART `. :: PWM (pulse width modulation) ---------------------------- -There are 8 independent channels each of which have 2 outputs making it 16 -PWM channels in total which can be clocked from 7Hz to 125Mhz. +There are 8 independent PWM generators called slices, which each have two +channels making it 16 PWM channels in total which can be clocked from +8Hz to 62.5Mhz at a machine.freq() of 125Mhz. The two channels of a +slice run at the same frequency, but can have a different duty rate. +The two channels are usually assigned to adjacent GPIO pin pairs with +even/odd numbers. So GPIO0 and GPIO1 are at slice 0, GPIO2 and GPIO3 +are at slice 1, and so on. A certain channel can be assigned to +different GPIO pins (see Pinout). For instance slice 0, channel A can be assigned +to both GPIO0 and GPIO16. Use the ``machine.PWM`` class:: from machine import Pin, PWM - pwm0 = PWM(Pin(0)) # create PWM object from a pin - pwm0.freq() # get current frequency - pwm0.freq(1000) # set frequency - pwm0.duty_u16() # get current duty cycle, range 0-65535 - pwm0.duty_u16(200) # set duty cycle, range 0-65535 - pwm0.deinit() # turn off PWM on the pin + # create PWM object from a pin and set the frequency of slice 0 + # and duty cycle for channel A + pwm0 = PWM(Pin(0), freq=2000, duty_u16=32768) + pwm0.freq() # get the current frequency of slice 0 + pwm0.freq(1000) # set/change the frequency of slice 0 + pwm0.duty_u16() # get the current duty cycle of channel A, range 0-65535 + pwm0.duty_u16(200) # set the duty cycle of channel A, range 0-65535 + pwm0.duty_u16(0) # stop the output at channel A + print(pwm0) # show the properties of the PWM object. + pwm0.deinit() # turn off PWM of slice 0, stopping channels A and B ADC (analog to digital conversion) ---------------------------------- diff --git a/docs/samd/pinout.rst b/docs/samd/pinout.rst index 46d9d7a29d1b..5fe1e14ecb37 100644 --- a/docs/samd/pinout.rst +++ b/docs/samd/pinout.rst @@ -83,7 +83,9 @@ Examples for Adafruit ItsyBitsy M0 Express: - uart 4 at pins D2/D5 - uart 5 at pins SCL/SDA -or other combinations. +or other combinations. For hardware flow control, tx must be at pad 0, rx at pad 1, +rts at pad 2 and cts at pad 3. This applies for instance to +UART 3 or UART 1 at the pins D13/D11/D10/D12 for rx/tx/rts/cts. SAMD21 I2C assignments `````````````````````` @@ -105,7 +107,7 @@ or other combinations. SAMD21 SPI assignments `````````````````````` -The I2C devices and signals must be chosen according to the following rules: +The SPI devices and signals must be chosen according to the following rules: - The following pad number pairs are suitable for MOSI/SCK: 0/1, 2/3, 3/1, and 0/3. - The MISO signal must be at a Pin with a different pad number than MOSI or SCK. @@ -158,14 +160,14 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 22 PA22 D13 6 - - 3/0 5/1 4/0 1/6 0/2 34 PB02 DOTSTAR_CLK 2 14 - - 5/0 6/0 2/2 - 35 PB03 DOTSTAR_DATA 9 15 - - 5/1 6/1 - - - 43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1 - 11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7 - 9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5 - 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 - 42 PB10 FLASH_SCK 10 - - - 4/2 5/0 0/4 1/0 - 10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6 55 PB23 MISO 7 - - 1/3 5/3 7/1 - - 0 PA00 MOSI 0 - - - 1/0 2/0 - - + 43 PB11 QSPI_CS 12 - - - 4/3 5/1 0/5 1/1 + 8 PA08 QSPI_D0 - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 QSPI_D1 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 QSPI_D2 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 QSPI_D3 11 11 - 0/3 2/3 1/1 0/3 1/7 + 42 PB10 QSPI_SCK 10 - - - 4/2 5/0 0/4 1/0 1 PA01 SCK 1 - - - 1/1 2/1 - - 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 @@ -214,7 +216,9 @@ Examples for Adafruit ItsyBitsy 4 Express: - uart 4 at pins SDA/SCL - uart 5 at pins D12/D13 -or other combinations. +or other combinations. For hardware flow control, tx must be at pad 0, rx at pad 1, +rts at pad 2 and cts at pad 3. This applies for instance to +UART 5 at the pins D12/D13/D10/D11 for rx/tx/rts/cts. SAMD51 I2C assignments `````````````````````` @@ -284,15 +288,15 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 21 PA21 D11 5 - - 5/3 3/3 7/1 1/5 0/1 22 PA22 D12 6 - - 3/0 5/1 4/0 1/6 0/2 23 PA23 D13 7 - - 3/1 5/0 4/1 1/7 0/3 - 43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1 - 11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7 - 9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5 - 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 - 42 PB10 FLASH_SCK 10 - - - 4/2 5/0 0/4 1/0 - 10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6 54 PB22 MISO 22 - - 1/2 5/2 7/0 - - 55 PB23 MOSI 7 - - 1/3 5/3 7/1 - - 35 PB03 NEOPIXEL 9 15 - - 5/1 6/1 - - + 43 PB11 QSPI_CS 12 - - - 4/3 5/1 0/5 1/1 + 8 PA08 QSPI_D0 - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 QSPI_D1 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 QSPI_D2 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 QSPI_D3 11 11 - 0/3 2/3 1/1 0/3 1/7 + 42 PB10 QSPI_SCK 10 - - - 4/2 5/0 0/4 1/0 17 PA17 SCK 1 - - 1/1 3/0 2/1 1/1 0/5 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 @@ -330,6 +334,75 @@ The default devices at the board are: - SPI 1 at pins PA23/PA22/PA17, labelled MOSI, MISO and SCK - DAC output on pins PA02 and PA05, labelled A0 and A1 +Adafruit Metro M4 Airlift pin assignment table +---------------------------------------------- + +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== +Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + 2 PA02 A0 2 0 - - - - - - + 5 PA05 A1 5 5 - - 0/1 0/1 - - + 6 PA06 A2 6 6 - - 0/2 1/0 - - + 32 PB00 A3 9 12 - - 5/2 7/0 - - + 40 PB08 A4 8 2 0 - 4/0 4/0 - - + 41 PB09 A5 9 3 1 - 4/1 4/1 - - + 23 PA23 D0 7 - - 3/1 5/0 4/1 1/7 0/3 + 22 PA22 D1 6 - - 3/0 5/1 4/0 1/6 0/2 + 49 PB17 D2 1 - - 5/1 - 6/1 3/1 0/5 + 48 PB16 D3 0 - - 5/0 - 6/0 3/0 0/4 + 45 PB13 D4 13 - - 4/1 - 4/1 3/1 0/1 + 46 PB14 D5 14 - - 4/2 - 5/0 4/0 0/2 + 47 PB15 D6 15 - - 4/3 - 5/1 4/1 0/3 + 44 PB12 D7 12 - - 4/0 - 4/0 3/0 0/0 + 21 PA21 D8 5 - - 5/3 3/3 7/1 1/5 0/1 + 20 PA20 D9 4 - - 5/2 3/2 7/0 1/4 0/0 + 3 PA03 AREF 3 10 - - - - - - + 18 PA18 D10 2 - - 1/2 3/2 3/0 1/2 0/6 + 19 PA19 D11 3 - - 1/3 3/3 3/1 1/3 0/7 + 16 PA16 D13 0 - - 1/0 3/1 2/0 1/0 0/4 + 36 PB04 ESP_BUSY 4 - 6 - - - - - + 15 PA15 ESP_CS 15 - - 2/3 4/3 3/1 2/1 1/3 + 33 PB01 ESP_GPIO0 1 13 - - 5/3 7/1 - - + 37 PB05 ESP_RESET 5 - 7 - - - - - + 55 PB23 ESP_RTS 7 - - 1/3 5/3 7/1 - - + 7 PA07 ESP_RX 7 7 - - 0/3 1/1 - - + 4 PA04 ESP_TX 4 4 - - 0/0 0/0 - - + 43 PB11 FLASH_CS 12 - - - 4/3 5/1 0/5 1/1 + 11 PA11 FLASH_HOLD 11 11 - 0/3 2/3 1/1 0/3 1/7 + 9 PA09 FLASH_MISO 9 9 3 0/1 2/0 0/1 0/1 1/5 + 8 PA08 FLASH_MOSI - 8 2 0/0 2/1 0/0 0/0 1/4 + 42 PB10 FLASH_SCK 10 - - - 4/2 5/0 0/4 1/0 + 10 PA10 FLASH_WP 10 10 - 0/2 2/2 1/0 0/2 1/6 + 14 PA14 MISO 14 - - 2/2 4/2 3/0 2/0 1/2 + 12 PA12 MOSI 12 - - 2/0 4/1 2/0 0/6 1/2 + 54 PB22 NEOPIXEL 22 - - 1/2 5/2 7/0 - - + 38 PB06 RXLED 6 - 8 - - - - - + 13 PA13 SCK 13 - - 2/1 4/0 2/1 0/7 1/3 + 35 PB03 SCL 9 15 - - 5/1 6/1 - - + 34 PB02 SDA 2 14 - - 5/0 6/0 2/2 - + 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - + 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - + 62 PB30 SWO 14 - - 7/0 5/1 0/0 4/0 0/6 + 39 PB07 TXLED 7 - 9 - - - - - + 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - + 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - + 17 PA17 USB_HOSTEN 1 - - 1/1 3/0 2/1 1/1 0/5 + 0 PA00 - 0 - - - 1/0 2/0 - - + 1 PA01 - 1 - - - 1/1 2/1 - - + 27 PA27 - 11 - - - - - - - + 63 PB31 - 15 - - 7/1 5/0 0/1 4/1 0/7 +=== ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== + +For the definition of the table columns see the explanation at the table +for Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`. + +The default devices at the board are: + +- UART 3 at pins PA23/PA22, labelled D0/D1 resp. RX/TX +- I2C 5 at pins PB02/PB03, labelled SDA/SCL +- SPI 4 at pins PA12/PA14/PA13, labelled MOSI, MISO and SCK +- DAC output on pins PA02 and PA05, labelled A0 and A1 + SEEED XIAO pin assignment table ------------------------------- @@ -577,6 +650,12 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 15 PA15 LED 15 - - 2/3 4/3 3/1 2/1 1/3 55 PB23 MISO 7 - - 1/3 5/3 7/1 - - 54 PB22 MOSI 22 - - 1/2 5/2 7/0 - - + 43 PB11 QSPI_CS 12 - - - 4/3 5/1 0/5 1/1 + 8 PA08 QSPI_D0 - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 QSPI_D1 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 QSPI_D2 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 QSPI_D3 11 11 - 0/3 2/3 1/1 0/3 1/7 + 42 PB10 QSPI_SCK 10 - - - 4/2 5/0 0/4 1/0 1 PA01 SCK 1 - - - 1/1 2/1 - - 13 PA13 SCL 13 - - 2/1 4/0 2/1 0/7 1/3 12 PA12 SDA 12 - - 2/0 4/1 2/0 0/6 1/2 @@ -584,17 +663,11 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 31 PA31 SWDIO 15 - - 7/3 1/3 6/1 2/1 - 24 PA24 USB_DM 8 - - 3/2 5/2 5/0 2/2 - 25 PA25 USB_DP 9 - - 3/3 5/3 5/1 - - - 8 PA08 - - 8 2 0/0 2/1 0/0 0/0 1/4 - 9 PA09 - 9 9 3 0/1 2/0 0/1 0/1 1/5 - 10 PA10 - 10 10 - 0/2 2/2 1/0 0/2 1/6 - 11 PA11 - 11 11 - 0/3 2/3 1/1 0/3 1/7 14 PA14 - 14 - - 2/2 4/2 3/0 2/0 1/2 18 PA18 - 2 - - 1/2 3/2 3/0 1/2 0/6 22 PA22 - 6 - - 3/0 5/1 4/0 1/6 0/2 23 PA23 - 7 - - 3/1 5/0 4/1 1/7 0/3 27 PA27 - 11 - - - - - - - - 42 PB10 - 10 - - - 4/2 5/0 0/4 1/0 - 43 PB11 - 12 - - - 4/3 5/1 0/5 1/1 === ==== ============ ==== ==== ==== ====== ====== ===== ===== ===== For the definition of the table columns see the explanation at the table for @@ -661,6 +734,12 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 117 PD21 SD_DET 11 - - 1/3 3/3 - 1/1 - 83 PC19 SD_CS 3 - - 6/3 0/3 - 0/3 - 82 PC18 SD_MISO 2 - - 6/2 0/2 - 0/2 - + 43 PB11 QSPI_CS 12 - - - 4/3 5/1 0/5 1/1 + 8 PA08 QSPI_D0 - 8 2 0/0 2/1 0/0 0/0 1/4 + 9 PA09 QSPI_D1 9 9 3 0/1 2/0 0/1 0/1 1/5 + 10 PA10 QSPI_D2 10 10 - 0/2 2/2 1/0 0/2 1/6 + 11 PA11 QSPI_D3 11 11 - 0/3 2/3 1/1 0/3 1/7 + 42 PB10 QSPI_SCK 10 - - - 4/2 5/0 0/4 1/0 80 PC16 SD_MOSI 0 - - 6/0 0/1 - 0/0 - 81 PC17 SD_SCK 1 - - 6/1 0/0 - 0/1 - 30 PA30 SWCLK 14 - - 7/2 1/2 6/0 2/0 - @@ -677,17 +756,11 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM 2 PA02 - 2 0 - - - - - - 3 PA03 - 3 10 - - - - - - 5 PA05 - 5 5 - - 0/1 0/1 - - - 8 PA08 - - 8 2 0/0 2/1 0/0 0/0 1/4 - 9 PA09 - 9 9 3 0/1 2/0 0/1 0/1 1/5 - 10 PA10 - 10 10 - 0/2 2/2 1/0 0/2 1/6 - 11 PA11 - 11 11 - 0/3 2/3 1/1 0/3 1/7 14 PA14 - 14 - - 2/2 4/2 3/0 2/0 1/2 18 PA18 - 2 - - 1/2 3/2 3/0 1/2 0/6 19 PA19 - 3 - - 1/3 3/3 3/1 1/3 0/7 23 PA23 - 7 - - 3/1 5/0 4/1 1/7 0/3 27 PA27 - 11 - - - - - - - - 42 PB10 - 10 - - - 4/2 5/0 0/4 1/0 - 43 PB11 - 12 - - - 4/3 5/1 0/5 1/1 46 PB14 - 14 - - 4/2 - 5/0 4/0 0/2 49 PB17 - 1 - - 5/1 - 6/1 3/1 0/5 54 PB22 - 22 - - 1/2 5/2 7/0 - - diff --git a/docs/samd/quickref.rst b/docs/samd/quickref.rst index cdfb0a475072..60c57b3a47a3 100644 --- a/docs/samd/quickref.rst +++ b/docs/samd/quickref.rst @@ -132,7 +132,7 @@ Use the :ref:`machine.Pin ` class:: print(p2.value()) # get value, 0 or 1 p4 = Pin('D4', Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor - p7 = Pin("PA07", Pin.OUT, value=1) # set pin high on creation + p7 = Pin('PA07', Pin.OUT, value=1) # set pin high on creation Pins can be denoted by a string or a number. The string is either the pin label of the respective board, like "D0" or "SDA", or in the form @@ -157,7 +157,7 @@ See :ref:`machine.UART `. :: # Use UART 3 on a ItsyBitsy M4 board from machine import UART - uart3 = UART(3, tx=Pin(1), rx=Pin(0), baudrate=115200) + uart3 = UART(3, tx=Pin('D1'), rx=Pin('D0'), baudrate=115200) uart3.write('hello') # write 5 bytes uart3.read(5) # read up to 5 bytes @@ -178,11 +178,12 @@ It supports all basic methods listed for that class. :: from machine import Pin, PWM - pwm = PWM(Pin(7)) # create PWM object from a pin - pwm.freq() # get current frequency - pwm.freq(1000) # set frequency - pwm.duty_u16() # get current duty cycle, range 0-65535 - pwm.duty_u16(200) # set duty cycle, range 0-65535 + # create PWM object from a pin and set the frequency and duty cycle + pwm = PWM(Pin('D7'), freq=2000, duty_u16=32768) + pwm.freq() # get the current frequency + pwm.freq(1000) # set/change the frequency + pwm.duty_u16() # get the current duty cycle, range 0-65535 + pwm.duty_u16(200) # set the duty cycle, range 0-65535 pwm.deinit() # turn off PWM on the pin pwm # show the PWM objects properties @@ -191,7 +192,7 @@ It supports all basic methods listed for that class. :: PWM Constructor ``````````````` -.. class:: PWM(dest, freq, duty_u16, duty_ns, *, invert, device) +.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert, device) :noindex: Construct and return a new PWM object using the following parameters: @@ -213,9 +214,6 @@ PWM Constructor - *freq* should be an integer which sets the frequency in Hz for the PWM cycle. The valid frequency range is 1 Hz to 24 MHz. - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65536``. - The duty cycle of a X channel can only be changed, if the A and B channel - of the respective submodule is not used. Otherwise the duty_16 value of the - X channel is 32768 (50%). - *duty_ns* sets the pulse width in nanoseconds. The limitation for X channels apply as well. - *invert*\=True|False. Setting a bit inverts the respective output. @@ -245,9 +243,9 @@ Use the :ref:`machine.ADC ` class:: from machine import ADC - adc0 = ADC(Pin("A0")) # create ADC object on ADC pin, average=16 + adc0 = ADC(Pin('A0')) # create ADC object on ADC pin, average=16 adc0.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v - adc1 = ADC(Pin("A1"), average=1) # create ADC object on ADC pin, average=1 + adc1 = ADC(Pin('A1'), average=1) # create ADC object on ADC pin, average=1 The resolution of the ADC is 12 bit with 12 bit accuracy, irrespective of the value returned by read_u16(). If you need a higher resolution or better accuracy, use @@ -341,7 +339,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the # construct a SoftSPI bus on the given pins # polarity is the idle state of SCK # phase=0 means sample on the first edge of SCK, phase=1 means the second - spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(7), mosi=Pin(9), miso=Pin(10)) + spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D7'), mosi=Pin('D9'), miso=Pin('D10')) spi.init(baudrate=200000) # set the baud rate @@ -388,7 +386,7 @@ accessed via the :ref:`machine.SoftI2C ` class:: from machine import Pin, SoftI2C - i2c = SoftI2C(scl=Pin(10), sda=Pin(11), freq=100000) + i2c = SoftI2C(scl=Pin('D10'), sda=Pin('D11'), freq=100000) i2c.scan() # scan for devices @@ -424,7 +422,7 @@ The OneWire driver is implemented in software and works on all pins:: from machine import Pin import onewire - ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 + ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12 ow.scan() # return a list of devices on the bus ow.reset() # reset the bus ow.readbyte() # read a byte @@ -454,12 +452,12 @@ The DHT driver is implemented in software and works on all pins:: import dht import machine - d = dht.DHT11(machine.Pin(4)) + d = dht.DHT11(machine.Pin('D4')) d.measure() d.temperature() # eg. 23 (°C) d.humidity() # eg. 41 (% RH) - d = dht.DHT22(machine.Pin(4)) + d = dht.DHT22(machine.Pin('D4')) d.measure() d.temperature() # eg. 23.6 (°C) d.humidity() # eg. 41.3 (% RH) @@ -474,7 +472,7 @@ The APA102 on some Adafruit boards can be controlled using SoftSPI:: from machine import SoftSPI, Pin # create the SPI object. miso can be any unused pin. - spi=SoftSPI(sck=Pin(25), mosi=Pin(26), miso=Pin(14)) + spi=SoftSPI(sck=Pin('D25'), mosi=Pin('D26'), miso=Pin('D14')) # define a little function that writes the data with # preamble and postfix @@ -499,7 +497,7 @@ with the Neopixel driver from the MicroPython driver library:: import machine # 1 LED connected to Pin D8 on Adafruit Feather boards - p = machine.Pin(8, machine.Pin.OUT) + p = machine.Pin('D8', machine.Pin.OUT) n = neopixel.NeoPixel(p, 1) # set the led to red. diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst index 329a9c41c0cc..57262ffb5c63 100644 --- a/docs/zephyr/quickref.rst +++ b/docs/zephyr/quickref.rst @@ -19,7 +19,7 @@ See the corresponding section of the tutorial: :ref:`intro`. Delay and timing ---------------- -Use the :mod:`time ` module:: +Use the :mod:`time