diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/esp32/quickref.rst | 41 | ||||
-rw-r--r-- | docs/esp32/tutorial/pwm.rst | 220 | ||||
-rw-r--r-- | docs/library/esp32.rst | 23 | ||||
-rw-r--r-- | docs/library/machine.PWM.rst | 14 | ||||
-rw-r--r-- | docs/reference/mpremote.rst | 8 |
5 files changed, 245 insertions, 61 deletions
diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index ccc01099d1..4e70ff255e 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -148,6 +148,7 @@ Required keyword arguments for the constructor: - ``mdc`` and ``mdio`` - :class:`machine.Pin` objects (or integers) specifying the MDC and MDIO pins. - ``phy_type`` - Select the PHY device type. Supported devices are + ``PHY_GENERIC``, ``PHY_LAN8710``, ``PHY_LAN8720``, ``PHY_IP101``, ``PHY_RTL8201``, ``PHY_DP83848``, ``PHY_KSZ8041`` and ``PHY_KSZ8081``. These values are all constants defined in the ``network`` module. @@ -383,7 +384,7 @@ for more details. Use the :ref:`machine.PWM <machine.PWM>` class:: - from machine import Pin, PWM + from machine import Pin, PWM, lightsleep pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin freq = pwm0.freq() # get current frequency @@ -393,7 +394,7 @@ Use the :ref:`machine.PWM <machine.PWM>` class:: pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%) duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535 - pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%) + pwm0.duty_u16(65536*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%) duty_ns = pwm0.duty_ns() # get current pulse width in ns pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%) @@ -402,19 +403,35 @@ Use the :ref:`machine.PWM <machine.PWM>` class:: pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go print(pwm2) # view PWM settings + pwm2.deinit() # turn off PWM on the pin + + pwm0 = PWM(Pin(0), duty_u16=16384) # The output is at a high level 25% of the time. + pwm2 = PWM(Pin(2), duty_u16=16384, invert=1) # The output is at a low level 25% of the time. + + pwm4 = PWM(Pin(4), lightsleep=True) # Allow PWM during light sleep mode + + lightsleep(10*1000) # pwm0, pwm2 goes off, pwm4 stays on during 10s light sleep + # pwm0, pwm2, pwm4 on after 10s light sleep ESP chips have different hardware peripherals: -===================================================== ======== ======== ======== -Hardware specification ESP32 ESP32-S2 ESP32-C3 ------------------------------------------------------ -------- -------- -------- -Number of groups (speed modes) 2 1 1 -Number of timers per group 4 4 4 -Number of channels per group 8 8 6 ------------------------------------------------------ -------- -------- -------- -Different PWM frequencies (groups * timers) 8 4 4 -Total PWM channels (Pins, duties) (groups * channels) 16 8 6 -===================================================== ======== ======== ======== +======================================================= ======== ========= ========== +Hardware specification ESP32 ESP32-S2, ESP32-C2, + ESP32-S3, ESP32-C3, + ESP32-P4 ESP32-C5, + ESP32-C6, + ESP32-H2 +------------------------------------------------------- -------- --------- ---------- +Number of groups (speed modes) 2 1 1 +Number of timers per group 4 4 4 +Number of channels per group 8 8 6 +------------------------------------------------------- -------- --------- ---------- +Different PWM frequencies = (groups * timers) 8 4 4 +Total PWM channels (Pins, duties) = (groups * channels) 16 8 6 +======================================================= ======== ========= ========== + +In light sleep, the ESP32 PWM can only operate in low speed mode, so only 4 timers and +8 channels are available. A maximum number of PWM channels (Pins) are available on the ESP32 - 16 channels, but only 8 different PWM frequencies are available, the remaining 8 channels must diff --git a/docs/esp32/tutorial/pwm.rst b/docs/esp32/tutorial/pwm.rst index 2650284d35..82d43b36f6 100644 --- a/docs/esp32/tutorial/pwm.rst +++ b/docs/esp32/tutorial/pwm.rst @@ -11,16 +11,20 @@ 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:: +* More comprehensive example with all **16 PWM channels and 8 timers**:: + from time import sleep 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) + F = 10000 # Hz + D = 65536 // 16 # 6.25% + pins = (2, 4, 12, 13, 14, 15, 16, 18, 19, 22, 23, 25, 26, 27, 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))) + f = F * (i // 2 + 1) + d = min(65535, D * (i + 1)) + pwms.append(PWM(pin, freq=f, duty_u16=d)) + sleep(2 / f) print(pwms[i]) finally: for pwm in pwms: @@ -31,65 +35,100 @@ low all of the time. 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:: + PWM(Pin(2), freq=10000, duty_u16=4096) + PWM(Pin(4), freq=10000, duty_u16=8192) + PWM(Pin(12), freq=20000, duty_u16=12288) + PWM(Pin(13), freq=20000, duty_u16=16384) + PWM(Pin(14), freq=30030, duty_u16=20480) + PWM(Pin(15), freq=30030, duty_u16=24576) + PWM(Pin(16), freq=40000, duty_u16=28672) + PWM(Pin(18), freq=40000, duty_u16=32768) + PWM(Pin(19), freq=50000, duty_u16=36864) + PWM(Pin(22), freq=50000, duty_u16=40960) + PWM(Pin(23), freq=60060, duty_u16=45056) + PWM(Pin(25), freq=60060, duty_u16=49152) + PWM(Pin(26), freq=69930, duty_u16=53248) + PWM(Pin(27), freq=69930, duty_u16=57344) + PWM(Pin(32), freq=80000, duty_u16=61440) + PWM(Pin(33), freq=80000, duty_u16=65535) + + +* Example of a **smooth frequency change**:: from time import sleep from machine import Pin, PWM - F_MIN = 500 - F_MAX = 1000 + F_MIN = 1000 + F_MAX = 10000 f = F_MIN - delta_f = 1 + delta_f = F_MAX // 50 - p = PWM(Pin(5), f) - print(p) + pwm = PWM(Pin(27), f) while True: - p.freq(f) - - sleep(10 / F_MIN) + pwm.freq(f) + sleep(1 / f) + sleep(0.1) + print(pwm) f += delta_f - if f >= F_MAX or f <= F_MIN: + if f > F_MAX or f < F_MIN: delta_f = -delta_f + print() + if f > F_MAX: + f = F_MAX + elif f < F_MIN: + f = F_MIN - See PWM wave at Pin(5) with an oscilloscope. + See PWM wave on Pin(27) with an oscilloscope. + + Output is:: -* Example of a smooth duty change:: + PWM(Pin(27), freq=998, duty_u16=32768) + PWM(Pin(27), freq=1202, duty_u16=32768) + PWM(Pin(27), freq=1401, duty_u16=32768) + PWM(Pin(27), freq=1598, duty_u16=32768) + ... + PWM(Pin(27), freq=9398, duty_u16=32768) + PWM(Pin(27), freq=9615, duty_u16=32768) + PWM(Pin(27), freq=9804, duty_u16=32768) + PWM(Pin(27), freq=10000, duty_u16=32768) + + PWM(Pin(27), freq=10000, duty_u16=32768) + PWM(Pin(27), freq=9804, duty_u16=32768) + PWM(Pin(27), freq=9615, duty_u16=32768) + PWM(Pin(27), freq=9398, duty_u16=32768) + ... + PWM(Pin(27), freq=1598, duty_u16=32768) + PWM(Pin(27), freq=1401, duty_u16=32768) + PWM(Pin(27), freq=1202, duty_u16=32768) + PWM(Pin(27), freq=998, duty_u16=32768) + + +* Example of a **smooth duty change**:: from time import sleep from machine import Pin, PWM - DUTY_MAX = 2**16 - 1 + DUTY_MAX = 65535 duty_u16 = 0 - delta_d = 16 + delta_d = 256 - p = PWM(Pin(5), 1000, duty_u16=duty_u16) - print(p) + pwm = PWM(Pin(27), freq=1000, duty_u16=duty_u16) while True: - p.duty_u16(duty_u16) + pwm.duty_u16(duty_u16) + sleep(2 / pwm.freq()) + print(pwm) - sleep(1 / 1000) + if duty_u16 >= DUTY_MAX: + print() + sleep(2) + elif duty_u16 <= 0: + print() + sleep(2) duty_u16 += delta_d if duty_u16 >= DUTY_MAX: @@ -99,9 +138,106 @@ low all of the time. duty_u16 = 0 delta_d = -delta_d - See PWM wave at Pin(5) with an oscilloscope. + PWM wave on Pin(27) with an oscilloscope. + + Output is:: + + PWM(Pin(27), freq=998, duty_u16=0) + PWM(Pin(27), freq=998, duty_u16=256) + PWM(Pin(27), freq=998, duty_u16=512) + PWM(Pin(27), freq=998, duty_u16=768) + PWM(Pin(27), freq=998, duty_u16=1024) + ... + PWM(Pin(27), freq=998, duty_u16=64512) + PWM(Pin(27), freq=998, duty_u16=64768) + PWM(Pin(27), freq=998, duty_u16=65024) + PWM(Pin(27), freq=998, duty_u16=65280) + PWM(Pin(27), freq=998, duty_u16=65535) + + PWM(Pin(27), freq=998, duty_u16=65279) + PWM(Pin(27), freq=998, duty_u16=65023) + PWM(Pin(27), freq=998, duty_u16=64767) + PWM(Pin(27), freq=998, duty_u16=64511) + ... + PWM(Pin(27), freq=998, duty_u16=1023) + PWM(Pin(27), freq=998, duty_u16=767) + PWM(Pin(27), freq=998, duty_u16=511) + PWM(Pin(27), freq=998, duty_u16=255) + PWM(Pin(27), freq=998, duty_u16=0) + + +* Example of a **smooth duty change and PWM output inversion**:: + + from utime import sleep + from machine import Pin, PWM + + try: + DUTY_MAX = 65535 + + duty_u16 = 0 + delta_d = 65536 // 32 + + pwm = PWM(Pin(27)) + pwmi = PWM(Pin(32), invert=1) + + while True: + pwm.duty_u16(duty_u16) + pwmi.duty_u16(duty_u16) + + 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 + + sleep(.01) + print(pwm) + print(pwmi) + + finally: + try: + pwm.deinit() + except: + pass + try: + pwmi.deinit() + except: + pass + + Output is:: + + PWM(Pin(27), freq=5000, duty_u16=0) + PWM(Pin(32), freq=5000, duty_u16=32768, invert=1) + PWM(Pin(27), freq=5000, duty_u16=2048) + PWM(Pin(32), freq=5000, duty_u16=2048, invert=1) + PWM(Pin(27), freq=5000, duty_u16=4096) + PWM(Pin(32), freq=5000, duty_u16=4096, invert=1) + PWM(Pin(27), freq=5000, duty_u16=6144) + PWM(Pin(32), freq=5000, duty_u16=6144, invert=1) + PWM(Pin(27), freq=5000, duty_u16=8192) + PWM(Pin(32), freq=5000, duty_u16=8192, invert=1) + ... + + + See PWM waves on Pin(27) and Pin(32) with an oscilloscope. + +Note: New PWM parameters take effect in the next PWM cycle. + + pwm = PWM(2, duty=512) + print(pwm) + >>> PWM(Pin(2), freq=5000, duty=1023) # the duty is not relevant + pwm.init(freq=2, duty=64) + print(pwm) + >>> PWM(Pin(2), freq=2, duty=16) # the duty is not relevant + time.sleep(1 / 2) # wait one PWM period + print(pwm) + >>> PWM(Pin(2), freq=2, duty=64) # the duty is actual + +Note: machine.freq(20_000_000) reduces the highest PWM frequency to 10 MHz. -Note: the Pin.OUT mode does not need to be specified. The channel is initialized +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:: diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index dc35e7905e..24831c58d6 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -80,6 +80,29 @@ Functions 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()`. +.. function:: idf_task_info() + + Returns information about running ESP-IDF/FreeRTOS tasks, which include + MicroPython threads. This data is useful to gain insight into how much time + tasks spend running or if they are blocked for significant parts of time, + and to determine if allocated stacks are fully utilized or might be reduced. + + ``CONFIG_FREERTOS_USE_TRACE_FACILITY=y`` must be set in the board + configuration to make this method available. Additionally configuring + ``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` and + ``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` is recommended to be able to + retrieve the total and per-task runtime and the core ID respectively. + + The return value is a 2-tuple where the first value is the total runtime, + and the second a list of tasks. Each task is a 7-tuple containing: the task + ID, name, current state, priority, runtime, stack high water mark, and the + ID of the core it is running on. Runtime and core ID will be None when the + respective FreeRTOS configuration option is not enabled. + + .. note:: For an easier to use output based on this function you can use the + `utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`_, + which implements a live overview similar to the Unix ``top`` command. + Flash partitions ---------------- diff --git a/docs/library/machine.PWM.rst b/docs/library/machine.PWM.rst index 5f592b8dff..c2b606affd 100644 --- a/docs/library/machine.PWM.rst +++ b/docs/library/machine.PWM.rst @@ -11,20 +11,20 @@ Example usage:: from machine import PWM 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% + # and set freq 50 Hz and duty 12.5% + pwm.duty_u16(32768) # set duty to 50% # reinitialise with a period of 200us, duty of 5us pwm.init(freq=5000, duty_ns=5000) - pwm.duty_ns(3000) # set pulse width to 3us + pwm.duty_ns(3000) # set pulse width to 3us pwm.deinit() Constructors ------------ -.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert) +.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert=False) Construct and return a new PWM object using the following parameters: @@ -40,7 +40,7 @@ Constructors 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. + *invert* is available only on the esp32, mimxrt, nrf, rp2, samd and zephyr ports. Methods ------- @@ -116,10 +116,10 @@ Limitations of PWM resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest 8 bits of *duty_u16* are insignificant. So:: - pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2) + pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2) and:: - pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2 + 255) + pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2 + 255) will generate PWM with the same 50% duty cycle. diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst index 32ca5c246a..bee008c637 100644 --- a/docs/reference/mpremote.rst +++ b/docs/reference/mpremote.rst @@ -234,6 +234,7 @@ The full list of supported commands are: - ``rmdir <dirs...>`` to remove directories on the device - ``touch <file..>`` to create the files (if they don't already exist) - ``sha256sum <file..>`` to calculate the SHA256 sum of files + - ``tree [-vsh] <dirs...>`` to print a tree of the given directories 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 @@ -264,6 +265,13 @@ The full list of supported commands are: There is no supported way to undelete files removed by ``mpremote rm -r :``. Please use with caution. + The ``tree`` command will print a tree of the given directories. + Using the ``--size/-s`` option will print the size of each file, or use + ``--human/-h`` to use a more human readable format. + Note: Directory size is only printed when a non-zero size is reported by the device's filesystem. + The ``-v`` option can be used to include the name of the serial device in + the output. + All other commands implicitly assume the path is a remote path, but the ``:`` can be optionally used for clarity. |