ESP32 Confusing behaviour of PWM after soft reset
Consider:
from machine import Pin, PWM
pin = Pin(23, Pin.OUT)
pwm = PWM(pin, freq=38000, duty=338)
This works as expected. If you issue ctrl-d the waveform on the pin continues unchanged. If you paste the above code again, you cause a low output with
pwm.duty(0)
Subsequently changing the duty value to a value > 0 has no effect. This is surprising.
There is a simple workround of issuing pwm.deinit() at the start. The current state could be confusing to newcomers. It should either be documented or changed so that a soft reset de-initialises any PWM instance.
esp32/machine_pwm.c: Handle multiple timers: Bugfix PWM.deinit() critical error and fix pwm_print()
This PR is inherited from esp32/machine_pwm: handle multiple timers. #6276 and replace it.
This PR uses PR ESP32: New feature: EspError exception #6638
This PR was tested together with PR ESP32: New features PCNT() and QUAD() #6639
It is tested with 4 different frequencies at 8 different channels with different duties.
Frequencies and duties are right on proper pins.
from machine import Pin, PWM
import pcnt
P1 = 15
P2 = 2
P3 = 0
P4 = 4
P5 = 18
P6 = 21
P7 = 22
P8 = 23
C1 = 14
C2 = 27
C3 = 26
C4 = 25
C5 = 33
C6 = 32
C7 = 35
C8 = 34
DIR1 = 5
f = 1 # 1..4
d = int(1024 / 9)
cnt1 = None
cnt2 = None
cnt3 = None
cnt4 = None
cnt5 = None
cnt6 = None
cnt7 = None
cnt8 = None
pwm1 = None
pwm2 = None
pwm3 = None
pwm4 = None
pwm5 = None
pwm6 = None
pwm7 = None
pwm8 = None
def prnt():
global cnt1, cnt2, cnt3, cnt4, cnt5, cnt6, cnt7, cnt8
global pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, pwm8
cnt1.filter_disable()
cnt2.filter_disable()
cnt3.filter_disable()
cnt4.filter_disable()
cnt5.filter_disable()
cnt6.filter_disable()
cnt7.filter_disable()
cnt8.filter_disable()
print(pwm1)
print(pwm2)
print(pwm3)
print(pwm4)
print(pwm5)
print(pwm6)
print(pwm7)
print(pwm8)
print(cnt1)
print(cnt2)
print(cnt3)
print(cnt4)
print(cnt5)
print(cnt6)
print(cnt7)
print(cnt8)
def init1():
global cnt1, cnt2, cnt3, cnt4, cnt5, cnt6, cnt7, cnt8
global pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, pwm8
pwm1 = PWM(Pin(P1), freq=f*1, duty=d*1) # 1024-1 == 100% # 512-1 == 50%
pwm2 = PWM(Pin(P2), freq=f*1, duty=d*2)
pwm3 = PWM(Pin(P3), freq=f*100, duty=d*3)
pwm4 = PWM(Pin(P4), freq=f*100, duty=d*4-10)
pwm5 = PWM(Pin(P5), freq=f*100000, duty=d*5)
pwm6 = PWM(Pin(P6), freq=f*100000, duty=d*6)
pwm7 = PWM(Pin(P7), freq=f*10000000, duty=1000)#512)
pwm8 = PWM(Pin(P8), freq=f*10000000, duty=256)#512)
cnt1 = pcnt.PCNT(pcnt.Edge.FALL, C1, DIR1, pcnt.PinPull.UP)
cnt2 = pcnt.PCNT(pcnt.Edge.FALL, C2, DIR1, pcnt.PinPull.UP)
cnt3 = pcnt.PCNT(pcnt.Edge.FALL, C3, DIR1, pcnt.PinPull.UP)
cnt4 = pcnt.PCNT(pcnt.Edge.FALL, C4, DIR1, pcnt.PinPull.UP)
cnt5 = pcnt.PCNT(pcnt.Edge.FALL, C5, DIR1, pcnt.PinPull.UP)
cnt6 = pcnt.PCNT(pcnt.Edge.FALL, C6, DIR1, pcnt.PinPull.UP)
cnt7 = pcnt.PCNT(pcnt.Edge.FALL, C7, DIR1, pcnt.PinPull.UP)
cnt8 = pcnt.PCNT(pcnt.Edge.FALL, C8, DIR1, pcnt.PinPull.UP)
prnt()
def init2():
global cnt1, cnt2, cnt3, cnt4, cnt5, cnt6, cnt7, cnt8
global pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, pwm8
pwm1 = PWM(Pin(P1), freq=f*10000000, duty=512) # 1024 == 100% # 512 == 50%
pwm2 = PWM(Pin(P2), freq=f*10000000, duty=512)
pwm3 = PWM(Pin(P3), freq=f*10000, duty=d*6)
pwm4 = PWM(Pin(P4), freq=f*10000, duty=d*5)
pwm5 = PWM(Pin(P5), freq=f*100, duty=d*4)
pwm6 = PWM(Pin(P6), freq=f*100, duty=d*3)
pwm7 = PWM(Pin(P7), freq=f*1, duty=d*2)
pwm8 = PWM(Pin(P8), freq=f*1, duty=d*1)
cnt1 = pcnt.PCNT(pcnt.Edge.BOTH, C1, DIR1, pcnt.PinPull.NONE)
cnt2 = pcnt.PCNT(pcnt.Edge.BOTH, C2, DIR1, pcnt.PinPull.NONE)
cnt3 = pcnt.PCNT(pcnt.Edge.BOTH, C3, DIR1, pcnt.PinPull.NONE)
cnt4 = pcnt.PCNT(pcnt.Edge.BOTH, C4, DIR1, pcnt.PinPull.NONE)
cnt5 = pcnt.PCNT(pcnt.Edge.BOTH, C5, DIR1, pcnt.PinPull.NONE)
cnt6 = pcnt.PCNT(pcnt.Edge.BOTH, C6, DIR1, pcnt.PinPull.NONE)
cnt7 = pcnt.PCNT(pcnt.Edge.BOTH, C7, DIR1, pcnt.PinPull.NONE)
cnt8 = pcnt.PCNT(pcnt.Edge.BOTH, C8, DIR1, pcnt.PinPull.NONE)
prnt()
def deinit_all():
global cnt1, cnt2, cnt3, cnt4, cnt5, cnt6, cnt7, cnt8
global pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, pwm8
print('deinit_all():')
try:
pwm1.deinit()
except:
pass
try:
pwm2.deinit()
except:
pass
try:
pwm3.deinit()
except:
pass
try:
pwm4.deinit()
except:
pass
try:
pwm5.deinit()
except:
pass
try:
pwm6.deinit()
except:
pass
try:
pwm7.deinit()
except:
pass
try:
pwm8.deinit()
except:
pass
try:
cnt1.__del__()
except:
pass
try:
cnt2.__del__()
except:
pass
try:
cnt3.__del__()
except:
pass
try:
cnt4.__del__()
except:
pass
try:
cnt5.__del__()
except:
pass
try:
cnt6.__del__()
except:
pass
try:
cnt7.__del__()
except:
pass
try:
cnt8.__del__()
except:
pass
try:
_c = None
init1()
while True:
c = cnt1.count(), cnt2.count(), cnt3.count(), cnt4.count(), cnt5.count(), cnt6.count(), cnt7.count(), cnt8.count()
if _c != c[1]:
_c = c[1]
#print(c, end=' \r')
print(c)
if _c == 10:
break
pass
deinit_all()
print('')
init2()
while True:
c = cnt1.count(), cnt2.count(), cnt3.count(), cnt4.count(), cnt5.count(), cnt6.count(), cnt7.count(), cnt8.count()
if _c != c[7]:
_c = c[7]
#print(c, end=' \r')
print(c)
if _c == 10:
break
deinit_all()
finally:
print('finally:')
deinit_all()
Output is
>>> %Run -c $EDITOR_CONTENT
PWM(15, freq=1, duty=4(4/1023))
PWM(2, freq=1, duty=4(4/1023))
PWM(0, freq=100, duty=512(512/1023))
PWM(4, freq=100, duty=565(565/1023))
PWM(18, freq=100000, duty=564(282/511))
PWM(21, freq=100000, duty=678(339/511))
PWM(22, freq=10000000, duty=896(7/7))
PWM(23, freq=10000000, duty=256(2/7))
PCNT(unit=0, Pin(14), Pin(5), pin_pull_type=2)
PCNT(unit=1, Pin(27), Pin(5), pin_pull_type=2)
PCNT(unit=2, Pin(26), Pin(5), pin_pull_type=2)
PCNT(unit=3, Pin(25), Pin(5), pin_pull_type=2)
PCNT(unit=4, Pin(33), Pin(5), pin_pull_type=2)
PCNT(unit=5, Pin(32), Pin(5), pin_pull_type=2)
PCNT(unit=6, Pin(35), Pin(5), pin_pull_type=2)
PCNT(unit=7, Pin(34), Pin(5), pin_pull_type=2)
(1, 1, 5, 4, 4846, 4846, 484659, 484723)
(2, 2, 23, 22, 22613, 22613, 2261315, 2261358)
(3, 3, 123, 122, 122612, 122612, 12261240, 12261283)
(4, 4, 223, 222, 222616, 222616, 22261628, 22261670)
(5, 5, 323, 322, 322604, 322604, 32260413, 32260456)
(6, 6, 423, 422, 422610, 422610, 42261029, 42261072)
(7, 7, 523, 522, 522616, 522616, 52261652, 52261694)
(8, 8, 623, 622, 622614, 622614, 62261425, 62261467)
(9, 9, 723, 722, 722609, 722609, 72260934, 72260976)
(10, 10, 823, 822, 822606, 822606, 82260679, 82260722)
deinit_all():
PWM(15, freq=10000000, duty=512(4/7))
PWM(2, freq=10000000, duty=512(4/7))
PWM(0, freq=10000, duty=678(678/1023))
PWM(4, freq=10000, duty=565(565/1023))
PWM(18, freq=100, duty=452(452/1023))
PWM(21, freq=100, duty=339(339/1023))
PWM(22, freq=1, duty=226(226/1023))
PWM(23, freq=1, duty=113(113/1023))
PCNT(unit=0, Pin(14), Pin(5), pin_pull_type=0)
PCNT(unit=1, Pin(27), Pin(5), pin_pull_type=0)
PCNT(unit=2, Pin(26), Pin(5), pin_pull_type=0)
PCNT(unit=3, Pin(25), Pin(5), pin_pull_type=0)
PCNT(unit=4, Pin(33), Pin(5), pin_pull_type=0)
PCNT(unit=5, Pin(32), Pin(5), pin_pull_type=0)
PCNT(unit=6, Pin(35), Pin(5), pin_pull_type=0)
PCNT(unit=7, Pin(34), Pin(5), pin_pull_type=0)
(1029082, 1030001, 1041, 1039, 11, 10, 2, 2)
(2339568, 2339659, 2351, 2349, 24, 24, 2, 3)
(20134572, 20134666, 20145, 20144, 202, 201, 4, 4)
(22341441, 22341537, 22352, 22351, 224, 224, 4, 5)
(40133566, 40133661, 40145, 40143, 402, 401, 6, 6)
(42338735, 42338831, 42349, 42348, 424, 424, 6, 7)
(60147638, 60147733, 60159, 60157, 602, 602, 8, 8)
(62339969, 62340064, 62351, 62349, 624, 624, 8, 9)
(80133437, 80133530, 80144, 80143, 802, 801, 10, 10)
deinit_all():
finally:
deinit_all():
>>>