micropython: add micropython component

This commit is contained in:
KY-zhang-X
2022-09-29 12:10:37 +08:00
parent 1514f1cb9b
commit dd76146324
2679 changed files with 354110 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
.. _esp32_tutorial:
MicroPython tutorial for ESP32
==============================
This tutorial is intended to get you started using MicroPython on the ESP32
system-on-a-chip. If it is your first time it is recommended to follow the
tutorial through in the order below. Otherwise the sections are mostly self
contained, so feel free to skip to those that interest you.
The tutorial does not assume that you know Python, but it also does not attempt
to explain any of the details of the Python language. Instead it provides you
with commands that are ready to run, and hopes that you will gain a bit of
Python knowledge along the way. To learn more about Python itself please refer
to `<https://www.python.org>`__.
.. toctree::
:maxdepth: 1
:numbered:
intro.rst
pwm.rst
peripheral_access.rst

View File

@@ -0,0 +1,139 @@
.. _esp32_intro:
Getting started with MicroPython on the ESP32
=============================================
Using MicroPython is a great way to get the most of your ESP32 board. And
vice versa, the ESP32 chip is a great platform for using MicroPython. This
tutorial will guide you through setting up MicroPython, getting a prompt, using
WebREPL, connecting to the network and communicating with the Internet, using
the hardware peripherals, and controlling some external components.
Let's get started!
Requirements
------------
The first thing you need is a board with an 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
UART available to your PC.
Names of pins will be given in this tutorial using the chip names (eg GPIO2)
and it should be straightforward to find which pin this corresponds to on your
particular board.
Powering the board
------------------
If your board has a USB connector on it then most likely it is powered through
this when connected to your PC. Otherwise you will need to power it directly.
Please refer to the documentation for your board for further details.
Getting the firmware
--------------------
The first thing you need to do is download the most recent MicroPython firmware
.bin file to load onto your ESP32 device. You can download it from the
`MicroPython downloads page <https://micropython.org/download#esp32>`_.
From here, you have 3 main choices:
* Stable firmware builds
* Daily firmware builds
* Daily firmware builds with SPIRAM support
If you are just starting with MicroPython, the best bet is to go for the Stable
firmware builds. If you are an advanced, experienced MicroPython ESP32 user
who would like to follow development closely and help with testing new
features, there are daily builds. If your board has SPIRAM support you can
use either the standard firmware or the firmware with SPIRAM support, and in
the latter case you will have access to more RAM for Python objects.
Deploying the firmware
----------------------
Once you have the MicroPython firmware you need to load it onto your ESP32 device.
There are two main steps to do this: first you need to put your device in
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
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
boards, along with the Espressif DevKitC, PICO-KIT, WROVER-KIT dev-kits.
For best results it is recommended to first erase the entire flash of your
device before putting on new MicroPython firmware.
Currently we only support esptool.py to copy across the firmware. You can find
this tool here: `<https://github.com/espressif/esptool/>`__, or install it
using pip::
pip install esptool
Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer).
An older version (at least 1.2.1 is needed) works fine but will require Python
2.7.
Using esptool.py you can erase the flash with the command::
esptool.py --port /dev/ttyUSB0 erase_flash
And then deploy the new firmware using::
esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-20180511-v1.9.4.bin
Notes:
* You might need to change the "port" setting to something else relevant for your
PC
* You may need to reduce the baudrate if you get errors when flashing
(eg down to 115200 by adding ``--baud 115200`` into the command)
* For some boards with a particular FlashROM configuration you may need to
change the flash mode (eg by adding ``-fm dio`` into the command)
* The filename of the firmware should match the file that you have
If the above commands run without error then MicroPython should be installed on
your board!
Serial prompt
-------------
Once you have the firmware on the device you can access the REPL (Python prompt)
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
convertor, depending on your board. The baudrate is 115200.
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
is found at :ref:`esp8266_tutorial` (but skip the Introduction section).
Troubleshooting installation problems
-------------------------------------
If you experience problems during flashing or with running firmware immediately
after it, here are troubleshooting recommendations:
* Be aware of and try to exclude hardware problems. There are 2 common
problems: bad power source quality, and worn-out/defective FlashROM.
Speaking of power source, not just raw amperage is important, but also low
ripple and noise/EMI in general. The most reliable and convenient power
source is a USB port.
* 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
rate may be too high and lead to errors. Try a more common 115200 baud
rate instead in such cases.
* To catch incorrect flash content (e.g. from a defective sector on a chip),
add ``--verify`` switch to the commands above.
* If you still experience problems with flashing the firmware please
refer to esptool.py project page, https://github.com/espressif/esptool
for additional documentation and a bug tracker where you can report problems.
* If you are able to flash the firmware but the ``--verify`` option returns
errors even after multiple retries the you may have a defective FlashROM chip.

