summaryrefslogtreecommitdiffstatshomepage
path: root/docs/esp32
diff options
context:
space:
mode:
Diffstat (limited to 'docs/esp32')
-rw-r--r--docs/esp32/quickref.rst41
-rw-r--r--docs/esp32/tutorial/pwm.rst220
2 files changed, 207 insertions, 54 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::