-
Notifications
You must be signed in to change notification settings - Fork 143
/
test_pwm.py
207 lines (163 loc) · 7.14 KB
/
test_pwm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import os
import sys
import periphery
from .test import ptest, pokay, passert, AssertRaises
if sys.version_info[0] == 3:
raw_input = input
pwm_chip = None
pwm_channel = None
def test_arguments():
ptest()
# Invalid open types
with AssertRaises("invalid open types", TypeError):
periphery.PWM("foo", 0)
with AssertRaises("invalid open types", TypeError):
periphery.PWM(0, "foo")
def test_open_close():
ptest()
# Open non-existent PWM chip
with AssertRaises("non-existent PWM chip", LookupError):
periphery.PWM(9999, pwm_channel)
# Open non-existent PWM channel
with AssertRaises("non-existent PWM channel", periphery.PWMError):
periphery.PWM(pwm_chip, 9999)
# Open legitimate PWM chip/channel
pwm = periphery.PWM(pwm_chip, pwm_channel)
passert("property chip", pwm.chip == pwm_chip)
passert("property channel", pwm.channel == pwm_channel)
# Initialize period and duty cycle
pwm.period = 5e-3
pwm.duty_cycle = 0
# Set period, check period, check period_ns, check frequency
pwm.period = 1e-3
passert("period is correct", abs(pwm.period - 1e-3) < 1e-4)
passert("period_ns is correct", abs(pwm.period_ns - 1000000) < 1e5)
passert("frequency is correct", abs(pwm.frequency - 1000) < 100)
pwm.period = 5e-4
passert("period is correct", abs(pwm.period - 5e-4) < 1e-5)
passert("period_ns is correct", abs(pwm.period_ns - 500000) < 1e4)
passert("frequency is correct", abs(pwm.frequency - 2000) < 100)
# Set frequency, check frequency, check period, check period_ns
pwm.frequency = 1000
passert("frequency is correct", abs(pwm.frequency - 1000) < 100)
passert("period is correct", abs(pwm.period - 1e-3) < 1e-4)
passert("period_ns is correct", abs(pwm.period_ns - 1000000) < 1e5)
pwm.frequency = 2000
passert("frequency is correct", abs(pwm.frequency - 2000) < 100)
passert("period is correct", abs(pwm.period - 5e-4) < 1e-5)
passert("period_ns is correct", abs(pwm.period_ns - 500000) < 1e4)
# Set period_ns, check period_ns, check period, check frequency
pwm.period_ns = 1000000
passert("period_ns is correct", abs(pwm.period_ns - 1000000) < 1e5)
passert("period is correct", abs(pwm.period - 1e-3) < 1e-4)
passert("frequency is correct", abs(pwm.frequency - 1000) < 100)
pwm.period_ns = 500000
passert("period_ns is correct", abs(pwm.period_ns - 500000) < 1e4)
passert("period is correct", abs(pwm.period - 5e-4) < 1e-5)
passert("frequency is correct", abs(pwm.frequency - 2000) < 100)
pwm.period_ns = 1000000
# Set duty cycle, check duty cycle, check duty_cycle_ns
pwm.duty_cycle = 0.25
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.25) < 1e-3)
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 250000) < 1e4)
pwm.duty_cycle = 0.50
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.50) < 1e-3)
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 500000) < 1e4)
pwm.duty_cycle = 0.75
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.75) < 1e-3)
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 750000) < 1e4)
# Set duty_cycle_ns, check duty_cycle_ns, check duty_cycle
pwm.duty_cycle_ns = 250000
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 250000) < 1e4)
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.25) < 1e-3)
pwm.duty_cycle_ns = 500000
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 500000) < 1e4)
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.50) < 1e-3)
pwm.duty_cycle_ns = 750000
passert("duty_cycle_ns is correct", abs(pwm.duty_cycle_ns - 750000) < 1e4)
passert("duty_cycle is correct", abs(pwm.duty_cycle - 0.75) < 1e-3)
# Set polarity, check polarity
pwm.polarity = "normal"
passert("polarity is normal", pwm.polarity == "normal")
pwm.polarity = "inversed"
passert("polarity is inversed", pwm.polarity == "inversed")
# Set enabled, check enabled
pwm.enabled = True
passert("pwm is enabled", pwm.enabled == True)
pwm.enabled = False
passert("pwm is disabled", pwm.enabled == False)
# Use enable()/disable(), check enabled
pwm.enable()
passert("pwm is enabled", pwm.enabled == True)
pwm.disable()
passert("pwm is disabled", pwm.enabled == False)
# Set invalid polarity
with AssertRaises("set invalid polarity", ValueError):
pwm.polarity = "foo"
pwm.close()
def test_loopback():
ptest()
def test_interactive():
ptest()
pwm = periphery.PWM(pwm_chip, pwm_channel)
print("Starting interactive test. Get out your oscilloscope, buddy!")
raw_input("Press enter to continue...")
# Set initial parameters and enable PWM
pwm.duty_cycle = 0.0
pwm.frequency = 1e3
pwm.polarity = "normal"
pwm.enabled = True
# Check tostring
print("PWM description: {}".format(str(pwm)))
passert("interactive success", raw_input("PWM description looks ok? y/n ") == "y")
# Set 1 kHz frequency, 0.25 duty cycle
pwm.frequency = 1e3
pwm.duty_cycle = 0.25
passert("interactive success", raw_input("Frequency is 1 kHz, duty cycle is 25%? y/n ") == "y")
# Set 1 kHz frequency, 0.50 duty cycle
pwm.frequency = 1e3
pwm.duty_cycle = 0.50
passert("interactive success", raw_input("Frequency is 1 kHz, duty cycle is 50%? y/n ") == "y")
# Set 2 kHz frequency, 0.25 duty cycle
pwm.frequency = 2e3
pwm.duty_cycle = 0.25
passert("interactive success", raw_input("Frequency is 2 kHz, duty cycle is 25%? y/n ") == "y")
# Set 2 kHz frequency, 0.50 duty cycle
pwm.frequency = 2e3
pwm.duty_cycle = 0.50
passert("interactive success", raw_input("Frequency is 2 kHz, duty cycle is 50%? y/n ") == "y")
pwm.duty_cycle = 0.0
pwm.enabled = False
pwm.close()
if __name__ == "__main__":
if os.environ.get("CI") == "true":
test_arguments()
sys.exit(0)
if len(sys.argv) < 3:
print("Usage: python -m tests.test_pwm <PWM chip> <PWM channel>")
print("")
print("[1/4] Arguments test: No requirements.")
print("[2/4] Open/close test: PWM channel should be real.")
print("[3/4] Loopback test: No test.")
print("[4/4] Interactive test: PWM channel should be observed with an oscilloscope or logic analyzer.")
print("")
print("Hint: for Raspberry Pi 3, enable PWM0 and PWM1 with:")
print(" $ echo \"dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4\" | sudo tee -a /boot/config.txt")
print(" $ sudo reboot")
print("Monitor GPIO 18 (header pin 12), and run this test with:")
print(" python -m tests.test_pwm 0 0")
print("or, monitor GPIO 13 (header pin 33), and run this test with:")
print(" python -m tests.test_pwm 0 1")
print("")
sys.exit(1)
pwm_chip = int(sys.argv[1])
pwm_channel = int(sys.argv[2])
test_arguments()
pokay("Arguments test passed.")
test_open_close()
pokay("Open/close test passed.")
test_loopback()
pokay("Loopback test passed.")
test_interactive()
pokay("Interactive test passed.")
pokay("All tests passed!")