tino / pyFirmata

Python interface for the Firmata (http://firmata.org/) protocol. It is compliant with Firmata 2.1. Any help with updating to 2.2 is welcome. The Capability Query is implemented, but the Pin State Query feature not yet.
MIT License
575 stars 193 forks source link

Analog Read issues when two megas connected to PC #104

Open Celldom-Han opened 3 years ago

Celldom-Han commented 3 years ago

Hardware setup: Two Arduino Megas 2560 are connected to my PC (COM5, COM6) over USB, they take up two USB plugs on a 4:1 USB dock.

Software setup: -Both Megas have standardFirmata.c loaded onto them. -Pyfirmata package used in my python code to, at 1s intervals, do an analog read from 12 analog input pins on each mega (24 reads total per second) -In case this has any relevance, the code is displaying these analog reads on a dash app, and there's a callback at 1s intervals in the dash python code to do the analog reads

Issue: When I have just one of the two Megas connected, I get expected readings. However when both are connected via USB, one mega (COM5) seems to repeatedly give the first reading it gave, and never really changes from that reading (exact same voltage reading down to the 3rd decimal place). It's almost like it's unable to give a new reading or just keeps dumping the same first reading to the serial port buffer. I know the reading update function is correctly written because when I disconnect the COM6 Arduino and rerun the dash app, all of a sudden COM5 reads as expected and does change according to sensor input and noise.

I'm wondering if there's some quirk with pyfirmata that requires some minimum time delay before reading from one COM vs a second COM port?

For further context, both Megas can be connected at the same time and the digital write functions work perfectly fine for both simultaneously.

Celldom-Han commented 3 years ago

` class PneumaticsController: def init(self, arduino_port="COM4", baud=9600, reg_blocks=1): self.arduino_port = arduino_port self.baud = baud self.reg_blocks = reg_blocks

    # =============== Set Physical Parameters ===============
    self.valid_pressures = {'loaderLoadMin': -180,
                            'loaderLoadMax': 0,
                            'loaderSqueezeMin': -1000,
                            'loaderSqueezeMax': 0,
                            'ctrlBoxLoadMin': -1000,
                            'ctrlBoxLoadMax': 0,
                            'ctrlBoxSqueezeMin': -1000,
                            'ctrlBoxSqueezeMax': 0}

    # =============== Sensor Properties ===============
    # the pressure is linearly proportional to the sensor reading
    # following the equation y = m * x + b
    # x is the arduino_mega output [0, 1023]
    # m is the slope and b is the intercept

    self.voltage_supply = 5  # voltage of analog pins and given to sensor
    self.Patm = 1000  # define atmospheric pressure
    self.Prange = 160  # define sensor pressure differential range
    self.Pmax = self.Patm  # maximum sensor inlet pressure (mBar abs)
    self.Pmin = self.Patm - self.Prange  # minimum sensor inlet pressure (mBar abs)

    # =============== Controller Properties ===============
    # These variables define the pressures for the different loading steps in mbar
    # and the times for each loading step in milliseconds

    # global count
    # global load_state
    # global squeeze_pressure
    # global squeeze_time
    # self.loadState = False
    # count = 0
    self.load_pressure = -50
    self.squeeze_pressure = -1000
    self.squeeze_time = 1000
    self.zero_pressure = 0
    self.PWM_to_pressure_factor = -965
    self.PWM_to_pressure_offset = 5
    self.load_PWM = (self.load_pressure-self.PWM_to_pressure_offset) / self.PWM_to_pressure_factor

    # =============== Handshake with arduino_mega ===============
    try:
        arduino_mega = pf.ArduinoMega(self.arduino_port)
        iterator = pf.util.Iterator(arduino_mega)
        iterator.start()
        time.sleep(0.1)
        # self.logger.info("Connected to "+str(arduino_mega))
    except Exception as error:
        # self.logger.info("Failed to connect to arduino_mega.")
        print('Failed to connect to arduino_mega. {}'.format(error))

    # =============== Configure pins for regulators ===============
    # PneumaticsController alwways has at least one regulator block
    # Assign pins for first regulator block
    # self.LEDpin = arduino_mega.get_pin('d:13:p') # Pin for built-in LED

    self.b1ps1 = arduino_mega.get_pin('a:7:i')  # Pin to connect to pressure sensor 1
    self.b1ps2 = arduino_mega.get_pin('a:6:i')  # Pin to connect to pressure sensor 2
    self.b1ps3 = arduino_mega.get_pin('a:5:i')  # Pin to connect to pressure sensor 3
    self.b1ps4 = arduino_mega.get_pin('a:4:i')  # Pin to connect to pressure sensor 4
    self.b1ps5 = arduino_mega.get_pin('a:3:i')  # Pin to connect to pressure sensor 5
    self.b1ps6 = arduino_mega.get_pin('a:2:i')  # Pin to connect to pressure sensor 6

    self.b1r1 = arduino_mega.get_pin('d:13:p')  # Pin to connect to regulator, PWM mode
    self.b1r2 = arduino_mega.get_pin('d:12:p')  # Pin to connect to regulator, PWM mode
    self.b1r3 = arduino_mega.get_pin('d:11:p')  # Pin to connect to regulator, PWM mode
    self.b1r4 = arduino_mega.get_pin('d:10:p')  # Pin to connect to regulator, PWM mode
    self.b1r5 = arduino_mega.get_pin('d:9:p')  # Pin to connect to regulator, PWM mode
    self.b1r6 = arduino_mega.get_pin('d:8:p')  # Pin to connect to regulator, PWM mode

    self.b1 = {# Name    Input    Output
                'r1': {'i': self.b1ps1, 'o': self.b1r1},
                'r2': {'i': self.b1ps2, 'o': self.b1r2},
                'r3': {'i': self.b1ps3, 'o': self.b1r3},
                'r4': {'i': self.b1ps4, 'o': self.b1r4},
                'r5': {'i': self.b1ps5, 'o': self.b1r5},
                'r6': {'i': self.b1ps6, 'o': self.b1r6}
                }

    if self.reg_blocks == 2:
        # This PneumaticsController has two regulator blocks
        # Assign more pins for second regulator block

        self.b2ps1 = arduino_mega.get_pin('a:13:i')  # Pin to connect to pressure sensor 1
        self.b2ps2 = arduino_mega.get_pin('a:12:i')  # Pin to connect to pressure sensor 2
        self.b2ps3 = arduino_mega.get_pin('a:11:i')  # Pin to connect to pressure sensor 3
        self.b2ps4 = arduino_mega.get_pin('a:10:i')  # Pin to connect to pressure sensor 4
        self.b2ps5 = arduino_mega.get_pin('a:9:i')  # Pin to connect to pressure sensor 5
        self.b2ps6 = arduino_mega.get_pin('a:8:i')  # Pin to connect to pressure sensor 6

        self.b2r1 = arduino_mega.get_pin('d:7:p')  # Pin to connect to regulator, PWM mode
        self.b2r2 = arduino_mega.get_pin('d:6:p')  # Pin to connect to regulator, PWM mode
        self.b2r3 = arduino_mega.get_pin('d:5:p')  # Pin to connect to regulator, PWM mode
        self.b2r4 = arduino_mega.get_pin('d:4:p')  # Pin to connect to regulator, PWM mode
        self.b2r5 = arduino_mega.get_pin('d:3:p')  # Pin to connect to regulator, PWM mode
        self.b2r6 = arduino_mega.get_pin('d:2:p')  # Pin to connect to regulator, PWM mode

        self.b2 =  {# Name    Input    Output
                    'r1': {'i': self.b2ps1, 'o': self.b2r1},
                    'r2': {'i': self.b2ps2, 'o': self.b2r2},
                    'r3': {'i': self.b2ps3, 'o': self.b2r3},
                    'r4': {'i': self.b2ps4, 'o': self.b2r4},
                    'r5': {'i': self.b2ps5, 'o': self.b2r5},
                    'r6': {'i': self.b2ps6, 'o': self.b2r6}
                    }

`