View File

@@ -0,0 +1,44 @@
Accessing peripherals directly via registers
============================================
The ESP32's peripherals can be controlled via direct register reads and writes.
This requires reading the datasheet to know what registers to use and what
values to write to them. The following example shows how to turn on and change
the prescaler of the MCPWM0 peripheral.
.. code-block:: python3
from micropython import const
from machine import mem32
# Define the register addresses that will be used.
DR_REG_DPORT_BASE = const(0x3FF00000)
DPORT_PERIP_CLK_EN_REG = const(DR_REG_DPORT_BASE + 0x0C0)
DPORT_PERIP_RST_EN_REG = const(DR_REG_DPORT_BASE + 0x0C4)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x3FF5E000)
MCPWM1 = const(0x3FF6C000)
# Enable CLK and disable RST.
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
mem32[DPORT_PERIP_CLK_EN_REG] |= DPORT_PWM0_CLK_EN
mem32[DPORT_PERIP_RST_EN_REG] &= ~DPORT_PWM0_CLK_EN
print(hex(mem32[DPORT_PERIP_CLK_EN_REG] & 0xffffffff))
print(hex(mem32[DPORT_PERIP_RST_EN_REG] & 0xffffffff))
# Change the MCPWM0 prescaler.
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG (reset value = 0)
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
Note that before a peripheral can be used its clock must be enabled and it must
be taken out of reset. In the above example the following registers are used
for this:
- ``DPORT_PERI_CLK_EN_REG``: used to enable a peripheral clock
- ``DPORT_PERI_RST_EN_REG``: used to reset (or take out of reset) a peripheral
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence
the value of ``DPORT_PWM0_CLK_EN``.

View File

@@ -0,0 +1,115 @@
.. _esp32_pwm:
Pulse Width Modulation
======================
Pulse width modulation (PWM) is a way to get an artificial analog output on a
digital pin. It achieves this by rapidly toggling the pin from low to high.
There are two parameters associated with this: the frequency of the toggling,
and the duty cycle. The duty cycle is defined to be how long the pin is high
compared with the length of a single period (low plus high time). Maximum
duty cycle is when the pin is high all of the time, and minimum is when it is
low all of the time.
* More comprehensive example with all 16 PWM channels and 8 timers::
from machine import Pin, PWM
try:
f = 100 # Hz
d = 1024 // 16 # 6.25%
pins = (15, 2, 4, 16, 18, 19, 22, 23, 25, 26, 27, 14 , 12, 13, 32, 33)
pwms = []
for i, pin in enumerate(pins):
pwms.append(PWM(Pin(pin), freq=f * (i // 2 + 1), duty= 1023 if i==15 else d * (i + 1)))
print(pwms[i])
finally:
for pwm in pwms:
try:
pwm.deinit()
except:
pass
Output is::
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
* Example of a smooth frequency change::
from utime import sleep
from machine import Pin, PWM
F_MIN = 500
F_MAX = 1000
f = F_MIN
delta_f = 1
p = PWM(Pin(5), f)
print(p)
while True:
p.freq(f)
sleep(10 / F_MIN)
f += delta_f
if f >= F_MAX or f <= F_MIN:
delta_f = -delta_f
See PWM wave at Pin(5) with an oscilloscope.
* Example of a smooth duty change::
from utime import sleep
from machine import Pin, PWM
DUTY_MAX = 2**16 - 1
duty_u16 = 0
delta_d = 16
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
print(p)
while True:
p.duty_u16(duty_u16)
sleep(1 / 1000)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
duty_u16 = DUTY_MAX
delta_d = -delta_d
elif duty_u16 <= 0:
duty_u16 = 0
delta_d = -delta_d
See PWM wave at Pin(5) with an oscilloscope.
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
to PWM mode internally once for each Pin that is passed to the PWM constructor.
The following code is wrong::
pwm = PWM(Pin(5, Pin.OUT), freq=1000, duty=512) # Pin(5) in PWM mode here
pwm = PWM(Pin(5, Pin.OUT), freq=500, duty=256) # Pin(5) in OUT mode here, PWM is off
Use this code instead::
pwm = PWM(Pin(5), freq=1000, duty=512)
pwm.init(freq=500, duty=256)