1
+ # pylint: disable=invalid-name
1
2
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2
3
#
3
4
# SPDX-License-Identifier: MIT
4
- """Custom PWMOut Wrapper for Rpi.GPIO PWM Class"""
5
- from RPi import GPIO
6
-
7
- GPIO .setmode (GPIO .BCM ) # Use BCM pins D4 = GPIO #4
8
- GPIO .setwarnings (False ) # shh!
5
+ # pylint: enable=invalid-name
6
+ """ PWMOut Class for lgpio lg library tx_pwm library """
9
7
8
+ import lgpio
9
+ import board # need board to get access to the CHIP object in the pin module
10
10
11
11
# pylint: disable=unnecessary-pass
12
12
class PWMError (IOError ):
@@ -18,47 +18,47 @@ class PWMError(IOError):
18
18
# pylint: enable=unnecessary-pass
19
19
20
20
21
- class PWMOut :
21
+ class PWMOut : # pylint: disable=invalid-name
22
22
"""Pulse Width Modulation Output Class"""
23
23
24
- def __init__ (self , pin , * , frequency = 500 , duty_cycle = 0 , variable_frequency = False ):
25
- self ._pwmpin = None
24
+ def __init__ (self , pin , * , frequency = 500 , duty_cycle = 0 ,
25
+ variable_frequency = False ):
26
+ if variable_frequency :
27
+ print ("Variable Frequency is not supported, ignoring..." )
28
+ self ._pin = pin
29
+ result = lgpio .gpio_claim_output (board .pin .CHIP , self ._pin .id ,
30
+ lFlags = lgpio .SET_PULL_NONE )
31
+ if result < 0 :
32
+ raise RuntimeError (lgpio .error_text (result ))
33
+ self ._enabled = False
34
+ self ._deinited = False
26
35
self ._period = 0
27
- self ._open (pin , duty_cycle , frequency , variable_frequency )
36
+ # set frequency
37
+ self ._frequency = frequency
38
+ # set duty
39
+ self .duty_cycle = duty_cycle
40
+ self .enabled = True
28
41
29
42
def __del__ (self ):
30
43
self .deinit ()
31
44
32
45
def __enter__ (self ):
33
46
return self
34
47
35
- def __exit__ (self , t , value , traceback ):
48
+ def __exit__ (self , exc_type , exc_val , exc_tb ):
36
49
self .deinit ()
37
50
38
- def _open (self , pin , duty = 0 , freq = 500 , variable_frequency = False ):
39
- self ._pin = pin
40
- GPIO .setup (pin .id , GPIO .OUT )
41
- self ._pwmpin = GPIO .PWM (pin .id , freq )
42
-
43
- if variable_frequency :
44
- print ("Variable Frequency is not supported, continuing without it..." )
45
-
46
- # set frequency
47
- self .frequency = freq
48
- # set duty
49
- self .duty_cycle = duty
50
-
51
- self .enabled = True
52
-
53
51
def deinit (self ):
54
52
"""Deinit the PWM."""
55
- if self ._pwmpin is not None :
56
- self ._pwmpin .stop ()
57
- GPIO .cleanup (self ._pin .id )
58
- self ._pwmpin = None
53
+ if not self ._deinited :
54
+ if self .enabled :
55
+ self ._enabled = False # turn off the pwm
56
+ self ._deinited = True
57
+
59
58
60
59
def _is_deinited (self ):
61
- if self ._pwmpin is None :
60
+ """ raise Value error if the object has been de-inited """
61
+ if self ._deinited :
62
62
raise ValueError (
63
63
"Object has been deinitialize and can no longer "
64
64
"be used. Create a new object."
@@ -103,13 +103,15 @@ def duty_cycle(self, duty_cycle):
103
103
raise TypeError ("Invalid duty cycle type, should be int or float." )
104
104
105
105
if not 0 <= duty_cycle <= 65535 :
106
- raise ValueError ("Invalid duty cycle value, should be between 0 and 65535" )
106
+ raise ValueError ("Invalid duty cycle value, should be between "
107
+ "0 and 65535" )
107
108
108
109
# convert from 16-bit
109
110
duty_cycle /= 65535.0
110
111
111
112
self ._duty_cycle = duty_cycle
112
- self ._pwmpin .ChangeDutyCycle (round (self ._duty_cycle * 100 ))
113
+ if self ._enabled :
114
+ self .enabled = True # turn on with new values
113
115
114
116
@property
115
117
def frequency (self ):
@@ -129,8 +131,9 @@ def frequency(self, frequency):
129
131
if not isinstance (frequency , (int , float )):
130
132
raise TypeError ("Invalid frequency type, should be int or float." )
131
133
132
- self ._pwmpin .ChangeFrequency (round (frequency ))
133
134
self ._frequency = frequency
135
+ if self .enabled :
136
+ self .enabled = True # turn on with new values
134
137
135
138
@property
136
139
def enabled (self ):
@@ -147,19 +150,18 @@ def enabled(self):
147
150
@enabled .setter
148
151
def enabled (self , value ):
149
152
if not isinstance (value , bool ):
150
- raise TypeError ("Invalid enabled type, should be string." )
151
-
152
- if value :
153
- self ._pwmpin .start (round (self ._duty_cycle * 100 ))
154
- else :
155
- self ._pwmpin .stop ()
153
+ raise TypeError ("Invalid enabled type, should be bool." )
156
154
155
+ frequency = self ._frequency if value else 0
156
+ duty_cycle = round (self ._duty_cycle * 100 )
157
157
self ._enabled = value
158
+ result = lgpio .tx_pwm (board .pin .CHIP , self ._pin .id , frequency , duty_cycle )
159
+ if result < 0 :
160
+ raise RuntimeError (lgpio .error_text (result ))
161
+ return result
162
+
158
163
159
164
# String representation
160
165
def __str__ (self ):
161
- return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
162
- self ._pin ,
163
- self .frequency ,
164
- self .duty_cycle ,
165
- )
166
+ return (f"pin { self ._pin } (freq={ self .frequency :f} Hz, duty_cycle="
167
+ f"{ self .duty_cycle } ({ round (self .duty_cycle / 655.35 )} %)" )
0 commit comments