kopia lustrzana https://github.com/micropython/micropython
Merge remote-tracking branch 'origin/master' into awrite
Signed-off-by: Matthias Urlichs <matthias@urlichs.de>pull/10837/head
commit
72754ebed1
|
@ -1,3 +1,12 @@
|
|||
# all: Update Python formatting to ruff-format.
|
||||
bbd8760bd9a2302e5abee29db279102bb11d7732
|
||||
|
||||
# all: Fix various spelling mistakes found by codespell 2.2.6.
|
||||
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
|
||||
|
||||
# all: Fix spelling mistakes based on codespell check.
|
||||
b1229efbd1509654dec6053865ab828d769e29db
|
||||
|
||||
# top: Update Python formatting to black "2023 stable style".
|
||||
8b2748269244304854b3462cb8902952b4dcb892
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
# These are binary so should never be modified by git.
|
||||
*.a binary
|
||||
*.ico binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.dxf binary
|
||||
|
|
|
@ -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: ''
|
||||
|
|
|
@ -7,14 +7,24 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
code-formatting:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_code_formatting_setup
|
||||
run: source tools/ci.sh && ci_c_code_formatting_setup
|
||||
- name: Run code formatting
|
||||
run: source tools/ci.sh && ci_code_formatting_run
|
||||
run: source tools/ci.sh && ci_c_code_formatting_run
|
||||
- name: Check code formatting
|
||||
run: git diff --exit-code
|
||||
|
||||
code-spelling:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- name: Install packages
|
||||
|
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: '100'
|
||||
- uses: actions/setup-python@v4
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
name: Build docs
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
|
@ -14,9 +15,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- name: Install Python packages
|
||||
run: pip install Sphinx
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: Build docs
|
||||
run: make -C docs/ html
|
||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
embedding:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
|
||||
- name: Run
|
||||
|
|
|
@ -11,20 +11,18 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Version is determined from git,
|
||||
# should be deep enough to get to latest tag
|
||||
fetch-depth: '1000'
|
||||
- run: |
|
||||
git fetch --prune --unshallow --tags
|
||||
- uses: actions/setup-python@v1
|
||||
# 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
|
||||
- name: Build mpremote wheel
|
||||
run: cd tools/mpremote && python -m build --wheel
|
||||
- name: Archive mpremote wheel
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpremote
|
||||
path: |
|
||||
|
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
test:
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get python2
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_mpy_format_setup
|
||||
- name: Test mpy-tool.py
|
||||
|
|
|
@ -17,6 +17,6 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build ports download metadata
|
||||
run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_cc3200_setup
|
||||
- name: Build
|
||||
|
|
|
@ -18,20 +18,11 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_idf402:
|
||||
build_idf50:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- 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
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_mimxrt_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_nrf_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_powerpc_setup
|
||||
- name: Build
|
||||
|
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
build_and_test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_qemu_arm_setup
|
||||
- name: Build and run test suite
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build_renesas_ra_board:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_renesas_ra_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_rp2_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_samd_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build_pyb:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_stm32_setup
|
||||
- name: Build
|
||||
|
@ -30,7 +30,7 @@ jobs:
|
|||
build_nucleo:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_stm32_setup
|
||||
- name: Build
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
name: teensy port
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'tools/**'
|
||||
- 'py/**'
|
||||
- 'extmod/**'
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/teensy/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_teensy_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_teensy_build
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
minimal:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_minimal_build
|
||||
- name: Run main test suite
|
||||
|
@ -35,7 +35,7 @@ jobs:
|
|||
reproducible:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build with reproducible date
|
||||
run: source tools/ci.sh && ci_unix_minimal_build
|
||||
env:
|
||||
|
@ -46,7 +46,7 @@ jobs:
|
|||
standard:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_standard_build
|
||||
- name: Run main test suite
|
||||
|
@ -55,10 +55,22 @@ jobs:
|
|||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
standard_v2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||
- name: Build
|
||||
|
@ -85,9 +97,9 @@ 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
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||
- name: Build
|
||||
|
@ -103,9 +115,9 @@ 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
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||
- name: Build
|
||||
|
@ -119,7 +131,7 @@ jobs:
|
|||
float:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_float_build
|
||||
- name: Run main test suite
|
||||
|
@ -131,7 +143,7 @@ jobs:
|
|||
stackless_clang:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_clang_setup
|
||||
- name: Build
|
||||
|
@ -145,7 +157,7 @@ jobs:
|
|||
float_clang:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_clang_setup
|
||||
- name: Build
|
||||
|
@ -159,7 +171,7 @@ jobs:
|
|||
settrace:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_settrace_build
|
||||
- name: Run main test suite
|
||||
|
@ -171,7 +183,7 @@ jobs:
|
|||
settrace_stackless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_settrace_stackless_build
|
||||
- name: Run main test suite
|
||||
|
@ -183,7 +195,7 @@ jobs:
|
|||
macos:
|
||||
runs-on: macos-11.0
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.8'
|
||||
|
@ -198,7 +210,7 @@ jobs:
|
|||
qemu_mips:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_qemu_mips_setup
|
||||
- name: Build
|
||||
|
@ -212,7 +224,7 @@ jobs:
|
|||
qemu_arm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_qemu_arm_setup
|
||||
- name: Build
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_webassembly_setup
|
||||
- name: Build
|
||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_windows_setup
|
||||
- name: Build
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_zephyr_setup
|
||||
- name: Install Zephyr
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
||||
name: Python code lint and formatting with ruff
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
ruff:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: pip install --user ruff==0.1.3
|
||||
- run: ruff check --output-format=github .
|
||||
- run: ruff format --diff .
|
|
@ -56,3 +56,6 @@
|
|||
[submodule "lib/micropython-lib"]
|
||||
path = lib/micropython-lib
|
||||
url = https://github.com/micropython/micropython-lib.git
|
||||
[submodule "lib/protobuf-c"]
|
||||
path = lib/protobuf-c
|
||||
url = https://github.com/protobuf-c/protobuf-c.git
|
||||
|
|
|
@ -2,8 +2,8 @@ repos:
|
|||
- repo: local
|
||||
hooks:
|
||||
- id: codeformat
|
||||
name: MicroPython codeformat.py for changed files
|
||||
entry: tools/codeformat.py -v -f
|
||||
name: MicroPython codeformat.py for changed C files
|
||||
entry: tools/codeformat.py -v -c -f
|
||||
language: python
|
||||
- id: verifygitlog
|
||||
name: MicroPython git commit message format checker
|
||||
|
@ -11,3 +11,8 @@ repos:
|
|||
language: python
|
||||
verbose: true
|
||||
stages: [commit-msg]
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.1.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-format
|
||||
|
|
|
@ -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,21 +46,23 @@ 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
|
||||
====================
|
||||
|
||||
Both C and Python code are auto-formatted using the `tools/codeformat.py`
|
||||
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
|
||||
format C code and [black](https://github.com/psf/black) to format Python code.
|
||||
After making changes, and before committing, run this tool to reformat your
|
||||
changes to the correct style. Without arguments this tool will reformat all
|
||||
source code (and may take some time to run). Otherwise pass as arguments to
|
||||
the tool the files that changed and it will only reformat those.
|
||||
Both C and Python code formatting are controlled for consistency across the
|
||||
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
|
||||
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
|
||||
Python code is linted and formatted using
|
||||
[ruff & ruff format](https://github.com/astral-sh/ruff).
|
||||
After making changes, and before committing, run `tools/codeformat.py` to
|
||||
reformat your C code and `ruff format` for any Python code. Without
|
||||
arguments this tool will reformat all source code (and may take some time
|
||||
to run). Otherwise pass as arguments to the tool the files that changed,
|
||||
and it will only reformat those.
|
||||
|
||||
uncrustify
|
||||
==========
|
||||
|
@ -102,7 +101,7 @@ Brew
|
|||
This command may work, please raise a new Issue if it doesn't:
|
||||
|
||||
```
|
||||
brew install https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb
|
||||
curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb
|
||||
```
|
||||
|
||||
Automatic Pre-Commit Hooks
|
||||
|
@ -155,12 +154,22 @@ Tips:
|
|||
* To ignore the pre-commit message format check temporarily, start the commit
|
||||
message subject line with "WIP" (for "Work In Progress").
|
||||
|
||||
Running pre-commit manually
|
||||
===========================
|
||||
|
||||
Once pre-commit is installed as per the previous section it can be manually
|
||||
run against the MicroPython python codebase to update file formatting on
|
||||
demand, with either:
|
||||
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
|
||||
* `pre-commit run --file ./path/to/my/file` to fix just one file
|
||||
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
|
||||
|
||||
Python code conventions
|
||||
=======================
|
||||
|
||||
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
|
||||
is auto-formatted using [black](https://github.com/psf/black) with a line-length
|
||||
of 99 characters.
|
||||
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
|
||||
with a line-length of 99 characters.
|
||||
|
||||
Naming conventions:
|
||||
- Module names are short and all lowercase; eg pyb, stm.
|
||||
|
@ -255,7 +264,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:
|
||||
|
||||
|
|
8
LICENSE
8
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)
|
||||
|
@ -76,8 +78,6 @@ used during the build process and is not part of the compiled source code.
|
|||
/*/stm32*.h (BSD-3-clause)
|
||||
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
||||
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
||||
/teensy
|
||||
/core (PJRC.COM)
|
||||
/zephyr
|
||||
/src (Apache-2.0)
|
||||
/tools
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[![CI badge](https://github.com/micropython/micropython/workflows/unix%20port/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
|
||||
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
|
@ -119,7 +119,6 @@ In addition, the following ports are provided in this repository:
|
|||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
||||
- [teensy](ports/teensy) -- Teensy 3.x.
|
||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
||||
|
||||
|
|
194
docs/conf.py
194
docs/conf.py
|
@ -19,55 +19,56 @@ import os
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
sys.path.insert(0, os.path.abspath("."))
|
||||
|
||||
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
|
||||
micropy_version = os.getenv("MICROPY_VERSION") or "latest"
|
||||
micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",")
|
||||
url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",)
|
||||
|
||||
# The members of the html_context dict are available inside topindex.html
|
||||
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
|
||||
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
|
||||
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
|
||||
html_context = {
|
||||
'cur_version':micropy_version,
|
||||
'all_versions':[
|
||||
(ver, url_pattern % ver) for ver in micropy_all_versions
|
||||
"cur_version": micropy_version,
|
||||
"all_versions": [(ver, url_pattern % ver) for ver in micropy_all_versions],
|
||||
"downloads": [
|
||||
("PDF", url_pattern % micropy_version + "/micropython-docs.pdf"),
|
||||
],
|
||||
'downloads':[
|
||||
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'),
|
||||
],
|
||||
'is_release': micropy_version != 'latest',
|
||||
"is_release": micropy_version != "latest",
|
||||
}
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinxcontrib.jquery",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates']
|
||||
templates_path = ["templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = 'MicroPython'
|
||||
copyright = '- The MicroPython Documentation is Copyright © 2014-2022, Damien P. George, Paul Sokolovsky, and contributors'
|
||||
project = "MicroPython"
|
||||
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
|
||||
|
@ -79,41 +80,41 @@ version = release = micropy_version
|
|||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['build', '.venv']
|
||||
exclude_patterns = ["build", ".venv"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
default_role = 'any'
|
||||
default_role = "any"
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
# keep_warnings = False
|
||||
|
||||
# Global include files. Sphinx docs suggest using rst_epilog in preference
|
||||
# of rst_prolog, so we follow. Absolute paths below mean "from the base
|
||||
|
@ -125,144 +126,148 @@ rst_epilog = """
|
|||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# on_rtd is whether we are on readthedocs.org
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
html_theme = "default"
|
||||
html_theme_path = ["."]
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
html_theme_path = ["."]
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = ['.']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = '../../logo/trans-logo.png'
|
||||
# html_logo = '../../logo/trans-logo.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
html_favicon = 'static/favicon.ico'
|
||||
html_favicon = "static/favicon.ico"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['static']
|
||||
html_static_path = ["static"]
|
||||
|
||||
# Add a custom CSS file for HTML generation
|
||||
html_css_files = [
|
||||
'custom.css',
|
||||
"custom.css",
|
||||
]
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
# html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%d %b %Y'
|
||||
html_last_updated_fmt = "%d %b %Y"
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
html_additional_pages = {"index": "topindex.html"}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'MicroPythondoc'
|
||||
htmlhelp_basename = "MicroPythondoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Include 3 levels of headers in PDF ToC
|
||||
'preamble': '\setcounter{tocdepth}{2}',
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Include 3 levels of headers in PDF ToC
|
||||
"preamble": r"\setcounter{tocdepth}{2}",
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
|
||||
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
|
||||
(
|
||||
master_doc,
|
||||
"MicroPython.tex",
|
||||
"MicroPython Documentation",
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
# latex_domain_indices = True
|
||||
|
||||
# Enable better Unicode support so that `make latexpdf` doesn't fail
|
||||
latex_engine = "xelatex"
|
||||
|
@ -272,12 +277,17 @@ latex_engine = "xelatex"
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'micropython', 'MicroPython Documentation',
|
||||
['Damien P. George, Paul Sokolovsky, and contributors'], 1),
|
||||
(
|
||||
"index",
|
||||
"micropython",
|
||||
"MicroPython Documentation",
|
||||
["Damien P. George, Paul Sokolovsky, and contributors"],
|
||||
1,
|
||||
),
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
@ -286,23 +296,29 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'MicroPython', 'MicroPython Documentation',
|
||||
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"MicroPython",
|
||||
"MicroPython Documentation",
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"MicroPython",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
# texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)}
|
||||
intersphinx_mapping = {"python": ("https://docs.python.org/3.5", None)}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -100,7 +100,7 @@ For the stm32 port, the ARM cross-compiler is required:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib
|
||||
$ sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi
|
||||
|
||||
See the `ARM GCC
|
||||
toolchain <https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads>`_
|
||||
|
@ -228,7 +228,7 @@ You can also specify which board to use:
|
|||
.. code-block:: bash
|
||||
|
||||
$ cd ports/stm32
|
||||
$ make submodules
|
||||
$ make BOARD=<board> submodules
|
||||
$ make BOARD=<board>
|
||||
|
||||
See `ports/stm32/boards <https://github.com/micropython/micropython/tree/master/ports/stm32/boards>`_
|
||||
|
@ -245,7 +245,7 @@ that you use a virtual environment:
|
|||
|
||||
$ python3 -m venv env
|
||||
$ source env/bin/activate
|
||||
$ pip install sphinx
|
||||
$ pip install -r docs/requirements.txt
|
||||
|
||||
Navigate to the ``docs`` directory:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -102,7 +101,7 @@ A useful function for connecting to your local WiFi network is::
|
|||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the :mod:`socket <socket>` module can be used
|
||||
to create and use TCP/UDP sockets as usual, and the ``urequests`` module for
|
||||
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
|
||||
convenient HTTP requests.
|
||||
|
||||
After a call to ``wlan.connect()``, the device will by default retry to connect
|
||||
|
@ -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 <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%)
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 200 KiB |
|
@ -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.
|
||||
|
||||
|
|
|
@ -42,3 +42,83 @@ for this:
|
|||
|
||||
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence
|
||||
the value of ``DPORT_PWM0_CLK_EN``.
|
||||
|
||||
Synchronous access to pins directly via registers
|
||||
-------------------------------------------------
|
||||
|
||||
The following code shows how to access pins directly via registers. It has been
|
||||
tested on a generic ESP32 board. It configures pins 16, 17, 32 and 33 in output
|
||||
mode via registers, and switches pin output values via registers. Pins 16 and
|
||||
17 are switched simultaneously.
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
from micropython import const
|
||||
from machine import mem32, Pin
|
||||
|
||||
GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 output register
|
||||
GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 output register
|
||||
|
||||
GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 output enable register
|
||||
GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 output enable register
|
||||
|
||||
M16 = 1 << 16 # Pin(16) bit mask
|
||||
M17 = 1 << 17 # Pin(17) bit mask
|
||||
|
||||
M32 = 1 << (32-32) # Pin(32) bit mask
|
||||
M33 = 1 << (33-32) # Pin(33) bit mask
|
||||
|
||||
# Enable pin output mode like
|
||||
# p16 = Pin(16, mode=Pin.OUT)
|
||||
# p17 = Pin(17, mode=Pin.OUT)
|
||||
# p32 = Pin(32, mode=Pin.OUT)
|
||||
# p33 = Pin(33, mode=Pin.OUT)
|
||||
mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17
|
||||
mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33
|
||||
|
||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
||||
|
||||
# Set outputs to 1 like
|
||||
# p16(1)
|
||||
# p17(1)
|
||||
# p32(1)
|
||||
# p33(1)
|
||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
|
||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
|
||||
|
||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
||||
|
||||
# Set outputs to 0 like
|
||||
# p16(0)
|
||||
# p17(0)
|
||||
# p32(0)
|
||||
# p33(0)
|
||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
|
||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
|
||||
|
||||
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
|
||||
|
||||
while True:
|
||||
# Set outputs to 1
|
||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
|
||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33
|
||||
|
||||
# Set outputs to 0
|
||||
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
|
||||
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
|
||||
|
||||
|
||||
Output is::
|
||||
|
||||
0x0 0x0
|
||||
0x30000 0x3
|
||||
0x0 0x0
|
||||
|
||||
Pins 16 and 17 are switched synchronously:
|
||||
|
||||
.. image:: img/mem32_gpio_output.jpg
|
||||
|
||||
Same image on pins 32 and 33.
|
||||
|
||||
Note that pins 34-36 and 39 are inputs only. Also pins 1 and 3 are Tx, Rx of the REPL UART,
|
||||
pins 6-11 are connected to the built-in SPI flash.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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(<type>, [<elements>])"``,
|
||||
where ``<type>`` is the type code letter for the array and ``<elements>`` 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.
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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 <BLE.gatts_write>`) will be sent.
|
||||
|
||||
Otherwise, if *data* is ``None``, then the current local value (as
|
||||
set with :meth:`gatts_write <BLE.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 <BLE.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.
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
:mod:`deflate` -- deflate compression & decompression
|
||||
=====================================================
|
||||
|
||||
.. module:: deflate
|
||||
:synopsis: deflate compression & decompression
|
||||
|
||||
This module allows compression and decompression of binary data with the
|
||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
|
||||
(commonly used in the zlib library and gzip archiver).
|
||||
|
||||
**Availability:**
|
||||
|
||||
* Added in MicroPython v1.21.
|
||||
|
||||
* Decompression: Enabled via the ``MICROPY_PY_DEFLATE`` build option, on by default
|
||||
on ports with the "extra features" level or higher (which is most boards).
|
||||
|
||||
* Compression: Enabled via the ``MICROPY_PY_DEFLATE_COMPRESS`` build option, on
|
||||
by default on ports with the "full features" level or higher (generally this means
|
||||
you need to build your own firmware to enable this).
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: DeflateIO(stream, format=AUTO, wbits=0, close=False, /)
|
||||
|
||||
This class can be used to wrap a *stream* which is any
|
||||
:term:`stream-like <stream>` object such as a file, socket, or stream
|
||||
(including :class:`io.BytesIO`). It is itself a stream and implements the
|
||||
standard read/readinto/write/close methods.
|
||||
|
||||
The *stream* must be a blocking stream. Non-blocking streams are currently
|
||||
not supported.
|
||||
|
||||
The *format* can be set to any of the constants defined below, and defaults
|
||||
to ``AUTO`` which for decompressing will auto-detect gzip or zlib streams,
|
||||
and for compressing it will generate a raw stream.
|
||||
|
||||
The *wbits* parameter sets the base-2 logarithm of the DEFLATE dictionary
|
||||
window size. So for example, setting *wbits* to ``10`` sets the window size
|
||||
to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to
|
||||
window sizes of 32 to 32k bytes).
|
||||
|
||||
If *wbits* is set to ``0`` (the default), then for compression a window size
|
||||
of 256 bytes will be used (as if *wbits* was set to 8). For decompression, it
|
||||
depends on the format:
|
||||
|
||||
* ``RAW`` will use 256 bytes (corresponding to *wbits* set to 8).
|
||||
* ``ZLIB`` (or ``AUTO`` with zlib detected) will use the value from the zlib
|
||||
header.
|
||||
* ``GZIP`` (or ``AUTO`` with gzip detected) will use 32 kilobytes
|
||||
(corresponding to *wbits* set to 15).
|
||||
|
||||
See the :ref:`window size <deflate_wbits>` notes below for more information
|
||||
about the window size, zlib, and gzip streams.
|
||||
|
||||
If *close* is set to ``True`` then the underlying stream will be closed
|
||||
automatically when the :class:`deflate.DeflateIO` stream is closed. This is
|
||||
useful if you want to return a :class:`deflate.DeflateIO` stream that wraps
|
||||
another stream and not have the caller need to know about managing the
|
||||
underlying stream.
|
||||
|
||||
If compression is enabled, a given :class:`deflate.DeflateIO` instance
|
||||
supports both reading and writing. For example, a bidirectional stream like
|
||||
a socket can be wrapped, which allows for compression/decompression in both
|
||||
directions.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: deflate.AUTO
|
||||
deflate.RAW
|
||||
deflate.ZLIB
|
||||
deflate.GZIP
|
||||
|
||||
Supported values for the *format* parameter.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
A typical use case for :class:`deflate.DeflateIO` is to read or write a compressed
|
||||
file from storage:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import deflate
|
||||
|
||||
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
|
||||
with open("data.gz", "wb") as f:
|
||||
with deflate.DeflateIO(f, deflate.ZLIB) as d:
|
||||
# Use d.write(...) etc
|
||||
|
||||
# Reading a zlib-compressed stream (auto-detect window size).
|
||||
with open("data.z", "rb") as f:
|
||||
with deflate.DeflateIO(f, deflate.ZLIB) as d:
|
||||
# Use d.read(), d.readinto(), etc.
|
||||
|
||||
Because :class:`deflate.DeflateIO` is a stream, it can be used for example
|
||||
with :meth:`json.dump` and :meth:`json.load` (and any other places streams can
|
||||
be used):
|
||||
|
||||
.. code:: python
|
||||
|
||||
import deflate, json
|
||||
|
||||
# Write a dictionary as JSON in gzip format, with a
|
||||
# small (64 byte) window size.
|
||||
config = { ... }
|
||||
with open("config.gz", "wb") as f:
|
||||
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
|
||||
json.dump(config, f)
|
||||
|
||||
# Read back that dictionary.
|
||||
with open("config.gz", "rb") as f:
|
||||
with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
|
||||
config = json.load(f)
|
||||
|
||||
If your source data is not in a stream format, you can use :class:`io.BytesIO`
|
||||
to turn it into a stream suitable for use with :class:`deflate.DeflateIO`:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import deflate, io
|
||||
|
||||
# Decompress a bytes/bytearray value.
|
||||
compressed_data = get_data_z()
|
||||
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
|
||||
decompressed_data = d.read()
|
||||
|
||||
# Compress a bytes/bytearray value.
|
||||
uncompressed_data = get_data()
|
||||
stream = io.BytesIO()
|
||||
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
|
||||
d.write(uncompressed_data)
|
||||
compressed_data = stream.getvalue()
|
||||
|
||||
.. _deflate_wbits:
|
||||
|
||||
Deflate window size
|
||||
-------------------
|
||||
|
||||
The window size limits how far back in the stream the (de)compressor can
|
||||
reference. Increasing the window size will improve compression, but will require
|
||||
more memory and make the compressor slower.
|
||||
|
||||
If an input stream was compressed a given window size, then `DeflateIO`
|
||||
using a smaller window size will fail mid-way during decompression with
|
||||
:exc:`OSError`, but only if a back-reference actually refers back further
|
||||
than the decompressor's window size. This means it may be possible to decompress
|
||||
with a smaller window size. For example, this would trivially be the case if the
|
||||
original uncompressed data is shorter than the window size.
|
||||
|
||||
Decompression
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The zlib format includes a header which specifies the window size that was used
|
||||
to compress the data. This indicates the maximum window size required to
|
||||
decompress this stream. If this header value is less than the specified *wbits*
|
||||
value (or if *wbits* is unset), then the header value will be used.
|
||||
|
||||
The gzip format does not include the window size in the header, and assumes that
|
||||
all gzip compressors (e.g. the ``gzip`` utility, or CPython's implementation of
|
||||
:class:`gzip.GzipFile`) use the maximum window size of 32kiB. For this reason,
|
||||
if the *wbits* parameter is not set, the decompressor will use a 32 kiB window
|
||||
size (corresponding to *wbits* set to 15). This means that to be able to
|
||||
decompress an arbitrary gzip stream, you must have at least this much RAM
|
||||
available. If you control the source data, consider instead using the zlib
|
||||
format with a smaller window size.
|
||||
|
||||
The raw format has no header and therefore does not include any information
|
||||
about the window size. If *wbits* is not set, then it will default to a window
|
||||
size of 256 bytes, which may not be large enough for a given stream. Therefore
|
||||
it is recommended that you should always explicitly set *wbits* if using the raw
|
||||
format.
|
||||
|
||||
Compression
|
||||
~~~~~~~~~~~
|
||||
|
||||
For compression, MicroPython will default to a window size of 256 bytes for all
|
||||
formats. This provides a reasonable amount of compression with minimal memory
|
||||
usage and fast compression time, and will generate output that will work with
|
||||
any decompressor.
|
|
@ -62,12 +62,35 @@ Functions
|
|||
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
.. function:: osdebug(level)
|
||||
.. function:: osdebug(uart_no)
|
||||
|
||||
Turn esp os debugging messages on or off.
|
||||
.. note:: This is the ESP8266 form of this function.
|
||||
|
||||
The *level* parameter sets the threshold for the log messages for all esp components.
|
||||
The log levels are defined as constants:
|
||||
Change the level of OS serial debug log messages. On boot,
|
||||
OS serial debug log messages are disabled.
|
||||
|
||||
``uart_no`` is the number of the UART peripheral which should receive
|
||||
OS-level output, or ``None`` to disable OS serial debug log messages.
|
||||
|
||||
.. function:: osdebug(uart_no, [level])
|
||||
:no-index:
|
||||
|
||||
.. note:: This is the ESP32 form of this function.
|
||||
|
||||
Change the level of OS serial debug log messages. On boot, OS
|
||||
serial debug log messages are limited to Error output only.
|
||||
|
||||
The behaviour of this function depends on the arguments passed to it. The
|
||||
following combinations are supported:
|
||||
|
||||
``osdebug(None)`` restores the default OS debug log message level
|
||||
(``LOG_ERROR``).
|
||||
|
||||
``osdebug(0)`` enables all available OS debug log messages (in the
|
||||
default build configuration this is ``LOG_INFO``).
|
||||
|
||||
``osdebug(0, level)`` sets the OS debug log message level to the
|
||||
specified value. The log levels are defined as constants:
|
||||
|
||||
* ``LOG_NONE`` -- No log output
|
||||
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
|
||||
|
@ -77,6 +100,15 @@ Functions
|
|||
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
|
||||
which can potentially flood the output
|
||||
|
||||
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
|
||||
MicroPython binary by default, to save size. A custom build with a
|
||||
modified "``sdkconfig``" source file is needed to see any output
|
||||
at these log levels.
|
||||
|
||||
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
|
||||
to prevent communications issues. This means OS level logging is never
|
||||
seen when using ``mpremote run`` and similar tools.
|
||||
|
||||
.. function:: set_native_code_location(start, length)
|
||||
|
||||
**Note**: ESP8266 only
|
||||
|
|
|
@ -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
|
||||
|
@ -55,8 +51,6 @@ Functions
|
|||
buffers and other data. This data is useful to get a sense of how much memory
|
||||
is available to ESP-IDF and the networking stack in particular. It may shed
|
||||
some light on situations where ESP-IDF operations fail due to allocation failures.
|
||||
The information returned is *not* useful to troubleshoot Python allocation failures,
|
||||
use `micropython.mem_info()` instead.
|
||||
|
||||
The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the
|
||||
two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and
|
||||
|
@ -72,6 +66,21 @@ Functions
|
|||
[(240, 0, 0, 0), (7288, 0, 0, 0), (16648, 4, 4, 4), (79912, 35712, 35512, 35108),
|
||||
(15072, 15036, 15036, 15036), (113840, 0, 0, 0)]
|
||||
|
||||
.. note:: Free IDF heap memory in the `esp32.HEAP_DATA` region is available
|
||||
to be automatically added to the MicroPython heap to prevent a
|
||||
MicroPython allocation from failing. However, the information returned
|
||||
here is otherwise *not* useful to troubleshoot Python allocation
|
||||
failures. :func:`micropython.mem_info()` and :func:`gc.mem_free()` should
|
||||
be used instead:
|
||||
|
||||
The "max new split" value in :func:`micropython.mem_info()` output
|
||||
corresponds to the largest free block of ESP-IDF heap that could be
|
||||
automatically added on demand to the MicroPython heap.
|
||||
|
||||
The result of :func:`gc.mem_free()` is the total of the current "free"
|
||||
and "max new split" values printed by :func:`micropython.mem_info()`.
|
||||
|
||||
|
||||
Flash partitions
|
||||
----------------
|
||||
|
||||
|
@ -111,6 +120,11 @@ methods to enable over-the-air (OTA) updates.
|
|||
|
||||
Sets the partition as the boot partition.
|
||||
|
||||
.. note:: Do not enter :func:`deepsleep<machine.deepsleep>` after changing
|
||||
the OTA boot partition, without first performing a hard
|
||||
:func:`reset<machine.reset>` or power cycle. This ensures the bootloader
|
||||
will validate the new image before booting.
|
||||
|
||||
.. method:: Partition.get_next_update()
|
||||
|
||||
Gets the next update partition after this one, and returns a new Partition object.
|
||||
|
@ -126,7 +140,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
|
||||
~~~~~~~~~
|
||||
|
@ -179,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
|
|||
define the pulses.
|
||||
|
||||
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
|
||||
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
|
||||
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
|
||||
channels (0-7) and each can have a different clock divider.
|
||||
|
||||
So, in the example above, the 80MHz clock is divided by 8. Thus the
|
||||
|
@ -212,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||
``100``) and the output level to apply the carrier to (a boolean as per
|
||||
*idle_level*).
|
||||
|
||||
.. method:: RMT.source_freq()
|
||||
.. classmethod:: RMT.source_freq()
|
||||
|
||||
Returns the source clock frequency. Currently the source clock is not
|
||||
configurable so this will always return 80MHz.
|
||||
|
@ -250,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
|
||||
specifying individual durations and the output level for each.
|
||||
|
||||
Durations are in integer units of the channel resolution (as described
|
||||
above), between 1 and 32767 units. Output levels are any value that can
|
||||
be converted to a boolean, with ``True`` representing high voltage and
|
||||
``False`` representing low.
|
||||
Durations are in integer units of the channel resolution (as
|
||||
described above), between 1 and ``PULSE_MAX`` units. Output levels
|
||||
are any value that can be converted to a boolean, with ``True``
|
||||
representing high voltage and ``False`` representing low.
|
||||
|
||||
If transmission of an earlier sequence is in progress then this method will
|
||||
block until that transmission is complete before beginning the new sequence.
|
||||
|
@ -276,9 +290,24 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
|||
Passing in no argument will not change the channel. This function returns
|
||||
the current channel number.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: RMT.PULSE_MAX
|
||||
|
||||
Maximum integer that can be set for a pulse duration.
|
||||
|
||||
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.
|
||||
|
|
|
@ -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 <https://www.espressif.com/
|
||||
en/products/software/esp-now/overview>`_ protocol provided by Espressif on
|
||||
ESP32 and ESP8266 devices (`API docs <https://docs.espressif.com/
|
||||
projects/esp-idf/en/latest/api-reference/network/esp_now.html>`_).
|
||||
|
||||
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<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)<ESPNow.active()>`.
|
||||
|
||||
*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
|
||||
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
|
||||
api-reference/network/esp_wifi.html#_CPPv415wifi_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()<network.WLAN.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)<network.WLAN.active>` (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()<network.WLAN.disconnect>` after
|
||||
`active(True)<network.WLAN.active>`.
|
||||
|
||||
.. 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()<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()<network.WLAN.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()<network.WLAN.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()<ESPNow.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()<network.WLAN.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 reuse 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()<ESPNow.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()<ESPNow.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
|
||||
<https://docs.espressif.com/projects/esp-idf/en/latest/
|
||||
esp32/api-reference/network/esp_now.html#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 <https://docs.espressif.com/
|
||||
projects/esp-idf/en/latest/esp32/api-reference/network/
|
||||
esp_now.html#c.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()<ESPNow.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()<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
|
||||
<https://docs.espressif.com/projects/esp-idf/en/latest/
|
||||
api-reference/network/esp_now.html#api-reference>`_. 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<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<espnow.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()<ESPNow.send()>` a broadcast message, the broadcast (or
|
||||
multicast) MAC address must first be registered using
|
||||
`add_peer()<ESPNow.add_peer()>`. `send()<ESPNow.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)<ESPNow.send()>` 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()<network.WLAN.active>`
|
||||
`WLAN<network.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 <https://docs.espressif.com/
|
||||
projects/esp-idf/en/latest/esp32/api-guides/
|
||||
wifi.html#esp32-wi-fi-power-saving-mode>`_) 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
|
||||
<https://docs.espressif.com/
|
||||
projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
|
||||
#_CPPv419esp_wifi_set_config16wifi_interface_tP13wifi_config_t>`_
|
||||
). 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])<machine.lightsleep>` and
|
||||
`machine.deepsleep([time_ms])<machine.deepsleep>` 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)<network.WLAN.active>`) before entering light or deep sleep (see
|
||||
`Sleep Modes <https://docs.espressif.com/
|
||||
projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html>`_).
|
||||
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)<network.WLAN.active()>` then both interfaces should be set
|
||||
`active(False)<network.WLAN.active()>` 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()
|
||||
|
|
@ -24,7 +24,7 @@ Functions
|
|||
|
||||
.. function:: mem_alloc()
|
||||
|
||||
Return the number of bytes of heap RAM that are allocated.
|
||||
Return the number of bytes of heap RAM that are allocated by Python code.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
@ -33,8 +33,8 @@ Functions
|
|||
|
||||
.. function:: mem_free()
|
||||
|
||||
Return the number of bytes of available heap RAM, or -1 if this amount
|
||||
is not known.
|
||||
Return the number of bytes of heap RAM that is available for Python
|
||||
code to allocate, or -1 if this amount is not known.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
:mod:`gzip` -- gzip compression & decompression
|
||||
===============================================
|
||||
|
||||
.. module:: gzip
|
||||
:synopsis: gzip compression & decompression
|
||||
|
||||
|see_cpython_module| :mod:`python:gzip`.
|
||||
|
||||
This module allows compression and decompression of binary data with the
|
||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_ used by the gzip
|
||||
file format.
|
||||
|
||||
.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this
|
||||
module as it provides a streaming interface to compression and decompression
|
||||
which is convenient and more memory efficient when working with reading or
|
||||
writing compressed data to a file, socket, or stream.
|
||||
|
||||
**Availability:**
|
||||
|
||||
* This module is **not present by default** in official MicroPython firmware
|
||||
releases as it duplicates functionality available in the :mod:`deflate
|
||||
<deflate>` module.
|
||||
|
||||
* A copy of this module can be installed (or frozen)
|
||||
from :term:`micropython-lib` (`source <https://github.com/micropython/micropython-lib/blob/master/python-stdlib/gzip/gzip.py>`_).
|
||||
See :ref:`packages` for more information. This documentation describes that module.
|
||||
|
||||
* Compression support will only be available if compression support is enabled
|
||||
in the built-in :mod:`deflate <deflate>` module.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: open(filename, mode, /)
|
||||
|
||||
Wrapper around built-in :func:`open` returning a GzipFile instance.
|
||||
|
||||
.. function:: decompress(data, /)
|
||||
|
||||
Decompresses *data* into a bytes object.
|
||||
|
||||
.. function:: compress(data, /)
|
||||
|
||||
Compresses *data* into a bytes object.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: GzipFile(*, fileobj, mode)
|
||||
|
||||
This class can be used to wrap a *fileobj* which is any
|
||||
:term:`stream-like <stream>` object such as a file, socket, or stream
|
||||
(including :class:`io.BytesIO`). It is itself a stream and implements the
|
||||
standard read/readinto/write/close methods.
|
||||
|
||||
When the *mode* argument is ``"rb"``, reads from the GzipFile instance will
|
||||
decompress the data in the underlying stream and return decompressed data.
|
||||
|
||||
If compression support is enabled then the *mode* argument can be set to
|
||||
``"wb"``, and writes to the GzipFile instance will be compressed and written
|
||||
to the underlying stream.
|
||||
|
||||
By default the GzipFile class will read and write data using the gzip file
|
||||
format, including a header and footer with checksum and a window size of 512
|
||||
bytes.
|
||||
|
||||
The **file**, **compresslevel**, and **mtime** arguments are not
|
||||
supported. **fileobj** and **mode** must always be specified as keyword
|
||||
arguments.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
A typical use case for :class:`gzip.GzipFile` is to read or write a compressed
|
||||
file from storage:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import gzip
|
||||
|
||||
# Reading:
|
||||
with open("data.gz", "rb") as f:
|
||||
with gzip.GzipFile(fileobj=f, mode="rb") as g:
|
||||
# Use g.read(), g.readinto(), etc.
|
||||
|
||||
# Same, but using gzip.open:
|
||||
with gzip.open("data.gz", "rb") as f:
|
||||
# Use f.read(), f.readinto(), etc.
|
||||
|
||||
# Writing:
|
||||
with open("data.gz", "wb") as f:
|
||||
with gzip.GzipFile(fileobj=f, mode="wb") as g:
|
||||
# Use g.write(...) etc
|
||||
|
||||
# Same, but using gzip.open:
|
||||
with gzip.open("data.gz", "wb") as f:
|
||||
# Use f.write(...) etc
|
||||
|
||||
# Write a dictionary as JSON in gzip format, with a
|
||||
# small (64 byte) window size.
|
||||
config = { ... }
|
||||
with gzip.open("config.gz", "wb") as f:
|
||||
json.dump(config, f)
|
||||
|
||||
For guidance on working with gzip sources and choosing the window size see the
|
||||
note at the :ref:`end of the deflate documentation <deflate_wbits>`.
|
|
@ -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 <micropython_lib_python>` (e.g. :mod:`os`,
|
||||
:mod:`time`), as well as :ref:`MicroPython-specific modules <micropython_lib_micropython>`
|
||||
(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 <micropython_lib_extending>` 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,18 +57,21 @@ library.
|
|||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
asyncio.rst
|
||||
binascii.rst
|
||||
builtins.rst
|
||||
cmath.rst
|
||||
collections.rst
|
||||
errno.rst
|
||||
gc.rst
|
||||
gzip.rst
|
||||
hashlib.rst
|
||||
heapq.rst
|
||||
io.rst
|
||||
json.rst
|
||||
math.rst
|
||||
os.rst
|
||||
platform.rst
|
||||
random.rst
|
||||
re.rst
|
||||
select.rst
|
||||
|
@ -73,10 +80,10 @@ library.
|
|||
struct.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
uasyncio.rst
|
||||
zlib.rst
|
||||
_thread.rst
|
||||
|
||||
.. _micropython_lib_micropython:
|
||||
|
||||
MicroPython-specific libraries
|
||||
------------------------------
|
||||
|
@ -90,6 +97,7 @@ the following libraries.
|
|||
bluetooth.rst
|
||||
btree.rst
|
||||
cryptolib.rst
|
||||
deflate.rst
|
||||
framebuf.rst
|
||||
machine.rst
|
||||
micropython.rst
|
||||
|
@ -155,6 +163,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 +189,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``, ``gzip``,
|
||||
``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.
|
||||
(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.
|
||||
|
||||
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).
|
||||
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::
|
||||
|
||||
*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``.
|
||||
_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``.
|
||||
|
|
|
@ -86,16 +86,6 @@ Functions
|
|||
Classes
|
||||
-------
|
||||
|
||||
.. class:: FileIO(...)
|
||||
|
||||
This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: TextIOWrapper(...)
|
||||
|
||||
This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: StringIO([string])
|
||||
.. class:: BytesIO([string])
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ Methods
|
|||
Configure the ADC peripheral. *bits* will set the resolution of the
|
||||
conversion process.
|
||||
|
||||
.. method:: ADCBlock.connect(channel)
|
||||
ADCBlock.connect(source)
|
||||
ADCBlock.connect(channel, source)
|
||||
.. method:: ADCBlock.connect(channel, *, ...)
|
||||
ADCBlock.connect(source, *, ...)
|
||||
ADCBlock.connect(channel, source, *, ...)
|
||||
|
||||
Connect up a channel on the ADC peripheral so it is ready for sampling,
|
||||
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
|
||||
|
@ -56,3 +56,6 @@ Methods
|
|||
|
||||
If both *channel* and *source* are given then they are connected together
|
||||
and made ready for sampling.
|
||||
|
||||
Any additional keyword arguments are used to configure the returned ADC object,
|
||||
via its :meth:`init <machine.ADC.init>` method.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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
|
||||
-------
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
-------
|
||||
|
|
|
@ -9,9 +9,7 @@ This module provides a driver for WS2818 / NeoPixel LEDs.
|
|||
.. note:: This module is only included by default on the ESP8266, ESP32 and RP2
|
||||
ports. On STM32 / Pyboard and others, you can either install the
|
||||
``neopixel`` package using :term:`mip`, or you can download the module
|
||||
directly from
|
||||
<https://raw.githubusercontent.com/micropython/micropython-lib/master/micropython/drivers/led/neopixel/neopixel.py>`_
|
||||
and copy it to the filesystem.
|
||||
directly from :term:`micropython-lib` and copy it to the filesystem.
|
||||
|
||||
class NeoPixel
|
||||
--------------
|
||||
|
|
|
@ -130,7 +130,23 @@ Methods
|
|||
hidden Whether SSID is hidden (boolean)
|
||||
security Security protocol supported (enumeration, see module constants)
|
||||
key Access key (string)
|
||||
hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP)
|
||||
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
|
||||
|
|
|
@ -158,12 +158,50 @@ Network functions
|
|||
|
||||
The following are functions available in the network module.
|
||||
|
||||
.. function:: country([code])
|
||||
|
||||
Get or set the two-letter ISO 3166-1 Alpha-2 country code to be used for
|
||||
radio compliance.
|
||||
|
||||
If the *code* parameter is provided, the country will be set to this value.
|
||||
If the function is called without parameters, it returns the current
|
||||
country.
|
||||
|
||||
The default code ``"XX"`` represents the "worldwide" region.
|
||||
|
||||
.. function:: hostname([name])
|
||||
|
||||
Get or set the hostname that will identify this device on the network. It will
|
||||
be used by all interfaces.
|
||||
|
||||
This hostname is used for:
|
||||
* Sending to the DHCP server in the client request. (If using DHCP)
|
||||
* Broadcasting via mDNS. (If enabled)
|
||||
|
||||
If the *name* parameter is provided, the hostname will be set to this value.
|
||||
If the function is called without parameters, it returns the current
|
||||
hostname.
|
||||
|
||||
A change in hostname is typically only applied during connection. For DHCP
|
||||
this is because the hostname is part of the DHCP client request, and the
|
||||
implementation of mDNS in most ports only initialises the hostname once
|
||||
during connection. For this reason, you must set the hostname before
|
||||
activating/connecting your network interfaces.
|
||||
|
||||
The length of the hostname is limited to 32 characters.
|
||||
:term:`MicroPython ports <MicroPython port>` may choose to set a lower
|
||||
limit for memory reasons. If the given name does not fit, a `ValueError`
|
||||
is raised.
|
||||
|
||||
The default hostname is typically the name of the board.
|
||||
|
||||
.. function:: phy_mode([mode])
|
||||
|
||||
Get or set the PHY mode.
|
||||
|
||||
If the *mode* parameter is provided, sets the mode to its value. If
|
||||
the function is called without parameters, returns the current mode.
|
||||
If the *mode* parameter is provided, the PHY mode will be set to this value.
|
||||
If the function is called without parameters, it returns the current PHY
|
||||
mode.
|
||||
|
||||
The possible modes are defined as constants:
|
||||
* ``MODE_11B`` -- IEEE 802.11b,
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
:mod:`platform` -- access to underlying platform’s identifying data
|
||||
===================================================================
|
||||
|
||||
.. module:: platform
|
||||
:synopsis: access to underlying platform’s identifying data
|
||||
|
||||
|see_cpython_module| :mod:`python:platform`.
|
||||
|
||||
This module tries to retrieve as much platform-identifying data as possible. It
|
||||
makes this information available via function APIs.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: platform()
|
||||
|
||||
Returns a string identifying the underlying platform. This string is composed
|
||||
of several substrings in the following order, delimited by dashes (``-``):
|
||||
|
||||
- the name of the platform system (e.g. Unix, Windows or MicroPython)
|
||||
- the MicroPython version
|
||||
- the architecture of the platform
|
||||
- the version of the underlying platform
|
||||
- the concatenation of the name of the libc that MicroPython is linked to
|
||||
and its corresponding version.
|
||||
|
||||
For example, this could be
|
||||
``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``.
|
||||
|
||||
.. function:: python_compiler()
|
||||
|
||||
Returns a string identifying the compiler used for compiling MicroPython.
|
||||
|
||||
.. function:: libc_ver()
|
||||
|
||||
Returns a tuple of strings *(lib, version)*, where *lib* is the name of the
|
||||
libc that MicroPython is linked to, and *version* the corresponding version
|
||||
of this libc.
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -66,6 +66,17 @@ For running PIO programs, see :class:`rp2.StateMachine`.
|
|||
>>> rp2.asm_pio_encode("set(0, 1)", 0)
|
||||
57345
|
||||
|
||||
.. function:: bootsel_button()
|
||||
|
||||
Temporarily turns the QSPI_SS pin into an input and reads its value,
|
||||
returning 1 for low and 0 for high.
|
||||
On a typical RP2040 board with a BOOTSEL button, a return value of 1
|
||||
indicates that the button is pressed.
|
||||
|
||||
Since this function temporarily disables access to the external flash
|
||||
memory, it also temporarily disables interrupts and the other core to
|
||||
prevent them from trying to execute code from flash.
|
||||
|
||||
.. class:: PIOASMError
|
||||
|
||||
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is
|
||||
|
|
|
@ -15,21 +15,11 @@ 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)
|
||||
|
||||
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
|
||||
``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``
|
||||
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.
|
||||
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
|
||||
|
@ -38,13 +28,40 @@ Functions
|
|||
- *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, wrapping the underlying stream.
|
||||
The returned object has the usual `stream` interface methods like
|
||||
``read()``, ``write()``, etc.
|
||||
|
||||
- *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
|
||||
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.
|
||||
|
||||
- *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.
|
||||
|
|
|
@ -102,3 +102,39 @@ the second CPU, the RF core.
|
|||
Execute a HCI command on the SYS channel. The execution is synchronous.
|
||||
|
||||
Returns a bytes object with the result of the SYS command.
|
||||
|
||||
Functions specific to STM32WLxx MCUs
|
||||
------------------------------------
|
||||
|
||||
These functions are available on STM32WLxx microcontrollers, and interact with
|
||||
the integrated "SUBGHZ" radio modem peripheral.
|
||||
|
||||
.. function:: subghz_cs(level)
|
||||
|
||||
Sets the internal SPI CS pin attached to the radio peripheral. The ``level``
|
||||
argument is active-low: a truthy value means "CS pin high" and de-asserts the
|
||||
signal, a falsey value means "CS pin low" and asserts the signal.
|
||||
|
||||
The internal-only SPI bus corresponding to this CS signal can be instantiated
|
||||
using :ref:`machine.SPI()<machine.SPI>` ``id`` value ``"SUBGHZ"``.
|
||||
|
||||
.. function:: subghz_irq(handler)
|
||||
|
||||
Sets the internal SUBGHZ radio interrupt handler to the provided
|
||||
function. The handler function is called as a "hard" interrupt in response to
|
||||
radio peripheral interrupts. See :ref:`isr_rules` for more information about
|
||||
interrupt handlers in MicroPython.
|
||||
|
||||
Calling this function with the handler argument set to None disables the IRQ.
|
||||
|
||||
Due to a hardware limitation, each time this IRQ fires MicroPython disables
|
||||
it before calling the handler. In order to receive another interrupt, Python
|
||||
code should call ``subghz_irq()`` to set the handler again. This has the side
|
||||
effect of re-enabling the IRQ.
|
||||
|
||||
.. function:: subghz_is_busy()
|
||||
|
||||
Return a ``bool`` corresponding to the internal "RFBUSYS" signal from the
|
||||
radio peripheral. Before sending a new command to the radio over SPI then
|
||||
this function should be polled until it returns ``False``, to confirm the
|
||||
busy signal is de-asserted.
|
||||
|
|
|
@ -46,7 +46,7 @@ Functions
|
|||
.. function:: settrace(tracefunc)
|
||||
|
||||
Enable tracing of bytecode execution. For details see the `CPython
|
||||
documentaion <https://docs.python.org/3/library/sys.html#sys.settrace>`_.
|
||||
documentation <https://docs.python.org/3/library/sys.html#sys.settrace>`_.
|
||||
|
||||
This function requires a custom MicroPython build as it is typically not
|
||||
present in pre-built firmware (due to it affecting performance). The relevant
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ controlling its operation:
|
|||
|
||||
.. method:: WM8960.expand_3d(level)
|
||||
|
||||
Enable Stereo 3D exansion. *level* is a number between 0 and 15.
|
||||
Enable Stereo 3D expansion. *level* is a number between 0 and 15.
|
||||
A value of 0 disables the expansion.
|
||||
|
||||
.. method:: WM8960.mono(active)
|
||||
|
|
|
@ -34,5 +34,5 @@ Methods
|
|||
|
||||
These methods implement the simple and extended
|
||||
:ref:`block protocol <block-device-interface>` defined by
|
||||
:class:`uos.AbstractBlockDev`.
|
||||
:class:`os.AbstractBlockDev`.
|
||||
|
||||
|
|
|
@ -37,4 +37,4 @@ Methods
|
|||
|
||||
These methods implement the simple and extended
|
||||
:ref:`block protocol <block-device-interface>` defined by
|
||||
:class:`uos.AbstractBlockDev`.
|
||||
:class:`os.AbstractBlockDev`.
|
||||
|
|
|
@ -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
|
||||
<https://docs.zephyrproject.org/latest/guides/debug_tools/thread-analyzer.html#thread-analyzer>`_.
|
||||
|
||||
.. function:: shell_exec(cmd_in)
|
||||
|
|
|
@ -1,38 +1,82 @@
|
|||
:mod:`zlib` -- zlib decompression
|
||||
=================================
|
||||
:mod:`zlib` -- zlib compression & decompression
|
||||
===============================================
|
||||
|
||||
.. module:: zlib
|
||||
:synopsis: zlib decompression
|
||||
:synopsis: zlib compression & decompression
|
||||
|
||||
|see_cpython_module| :mod:`python:zlib`.
|
||||
|
||||
This module allows to decompress binary data compressed with
|
||||
This module allows compression and decompression of binary data with the
|
||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_
|
||||
(commonly used in zlib library and gzip archiver). Compression
|
||||
is not yet implemented.
|
||||
(commonly used in the zlib library and gzip archiver).
|
||||
|
||||
.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this
|
||||
module as it provides a streaming interface to compression and decompression
|
||||
which is convenient and more memory efficient when working with reading or
|
||||
writing compressed data to a file, socket, or stream.
|
||||
|
||||
**Availability:**
|
||||
|
||||
* From MicroPython v1.21 onwards, this module may not be present by default on
|
||||
all MicroPython firmware as it duplicates functionality available in
|
||||
the :mod:`deflate <deflate>` module.
|
||||
|
||||
* A copy of this module can be installed (or frozen)
|
||||
from :term:`micropython-lib` (`source <https://github.com/micropython/micropython-lib/blob/master/python-stdlib/zlib/zlib.py>`_).
|
||||
See :ref:`packages` for more information. This documentation describes that module.
|
||||
|
||||
* Requires the built-in :mod:`deflate <deflate>` module (available since MicroPython v1.21)
|
||||
|
||||
* Compression support will only be available if compression support is enabled
|
||||
in the built-in :mod:`deflate <deflate>` module.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: decompress(data, wbits=0, bufsize=0, /)
|
||||
.. function:: decompress(data, wbits=15, /)
|
||||
|
||||
Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window
|
||||
size used during compression (8-15, the dictionary size is power of 2 of
|
||||
that value). Additionally, if value is positive, *data* is assumed to be
|
||||
zlib stream (with zlib header). Otherwise, if it's negative, it's assumed
|
||||
to be raw DEFLATE stream. *bufsize* parameter is for compatibility with
|
||||
CPython and is ignored.
|
||||
Decompresses *data* into a bytes object.
|
||||
|
||||
.. class:: DecompIO(stream, wbits=0, /)
|
||||
The *wbits* parameter works the same way as for :meth:`zlib.compress`
|
||||
with the following additional valid values:
|
||||
|
||||
Create a `stream` wrapper which allows transparent decompression of
|
||||
compressed data in another *stream*. This allows to process compressed
|
||||
streams with data larger than available heap size. In addition to
|
||||
values described in :func:`decompress`, *wbits* may take values
|
||||
24..31 (16 + 8..15), meaning that input stream has gzip header.
|
||||
* ``0``: Automatically determine the window size from the zlib header
|
||||
(*data* must be in zlib format).
|
||||
* ``35`` to ``47``: Auto-detect either the zlib or gzip format.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
As for :meth:`zlib.compress`, see the :mod:`CPython documentation for zlib <python:zlib>`
|
||||
for more information about the *wbits* parameter. As for :meth:`zlib.compress`,
|
||||
MicroPython also supports smaller window sizes than CPython. See more
|
||||
:ref:`MicroPython-specific details <deflate_wbits>` in the
|
||||
:mod:`deflate <deflate>` module documentation.
|
||||
|
||||
This class is MicroPython extension. It's included on provisional
|
||||
basis and may be changed considerably or removed in later versions.
|
||||
If the data to be decompressed requires a larger window size, it will
|
||||
fail during decompression.
|
||||
|
||||
.. function:: compress(data, wbits=15, /)
|
||||
|
||||
Compresses *data* into a bytes object.
|
||||
|
||||
*wbits* allows you to configure the DEFLATE dictionary window size and the
|
||||
output format. The window size allows you to trade-off memory usage for
|
||||
compression level. A larger window size will allow the compressor to
|
||||
reference fragments further back in the input. The output formats are "raw"
|
||||
DEFLATE (no header/footer), zlib, and gzip, where the latter two
|
||||
include a header and checksum.
|
||||
|
||||
The low four bits of the absolute value of *wbits* set the base-2 logarithm of
|
||||
the DEFLATE dictionary window size. So for example, ``wbits=10``,
|
||||
``wbits=-10``, and ``wbits=26`` all set the window size to 1024 bytes. Valid
|
||||
window sizes are ``5`` to ``15`` inclusive (corresponding to 32 to 32k bytes).
|
||||
|
||||
Negative values of *wbits* between ``-5`` and ``-15`` correspond to "raw"
|
||||
output mode, positive values between ``5`` and ``15`` correspond to zlib
|
||||
output mode, and positive values between ``21`` and ``31`` correspond to
|
||||
gzip output mode.
|
||||
|
||||
See the :mod:`CPython documentation for zlib <python:zlib>` for more
|
||||
information about the *wbits* parameter. Note that MicroPython allows
|
||||
for smaller window sizes, which is useful when memory is constrained while
|
||||
still achieving a reasonable level of compression. It also speeds up
|
||||
the compressor. See more :ref:`MicroPython-specific details <deflate_wbits>`
|
||||
in the :mod:`deflate <deflate>` module documentation.
|
||||
|
|
|
@ -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
|
||||
Olimex RT1010Py - RxD/TxD D5/D6 -
|
||||
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
|
||||
================ =========== =========== =========== ===========
|
||||
Adafruit Metro M7 - D0/D1 D7/D3 A1/A0
|
||||
Olimex RT1010Py - RxD/TxD D7/D8 D5/D6
|
||||
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.
|
|
@ -92,9 +92,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
|
|||
|
||||
Available Pins follow the ranges and labelling of the respective board, like:
|
||||
|
||||
- 0-33 for Teensy 4.0,
|
||||
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
|
||||
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
|
||||
- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
|
||||
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
|
||||
|
||||
or the pin names of the Pin.board or Pin.cpu classes.
|
||||
|
@ -106,9 +104,9 @@ Notes:
|
|||
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
|
||||
default not connected to the MCU. For details refer to the schematics.
|
||||
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
|
||||
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
|
||||
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
|
||||
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
|
||||
- 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected.
|
||||
- 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
|
||||
- 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected.
|
||||
|
||||
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
|
||||
which can be used to invert a pin. Useful for illuminating active-low LEDs
|
||||
|
@ -145,22 +143,23 @@ 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('D2'), 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)
|
||||
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
|
||||
|
||||
# Create a group of four synchronized signals.
|
||||
# Start with Pin(4) at submodule 0, which creates the sync pulse.
|
||||
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
|
||||
# Pins 5, 6, and 9 are pins at the same module
|
||||
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
|
||||
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
|
||||
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
|
||||
# Start with Pin('D4') at submodule 0, which creates the sync pulse.
|
||||
pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD)
|
||||
# Pins D5, D6, and D9 are pins at the same module
|
||||
pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
|
||||
pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
|
||||
pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
|
||||
|
||||
pwm3 # show the PWM objects properties
|
||||
|
||||
|
@ -206,8 +205,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.
|
||||
|
@ -254,7 +254,7 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
|
|||
|
||||
from machine import ADC
|
||||
|
||||
adc = ADC(Pin(32)) # create ADC object on ADC pin
|
||||
adc = ADC(Pin('A2')) # create ADC object on ADC pin
|
||||
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
|
||||
|
||||
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
|
||||
|
@ -272,7 +272,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(0), mosi=Pin(2), miso=Pin(4))
|
||||
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4'))
|
||||
|
||||
spi.init(baudrate=200000) # set the baudrate
|
||||
|
||||
|
@ -301,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
|
|||
from machine import SPI, Pin
|
||||
|
||||
spi = SPI(0, 10000000)
|
||||
cs_pin = Pin(6, Pin.OUT, value=1)
|
||||
cs_pin = Pin('D6', Pin.OUT, value=1)
|
||||
cs_pin(0)
|
||||
spi.write('Hello World')
|
||||
cs_pin(1)
|
||||
|
@ -329,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
|
|||
|
||||
from machine import Pin, SoftI2C
|
||||
|
||||
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
|
||||
i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000)
|
||||
|
||||
i2c.scan() # scan for devices
|
||||
|
||||
|
@ -363,7 +363,7 @@ See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a si
|
|||
external Codec like UDA1334.::
|
||||
|
||||
from machine import I2S, Pin
|
||||
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
|
||||
i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'),
|
||||
mode=I2S.TX, bts=16,format=I2S.STEREO,
|
||||
rate=44100,ibuf=40000)
|
||||
i2s.write(buf) # write buffer of audio samples to I2S device
|
||||
|
@ -395,7 +395,7 @@ Example using the Teensy audio shield::
|
|||
|
||||
from machine import I2C, I2S, Pin
|
||||
from sgtl5000 import CODEC
|
||||
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
|
||||
i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'),
|
||||
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
|
||||
ibuf=40000,
|
||||
)
|
||||
|
@ -473,7 +473,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
|
||||
|
@ -503,12 +503,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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import os
|
||||
|
||||
# Directory that the project lives in, aka ../..
|
||||
SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2])
|
||||
SITE_ROOT = "/".join(os.path.dirname(__file__).split("/")[0:-2])
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
"%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it.
|
||||
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
|
||||
"%s/templates/"
|
||||
% SITE_ROOT, # Your custom template directory, before the RTD one to override it.
|
||||
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
|
||||
)
|
||||
|
|
|
@ -75,7 +75,7 @@ Execute the next instruction if <condition> is true:
|
|||
|
||||
* ite(<condition>) If then else
|
||||
|
||||
If <condtion> is true, execute the next instruction, otherwise execute the
|
||||
If <condition> 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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -32,7 +32,7 @@ Glossary
|
|||
|
||||
callee-owned tuple
|
||||
This is a MicroPython-specific construct where, for efficiency
|
||||
reasons, some built-in functions or methods may re-use the same
|
||||
reasons, some built-in functions or methods may reuse the same
|
||||
underlying tuple object to return data. This avoids having to allocate
|
||||
a new tuple for every call, and reduces heap fragmentation. Programs
|
||||
should not hold references to callee-owned tuples and instead only
|
||||
|
@ -120,7 +120,7 @@ Glossary
|
|||
<https://github.com/micropython/micropython-lib>`_ 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
|
||||
|
|
|
@ -31,3 +31,4 @@ implementation and the best practices to use them.
|
|||
asm_thumb2_index.rst
|
||||
filesystem.rst
|
||||
pyboard.py.rst
|
||||
micropython2_migration.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
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
.. _micropython2_migration:
|
||||
|
||||
MicroPython 2.0 Migration Guide
|
||||
===============================
|
||||
|
||||
MicroPython 2.0 is the (currently in development, not yet available) next major
|
||||
release of MicroPython.
|
||||
|
||||
After maintaining API compatibility for almost a decade with the ``1.x`` series, in
|
||||
order to unblock some project-wide improvements MicroPython 2.0 will introduce a
|
||||
small number of breaking API changes that will require some programs to be
|
||||
updated. This guide explains how to update your Python code to accommodate these
|
||||
changes.
|
||||
|
||||
This document is a work-in-progress. As more work is done on MicroPython 2.0,
|
||||
more items will be added to the lists below.
|
||||
|
||||
**Note:** There are currently no MicroPython 2.0 firmware builds available for
|
||||
download. You can build it yourself by enabling the ``MICROPY_PREVIEW_VERSION_2``
|
||||
config option. As it gets closer to being ready for release, builds will be
|
||||
provided for both ``1.x.y`` and ``2.0.0-preview``.
|
||||
|
||||
Hardware and peripherals
|
||||
------------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The goal is to improve consistency in the :mod:`machine` APIs across different
|
||||
ports, making it easier to write code, documentation, and tutorials that work on
|
||||
any supported microcontroller.
|
||||
|
||||
This means that some ports' APIs need to change to match other ports.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
||||
|
||||
OS & filesystem
|
||||
---------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The primary goal is to support the ability to execute :term:`.mpy files <.mpy
|
||||
file>` directly from the filesystem without first copying them into RAM. This
|
||||
improves code deployment time and reduces memory overhead and fragmentation.
|
||||
|
||||
Additionally, a further goal is to support a more flexible way of configuring
|
||||
partitions, filesystem types, and options like USB mass storage.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
||||
|
||||
CPython compatibility
|
||||
---------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The goal is to improve compatibility with CPython by removing MicroPython
|
||||
extensions from CPython APIs. In most cases this means moving existing
|
||||
MicroPython-specific functions or classes to new modules.
|
||||
|
||||
This makes it easier to write code that works on both CPython and MicroPython,
|
||||
which is useful for development and testing.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
|
@ -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 <https://pypa.github.io/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 <mpremote_examples>` 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 ``<command name> [--options] [args...]``. For commands
|
||||
that support multiple arguments (e.g. a list of files), the argument list can
|
||||
be terminated with ``+``.
|
||||
|
||||
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.
|
||||
|
||||
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 <mpremote_reset>` for more details.
|
||||
|
||||
Multiple commands can be specified and they will be run sequentially.
|
||||
|
||||
The full list of supported commands are:
|
||||
|
||||
- connect to a specified device via a device-name shortcut:
|
||||
- `connect <mpremote_command_connect>`
|
||||
- `disconnect <mpremote_command_disconnect>`
|
||||
- `resume <mpremote_command_resume>`
|
||||
- `soft_reset <mpremote_command_soft_reset>`
|
||||
- `repl <mpremote_command_repl>`
|
||||
- `eval <mpremote_command_eval>`
|
||||
- `exec <mpremote_command_exec>`
|
||||
- `run <mpremote_command_run>`
|
||||
- `fs <mpremote_command_fs>`
|
||||
- `df <mpremote_command_df>`
|
||||
- `edit <mpremote_command_edit>`
|
||||
- `mip <mpremote_command_mip>`
|
||||
- `mount <mpremote_command_mount>`
|
||||
- `unmount <mpremote_command_unmount>`
|
||||
- `rtc <mpremote_command_rtc>`
|
||||
- `sleep <mpremote_command_sleep>`
|
||||
- `reset <mpremote_command_reset>`
|
||||
- `bootloader <mpremote_command_bootloader>`
|
||||
|
||||
.. code-block:: bash
|
||||
.. _mpremote_command_connect:
|
||||
|
||||
$ mpremote <device-shortcut>
|
||||
|
||||
- connect to specified device via name:
|
||||
- **connect** -- connect to specified device via name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -54,88 +96,184 @@ The full list of supported commands are:
|
|||
- ``list``: list available devices
|
||||
- ``auto``: connect to the first available USB serial port
|
||||
- ``id:<serial>``: connect to the device with USB serial number
|
||||
``<serial>`` (the second entry in the output from the ``connect list``
|
||||
command)
|
||||
- ``port:<path>``: connect to the device with the given path
|
||||
``<serial>`` (the second column from the ``connect list``
|
||||
command output)
|
||||
- ``port:<path>``: connect to the device with the given path (the first column
|
||||
from the ``connect list`` command output
|
||||
- ``rfc2217://<host>:<port>``: connect to the device using serial over TCP
|
||||
(e.g. a networked serial port based on RFC2217)
|
||||
- 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 <mpremote_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 will not be auto-detected.
|
||||
|
||||
.. _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 <mpremote_reset>` is enabled.
|
||||
|
||||
- resume a previous ``mpremote`` session:
|
||||
.. _mpremote_command_resume:
|
||||
|
||||
- **resume** -- maintain existing interpreter state for subsequent commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote resume
|
||||
|
||||
This disables auto soft-reset.
|
||||
This disables :ref:`auto-soft-reset <mpremote_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_reset>`.
|
||||
|
||||
- enter the REPL on the connected device:
|
||||
.. _mpremote_command_repl:
|
||||
|
||||
- **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 <file>``, to capture output of the REPL session to the given
|
||||
file
|
||||
- ``--inject-code <string>``, 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 <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).
|
||||
|
||||
- evaluate and print the result of a Python expression:
|
||||
While the ``repl`` command running, you can use ``Ctrl-]`` or ``Ctrl-x`` to
|
||||
exit.
|
||||
|
||||
**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 <mpremote_reset>`, 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 <string>
|
||||
|
||||
- execute the given Python code:
|
||||
.. _mpremote_command_exec:
|
||||
|
||||
- **exec** -- execute the given Python code:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mpremote exec <string>
|
||||
|
||||
- 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 <file>
|
||||
$ mpremote run <file.py>
|
||||
|
||||
- execute filesystem commands on the device:
|
||||
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.
|
||||
|
||||
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 <command>
|
||||
$ mpremote fs <sub-command>
|
||||
|
||||
``<command>`` may be:
|
||||
``<sub-command>`` may be:
|
||||
|
||||
- ``cat <file..>`` to show the contents of a file or files on the device
|
||||
- ``ls`` to list the current directory
|
||||
- ``ls <dirs...>`` to list the given directories
|
||||
- ``cp [-r] <src...> <dest>`` to copy files; use ":" as a prefix to specify
|
||||
a file on the device
|
||||
- ``cp [-r] <src...> <dest>`` to copy files
|
||||
- ``rm <src...>`` to remove files on the device
|
||||
- ``mkdir <dirs...>`` to create directories on the device
|
||||
- ``rmdir <dirs...>`` to remove directories on the device
|
||||
- ``touch <file..>`` 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
|
||||
<https://en.wikipedia.org/wiki/Secure_copy_protocol>`_. 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 <mpremote_shortcuts>`, 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 +284,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 +294,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] <local-dir>
|
||||
|
||||
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 <filesystem>` 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 +330,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 +407,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 <sub-command>``
|
||||
|
||||
- ``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
|
||||
|
||||
Any user configuration, including user-defined shortcuts, can be placed in the file
|
||||
``.config/mpremote/config.py``. For example:
|
||||
"c33": "connect id:334D335C3138",
|
||||
|
||||
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 +468,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 +486,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 <mpremote_shortcuts>` above.
|
||||
|
||||
mpremote ls
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote c1
|
||||
|
||||
Connect to the device at ``COM1`` (Windows) and implicitly run the ``repl``
|
||||
command. See :ref:`shortcuts <mpremote_shortcuts>` above.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mpremote connect /dev/ttyUSB0
|
||||
|
||||
Explicitly specify which device to connect to, and as above, implicitly run the
|
||||
``repl`` command.
|
||||
|
||||
.. 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`.
|
||||
|
|
|
@ -86,7 +86,9 @@ and .mpy version.
|
|||
=================== ============
|
||||
MicroPython release .mpy version
|
||||
=================== ============
|
||||
v1.19 and up 6
|
||||
v1.22.0 and up 6.2
|
||||
v1.20 - v1.21.0 6.1
|
||||
v1.19.x 6
|
||||
v1.12 - v1.18 5
|
||||
v1.11 4
|
||||
v1.9.3 - v1.10 3
|
||||
|
@ -100,6 +102,8 @@ MicroPython repository at which the .mpy version was changed.
|
|||
=================== ========================================
|
||||
.mpy version change Git commit
|
||||
=================== ========================================
|
||||
6.1 to 6.2 6967ff3c581a66f73e9f3d78975f47528db39980
|
||||
6 to 6.1 d94141e1473aebae0d3c63aeaa8397651ad6fa01
|
||||
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
|
||||
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517
|
||||
3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e
|
||||
|
@ -146,8 +150,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
|
||||
====== ================================
|
||||
|
||||
|
|
|
@ -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
|
||||
-----------------
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 <https://www.mikroe.com/ra4m1-clicker>`_
|
||||
For the manual and other references for the board and RA Family MCU, please refer to the web page: `RA4M1 CLICKER <https://www.mikroe.com/ra4m1-clicker>`_
|
||||
|
||||
* EK-RA6M2
|
||||
|
||||
|
|
|
@ -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.
|
||||
>>>
|
||||
|
|
|
@ -12,9 +12,8 @@ To list supported modules, please enter::
|
|||
|
||||
help('modules')
|
||||
|
||||
Especially `machine` module and class :ref:`machine.Pin <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 <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'.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
sphinx~=7.2.6
|
||||
sphinxcontrib.jquery==4.1
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue