Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to create multiple instances Arduino board object #100

Open
01baftb opened this issue Jan 16, 2021 · 1 comment
Open

Unable to create multiple instances Arduino board object #100

01baftb opened this issue Jan 16, 2021 · 1 comment

Comments

@01baftb
Copy link

01baftb commented Jan 16, 2021

I am using pyFirmata to control multiple DC motors connected to a single Arduino Nano.

Problem: I am unable to create multiple instances of the pyfirmata.Arduino object connecting to the same communication port. See example code below where I create a general class to control a DC motor. Each motor that needs to be controlled is connected to the same Arduino comm port but only thing that differs is the pin number at which the pwm and direction signals are outputted from. When I create two different instances of the MyMotor() class, I get the following error:

Error:

Traceback (most recent call last):
  File "c:/tmp1/myMotorExample.py", line 21, in <module>
    motor_2 = MyMotor(port='COM5', pin_pwm=5, pin_direction=7)
  File "c:/tmp1/myMotorExample.py", line 7, in __init__
    self.board = pyfirmata.Arduino(port)
  File "C:\tmp1\my_venv\lib\site-packages\pyfirmata\__init__.py", line 19, in __init__
    super(Arduino, self).__init__(*args, **kwargs)
  File "C:\tmp1\my_venv\lib\site-packages\pyfirmata\pyfirmata.py", line 89, in __init__
    self.sp = serial.Serial(port, baudrate, timeout=timeout)
  File "C:\tmp1\my_venv\lib\site-packages\serial\serialwin32.py", line 31, in __init__
    super(Serial, self).__init__(*args, **kwargs)
  File "C:\tmp1\my_venv\lib\site-packages\serial\serialutil.py", line 240, in __init__
    self.open()
  File "C:\tmp1\my_venv\lib\site-packages\serial\serialwin32.py", line 62, in open
    raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
serial.serialutil.SerialException: could not open port 'COM5': PermissionError(13, 'Access is denied.', None, 5)

Example code

import pyfirmata

class MyMotor():
    
    def __init__(self, port, pin_pwm, pin_direction):
        # Setup the board 
        self.board = pyfirmata.Arduino(port)
        # Assign the pins 
        self.pin_pwm = self.board.get_pin('d:{}:p'.format(pin_pwm))
        self.pin_direction = self.board.get_pin('d:{}:o'.format(pin_direction))

    def run_motor(self, speed=0.5, direction=True):
        self.pin_pwm.write(speed)
        self.pin_direction.write(direction)
    
    def stop_motor(self):
        self.pin_pwm.write(0.0)


motor_1 = MyMotor(port='COM5', pin_pwm=3, pin_direction=4)
motor_2 = MyMotor(port='COM5', pin_pwm=5, pin_direction=7)
@01baftb
Copy link
Author

01baftb commented Jan 16, 2021

I think I figured out a temporary solution to my issue. However maybe this solution could be incorporated into pyfirmata. In summary, class attribute can be used to keep track of all Arduino comm ports already in use by pyfirmata.

import serial
import pyfirmata

class MyMotor():
    
    open_boards = [] 

    def __init__(self, port, pin_pwm, pin_direction):

        # Setup the board 
        try:
            self.board = pyfirmata.Arduino(port)
            self.open_boards.append(self.board)
            print('Success connecting to board.')
        except serial.serialutil.SerialException:
            print('Problem connecting to Arduino. Comm port may already be in use. Checking and trying to fix...')
            problem_fixed = False 
            for i in self.open_boards:
                if i.sp.port == port:
                    self.board = i
                    problem_fixed = True 
                    break 
            
            if not problem_fixed:
                print('Unable to fix the problem.')
                return    
            else:
                print('Requested port was already in used. Success with connecting to board. ')

        # Assign the pins 
        self.pin_pwm = self.board.get_pin('d:{}:p'.format(pin_pwm))
        self.pin_direction = self.board.get_pin('d:{}:o'.format(pin_direction))

    def run_motor(self, speed=0.5, direction=True):
        self.pin_pwm.write(speed)
        self.pin_direction.write(direction)
    
    def stop_motor(self):
        self.pin_pwm.write(0.0)

motor_1 = MyMotor(port='COM5', pin_pwm=3, pin_direction=4)
motor_1.run_motor()
motor_2 = MyMotor(port='COM5', pin_pwm=5, pin_direction=7)
motor_2.run_motor()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant