@@ -59,35 +59,58 @@ def shutdown(self):
5959
6060class softwarePWM (basicPWM ):
6161 def __init__ (self , pinToUse = 7 ):
62- logging .info ('Initializing software PWM on pin %s' , pinToUse )
63- global GPIO
64- from RPi import GPIO
62+ logging .info ('Initializing software PWM on GPIO pin %s (board pin %s)' , self ._board_to_bcm (pinToUse ), pinToUse )
63+ global PWMLED
64+ from gpiozero import PWMLED
65+ # Convert board pin to BCM GPIO number
66+ bcm_pin = self ._board_to_bcm (pinToUse )
6567 self .pinToUse = pinToUse
68+ self .bcm_pin = bcm_pin
6669 self .pwm = None
67- # TODO: Ponder if import RPi.GPIO as GPIO is a good idea
68- # TODO: Look at switching to gpiozero
69- GPIO .setmode (GPIO .BOARD )
70- GPIO .setup (self .pinToUse , GPIO .OUT )
71- GPIO .output (self .pinToUse ,0 )
70+
71+ # Create PWMLED device (starts at 0% duty cycle, off)
72+ self .pwm = PWMLED (bcm_pin , initial_value = 0 )
7273 super ().__init__ ()
7374
75+ def _board_to_bcm (self , board_pin ):
76+ """Convert board pin number to BCM GPIO number."""
77+ # Mapping for 40-pin Raspberry Pi header (board -> BCM)
78+ board_to_bcm_map = {
79+ 7 : 4 , 8 : 14 , 10 : 15 , 11 : 17 , 12 : 18 , 13 : 27 ,
80+ 15 : 22 , 16 : 23 , 18 : 24 , 19 : 10 , 21 : 9 , 22 : 25 ,
81+ 23 : 11 , 24 : 8 , 26 : 7 , 27 : 0 , 28 : 1 , 29 : 5 ,
82+ 31 : 6 , 32 : 12 , 33 : 13 , 35 : 19 , 36 : 16 , 37 : 26 ,
83+ 38 : 20 , 40 : 21
84+ }
85+
86+ if board_pin not in board_to_bcm_map :
87+ raise ValueError (f'Invalid board pin number: { board_pin } ' )
88+
89+ return board_to_bcm_map [board_pin ]
90+
7491 def startup (self , period = 10000 , dutyCycle = 0 ):
75- logging .debug ('Starting software PWM on pin %s with period of %s' , self .pinToUse , period )
76- self .pwm = GPIO .PWM (self .pinToUse , period )
77- logging .info ('Updating software PWM on pin %s initial duty cycle to %s' , self .pinToUse , round (dutyCycle / 3 ,2 ))
78- self .pwm .start (dutyCycle / 3 )
92+ # gpiozero uses frequency in Hz, convert from period in microseconds
93+ # frequency = 1 / (period / 1,000,000)
94+ frequency = 1_000_000 / period
95+ logging .debug ('Starting software PWM on GPIO %s (board pin %s) with frequency %.2f Hz' ,self .bcm_pin , self .pinToUse , frequency )
96+ self .pwm .frequency = frequency
97+ initial_value = (dutyCycle / 3 ) / 100
98+ logging .info ('Setting software PWM on GPIO %s initial duty cycle to %.2f%%' , self .bcm_pin , dutyCycle / 3 )
99+ self .pwm .value = initial_value
79100 super ().startup ()
80101
81102 def update (self , dutyCycle = 0 ):
82- logging .info ('Updating software PWM on pin %s duty cycle to %s' , self .pinToUse , round (dutyCycle / 3 ,2 ))
83- self .pwm .ChangeDutyCycle (dutyCycle / 3 )
103+ value = (dutyCycle / 3 ) / 100
104+ logging .info ('Updating software PWM on GPIO %s duty cycle to %.2f%%' , self .bcm_pin , dutyCycle / 3 )
105+ self .pwm .value = value
84106 super ().update ()
85107
86108 def shutdown (self ):
87- logging .debug ('Shutting down software PWM on pin %s' , self .pinToUse )
88- self .pwm .stop ()
89- logging .info ('Cleaning up software PWM on pin %s' , self .pinToUse )
90- GPIO .cleanup ()
109+ logging .debug ('Shutting down software PWM on GPIO %s (board pin %s)' , self .bcm_pin , self .pinToUse )
110+ self .pwm .off ()
111+ logging .info ('Cleaning up software PWM on GPIO %s' , self .bcm_pin )
112+ # gpiozero handles cleanup automatically, but explicitly close
113+ self .pwm .close ()
91114 super ().shutdown ()
92115
93116class hardwareBBBPWM (basicPWM ):
0 commit comments