├── .gitignore ├── README.md ├── init.py └── orangepwm.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OrangePWM - Python software PWM for Orange Pi 2 | ======= 3 | 4 | OrangePWM Python, for Orange Pi Lite, Orange Pi PC, Orange Pi Zero is easy programmatic PWM ligrary, is an easy way to implement software PWM (Pulse Width Modulation) output on Orange Pi using Python language. 5 | 6 | * [Authors's website - RU/UA](http://evergreens.com.ua/ru/products/development/iot-devices.html) 7 | * [Authors's website - EN](http://evergreen.team/en/products/development/iot-devices.html) 8 | * [PiZyPwm](https://github.com/aboudou/pizypwm/tree/master/rpi.gpio) 9 | 10 | 11 | Warning 12 | ------- 13 | 14 | Due to the non real-time capacities of Python language, do not expect PWM to be very accurate. Pulses will never exactly last the theorical duration. But OrangePWM will be enough if you don't need a great accuracy. 15 | 16 | Requirements 17 | ------------ 18 | 19 | * First of all : Orange Pi 20 | * Python (with Debian / Raspbian : packages “python” and “python-dev”) 21 | * PyA20.gpio library 22 | 23 | Example usage 24 | ------------- 25 | 26 | ``` 27 | from pyA20.gpio import gpio 28 | from pyA20.gpio import port 29 | from time import sleep 30 | from orangepwm import * 31 | 32 | gpio.init() 33 | 34 | # Set GPIO pin PA6 as PWM output with a frequency of 100 Hz 35 | pwm = OrangePwm(100, port.PA6) 36 | 37 | # Start PWM output with a duty cycle of 20%. The pulse (HIGH state) will have a duration of 38 | # (1 / 100) * (20 / 100) = 0.002 seconds, followed by a low state with a duration of 39 | # (1 / 100) * ((100 - 20) / 100) = 0.008 seconds. 40 | # If a LED is plugged to with GPIO pin, it will shine at 20% of its capacity. 41 | pwm.start(20) 42 | sleep(2) 43 | 44 | # Change duty cycle to 6%. The pulse (HIGH state) will now have a duration of 45 | # (1 / 100) * (6 / 100) = 0.0006 seconds, followed by a low state with a duration of 46 | # (1 / 100) * ((100 - 6) / 100) = 0.0094 seconds. 47 | # If a LED is plugged to with GPIO pin, it will shine at 6% of its capacity. 48 | pwm.changeDutyCycle(6) 49 | sleep(2) 50 | 51 | # Change the frequency of the PWM pattern. The pulse (HIGH state) will now have a duration of 52 | # (1 / 10) * (6 / 100) = 0.006 seconds, followed by a low state with a duration of 53 | # (1 / 10) * ((100 - 6) / 100) = 0.094 seconds. 54 | # If a LED is plugged to with GPIO pin, it will shine at 6% of its capacity, but you may 55 | # notice flickering. 56 | pwm.changeFrequency(10) 57 | sleep(2) 58 | 59 | # Stop PWM output 60 | pwm.stop() 61 | -------------------------------------------------------------------------------- /init.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | sys.path.append(os.path.dirname(__file__)) 3 | -------------------------------------------------------------------------------- /orangepwm.py: -------------------------------------------------------------------------------- 1 | from pyA20.gpio import gpio as GPIO 2 | from pyA20.gpio import port 3 | import threading 4 | import time 5 | 6 | class OrangePwm(threading.Thread): 7 | 8 | def __init__(self, frequency, gpioPin, gpioScheme=0): 9 | """ 10 | Init the OrangePwm instance. Expected parameters are : 11 | - frequency : the frequency in Hz for the PWM pattern. A correct value may be 100. 12 | - gpioPin : the gpio.port which will act as PWM ouput 13 | - gpioScheme : saved for compatibility with PiZyPWM code 14 | """ 15 | self.baseTime = 1.0 / frequency 16 | self.maxCycle = 100.0 17 | self.sliceTime = self.baseTime / self.maxCycle 18 | self.gpioPin = gpioPin 19 | self.terminated = False 20 | self.toTerminate = False 21 | #GPIO.setmode(gpioScheme) 22 | 23 | 24 | def start(self, dutyCycle): 25 | """ 26 | Start PWM output. Expected parameter is : 27 | - dutyCycle : percentage of a single pattern to set HIGH output on the GPIO pin 28 | 29 | Example : with a frequency of 1 Hz, and a duty cycle set to 25, GPIO pin will 30 | stay HIGH for 1*(25/100) seconds on HIGH output, and 1*(75/100) seconds on LOW output. 31 | """ 32 | self.dutyCycle = dutyCycle 33 | GPIO.setcfg(self.gpioPin, GPIO.OUTPUT) 34 | self.thread = threading.Thread(None, self.run, None, (), {}) 35 | self.thread.start() 36 | 37 | 38 | def run(self): 39 | """ 40 | Run the PWM pattern into a background thread. This function should not be called outside of this class. 41 | """ 42 | while self.toTerminate == False: 43 | if self.dutyCycle > 0: 44 | GPIO.output(self.gpioPin, GPIO.HIGH) 45 | time.sleep(self.dutyCycle * self.sliceTime) 46 | 47 | if self.dutyCycle < self.maxCycle: 48 | GPIO.output(self.gpioPin, GPIO.LOW) 49 | time.sleep((self.maxCycle - self.dutyCycle) * self.sliceTime) 50 | 51 | self.terminated = True 52 | 53 | 54 | def changeDutyCycle(self, dutyCycle): 55 | """ 56 | Change the duration of HIGH output of the pattern. Expected parameter is : 57 | - dutyCycle : percentage of a single pattern to set HIGH output on the GPIO pin 58 | 59 | Example : with a frequency of 1 Hz, and a duty cycle set to 25, GPIO pin will 60 | stay HIGH for 1*(25/100) seconds on HIGH output, and 1*(75/100) seconds on LOW output. 61 | """ 62 | self.dutyCycle = dutyCycle 63 | 64 | 65 | def changeFrequency(self, frequency): 66 | """ 67 | Change the frequency of the PWM pattern. Expected parameter is : 68 | - frequency : the frequency in Hz for the PWM pattern. A correct value may be 100. 69 | 70 | Example : with a frequency of 1 Hz, and a duty cycle set to 25, GPIO pin will 71 | stay HIGH for 1*(25/100) seconds on HIGH output, and 1*(75/100) seconds on LOW output. 72 | """ 73 | self.baseTime = 1.0 / frequency 74 | self.sliceTime = self.baseTime / self.maxCycle 75 | 76 | 77 | def stop(self): 78 | """ 79 | Stops PWM output. 80 | """ 81 | self.toTerminate = True 82 | while self.terminated == False: 83 | # Just wait 84 | time.sleep(0.01) 85 | 86 | GPIO.output(self.gpioPin, GPIO.LOW) 87 | GPIO.setcfg(self.gpioPin, GPIO.INPUT) 88 | --------------------------------------------------------------------------------