vsergeev / python-periphery

A pure Python 2/3 library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
MIT License
519 stars 139 forks source link

Using PWM on two instances #62

Open jarell-santella opened 1 year ago

jarell-santella commented 1 year ago

I have a very strange use case for this library such that I need two instances accessing the same PWM at the same time. I am aware this is not very typical or recommended. Because one PWM instance can close the file for another PWM instance using the same PWM and thus the same file, if we lose reference to one PWM instance and thus close the file, the other PWM instance will fail as well.

To combat this and to make sure that the other PWM instance can keep going even if one stops and closes the file, we can detect for a FileNotFoundError or PWMError and restart the PWM instance for the one that is intended to keep going. However, I am unsure why this first script does not work for that, but the second script does. The behavior of the first script is that it will keep throwing an error (either FileNotFoundError or PWMError) if another PWM instance stops, closing the file. It never recovers from this. However, the second script will throw the error once and then self-recover, which is intended. I am curious as to why the first script works, and the second script does not.

To reproduce this, start one of each script below and have them fun simultaneously. If you stop the first one first via a KeyboardInterrupt, the second one will throw an error and keep going. This is good. However, if you stop the second one first, the first one will continuously throw an error and does not recover.

Script that does not work:

import time
import random
import traceback

from periphery import PWM, PWMError

class Script():

    def __init__(self):
        self.pwm = PWM(0, 1)

    def start(self):
        while True:
            desired_frequency = random.uniform(1000.0, 10000.0)
            try:
                self.pwm.frequency = desired_frequency
                output = self.pwm.frequency
            except (PWMError, FileNotFoundError):
                print(traceback.format_exc())
                self.pwm = None
                self.pwm = PWM(0, 1)
            else:
                print(f"Frequency = {output}")

            time.sleep(0.1)

if __name__ == "__main__":
    script = Script()
    script.start()

Script that works:

import time
import random
import traceback

from periphery import PWM, PWMError

class Script():

    def __init__(self):
        self.retry = True

    def start(self):
        while True:
            desired_frequency = random.uniform(1000.0, 10000.0)
            try:
                if self.retry:
                    self.pwm = None
                    self.pwm = PWM(0, 1)
                    self.retry = False

                self.pwm.frequency = desired_frequency
                output = self.pwm.frequency
            except (PWMError, FileNotFoundError):
                print(traceback.format_exc())
                self.retry = True
            else:
                print(f"Frequency = {output}")

            time.sleep(0.1)

if __name__ == "__main__":
    script = Script()
    script.start()