-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbasicPWM.py
147 lines (124 loc) · 5.71 KB
/
basicPWM.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
import os
import logging
class basicPWM:
def __init__(self):
self.active = False
def startup(self, period=10000, dutyCycle=0):
self.active = True
def update(self, dutyCycle=0):
pass
def shutdown(self):
self.active = False
def status(self):
# TODO: String about PWM status?
pass
class hardwarePWM(basicPWM):
def __init__(self, pwmToUse=0):
self.pwmToUse = pwmToUse
if os.path.isdir('/sys/class/pwm/pwmchip0') and os.access('/sys/class/pwm/pwmchip0/export', os.W_OK):
logging.info('Initializing hardware PWM%s', self.pwmToUse)
else:
raise RuntimeError('Unable to access /sys/class/pwm/pwmchip0')
if not os.path.isdir(f'/sys/class/pwm/pwmchip0/pwm{self.pwmToUse}'):
logging.debug('Exporting hardware PWM%s', pwmToUse)
with open('/sys/class/pwm/pwmchip0/export', 'w', encoding='UTF-8') as p:
p.write(f'{pwmToUse}\n')
super().__init__()
def startup(self, period=18300, dutyCycle=0):
logging.debug('Starting hardware PWM%s with period of %s', self.pwmToUse, period)
with open(f'/sys/class/pwm/pwmchip0/pwm{self.pwmToUse}/period', 'w', encoding='UTF-8') as p:
p.write(f'{period}\n')
self.update(dutyCycle)
logging.info('Enabling hardware PWM%s', self.pwmToUse)
with open(f'/sys/class/pwm/pwmchip0/pwm{self.pwmToUse}/enable', 'w', encoding='UTF-8') as p:
p.write('1\n')
super().startup()
def update(self, dutyCycle=0):
logging.info('Updating hardware PWM%s duty cycle to %s', self.pwmToUse, dutyCycle*61)
with open(f'/sys/class/pwm/pwmchip0/pwm{self.pwmToUse}/duty_cycle', 'w', encoding='UTF-8') as p:
p.write(f'{dutyCycle*61}\n')
super().update()
def shutdown(self):
logging.debug('Shutting down hardware PWM%s', self.pwmToUse)
self.update() #Duty Cycle to 0
logging.info('Disabling hardware PWM%s', self.pwmToUse)
with open(f'/sys/class/pwm/pwmchip0/pwm{self.pwmToUse}/enable', 'w', encoding='UTF-8') as p:
p.write('0\n')
super().shutdown()
class softwarePWM(basicPWM):
def __init__(self, pinToUse=7):
logging.info('Initializing software PWM on pin %s', pinToUse)
global GPIO
from RPi import GPIO
self.pinToUse = pinToUse
self.pwm = None
# TODO: Ponder if import RPi.GPIO as GPIO is a good idea
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.pinToUse, GPIO.OUT)
GPIO.output(self.pinToUse,0)
super().__init__()
def startup(self, period=10000, dutyCycle=0):
logging.debug('Starting software PWM on pin %s with period of %s', self.pinToUse, period)
self.pwm = GPIO.PWM(self.pinToUse, period)
logging.info('Updating software PWM on pin %s initial duty cycle to %s', self.pinToUse, round(dutyCycle/3,2))
self.pwm.start(dutyCycle/3)
super().startup()
def update(self, dutyCycle=0):
logging.info('Updating software PWM on pin %s duty cycle to %s', self.pinToUse, round(dutyCycle/3,2))
self.pwm.ChangeDutyCycle(dutyCycle/3)
super().update()
def shutdown(self):
logging.debug('Shutting down software PWM on pin %s', self.pinToUse)
self.pwm.stop()
logging.info('Cleaning up software PWM on pin %s', self.pinToUse)
GPIO.cleanup()
super().shutdown()
class hardwareBBBPWM(basicPWM):
def __init__(self, pwmInfo='P9_16,1,B'):
(self.pinToUse, self.pwmToUse, self.ABToUse) = pwmInfo.split(',', 2)
logging.info('Initializing hardware PWM on pin %s', self.pinToUse)
if self.pwmToUse == '0':
self.pwmToUse = '48300200'
elif self.pwmToUse == '2':
self.pwmToUse = '48304200'
else: # Make 1 the default case
self.pwmToUse = '48302200'
self.ABToUse = '0' if self.ABToUse == 'A' else '1'
if os.path.isfile(f'/sys/devices/platform/ocp/ocp:{self.pinToUse}_pinmux/state'):
logging.info('Configuring pin %s for PWM', self.pinToUse)
with open(f'/sys/devices/platform/ocp/ocp:{self.pinToUse}_pinmux/state', 'w', encoding='UTF-8') as p:
p.write('pwm\n')
else:
raise RuntimeError(f'Unable to access /sys/devices/platform/ocp/ocp:{self.pinToUse}_pinmux/state')
with os.scandir('/sys/class/pwm/') as chips:
for chip in chips:
if chip.is_symlink() and self.pwmToUse in os.readlink(chip):
self.pwmToUse = chip.name
logging.debug('PWM hardware is %s', self.pwmToUse)
break
if not os.path.isdir(f'/sys/class/pwm/{self.pwmToUse}/pwm{self.ABToUse}'):
logging.debug('Exporting hardware %s/pwm%s', self.pwmToUse, self.ABToUse)
with open(f'/sys/class/pwm/{self.pwmToUse}/export', 'w', encoding='UTF-8') as p:
p.write(f'{self.ABToUse}\n')
super().__init__()
def startup(self, period=18300, dutyCycle=0):
logging.debug('Starting hardware %s/pwm%s with period of %s', self.pwmToUse, self.ABToUse, period)
with open(f'/sys/class/pwm/{self.pwmToUse}/pwm{self.ABToUse}/period', 'w', encoding='UTF-8') as p:
p.write(f'{period}\n')
self.update(dutyCycle)
logging.info('Enabling hardware %s/pwm%s', self.pwmToUse, self.ABToUse)
with open(f'/sys/class/pwm/{self.pwmToUse}/pwm{self.ABToUse}/enable', 'w', encoding='UTF-8') as p:
p.write('1\n')
super().startup()
def update(self, dutyCycle=0):
logging.info('Updating hardware %s/pwm%s duty cycle to %s', self.pwmToUse, self.ABToUse, dutyCycle*61)
with open(f'/sys/class/pwm/{self.pwmToUse}/pwm{self.ABToUse}/duty_cycle', 'w', encoding='UTF-8') as p:
p.write(f'{dutyCycle*61}\n')
super().update()
def shutdown(self):
logging.debug('Shutting down hardware %s/pwm%s', self.pwmToUse, self.ABToUse)
self.update() #Duty Cycle to 0
logging.info('Disabling hardware %s/pwm%s', self.pwmToUse, self.ABToUse)
with open(f'/sys/class/pwm/{self.pwmToUse}/pwm{self.ABToUse}/enable', 'w', encoding='UTF-8') as p:
p.write('0\n')
super().shutdown()