Giter Site home page Giter Site logo

alicat's Introduction

alicat

TCP/Serial driver and command line tool for Alicat mass flow controllers.

If you are using Analyt-MTC flow controllers, go to this repository for more info.

Example Connections

Type Usage
The standard DB9 cable connected directly to a computer (unix: /dev/ttyS0, windows: COM1). Good with older computers that still have the connector.
The cable connected to a computer through a USB converter (unix: /dev/ttyUSB0, windows: COM1). Good for newer computers and maker boards such as Raspberry Pis.
Multiple cables connected to one port via a splitter and Alicat's addressing (A-Z). Good when number of ports is limited.
Cables routed through a TCP device server (192.168.1.100:23).

Installation

pip install alicat

Usage

Command Line

For basic tasks, this driver includes a command-line interface. Read the help for more.

alicat --help

Python

This uses Python ≥3.5's async/await syntax to asynchronously communicate with an Alicat. For example:

import asyncio
from alicat import FlowController

async def get():
    async with FlowController('ip-address:port') as flow_controller:
        print(await flow_controller.get())

asyncio.run(get())

If the flow controller is communicating on the specified port, this should return a dictionary of the form:

{
  'setpoint': 0.0,         # Setpoint, either mass flow rate or pressure
  'control_point': 'flow', # Either 'flow' or 'pressure'
  'gas': 'Air',            # Can be any option in `flow_controller.gases`
  'mass_flow': 0.0,        # Mass flow (in units specified at time of purchase)
  'pressure': 25.46,       # Pressure (normally in psia)
  'temperature': 23.62,    # Temperature (normally in C)
  'total_flow': 0.0,       # Optional. If totalizer function purchased, will be included
  'volumetric_flow': 0.0   # Volumetric flow (in units specified at time of purchase)
}

On flow controllers, you can set the flow or pressure setpoints.

await flow_controller.set_flow_rate(1.0)
await flow_controller.set_pressure(20)

Gas Type

You can set the gas type by name or by index. For more on setting by index, see the gas table in your Alicat's manual.

await flow_controller.set_gas('N2')
await flow_controller.set_gas(8)

For firmware 5v and greater, you can create and set gas mixes. Mixes can contain up to five gases and are stored in gas indices 236-255.

await flow_controller.create_mix(mix_no=236, name="Mix1", gases={'N2': 50, 'O2': 30, 'CO2': 20})
await flow_controller.set_gas(236)
await flow_controller.delete_mix(236)

PID Parameters

For flow controllers, read and write PID loop settings for device tuning.

await flow_controller.set_pid(p=4000, i=4000, d=10, loop_type='PD2I')
print(await flow_controller.get_pid())
{
    'loop_type': 'PD2I',
    'P': '4000',
    'I': '4000',
    'D': '10',
}

Other Features

Additional features include override commands to increase device functionality.

await flow_controller.lock()            # Lock the front display.
await flow_controller.unlock()          # Unlock the front display.
await flow_controller.hold()            # Hold the valve in its current position.
await flow_controller.cancel_hold()     # Cancel the valve hold.
await flow_controller.tare_volumetric() # Tare volumetric flow.
await flow_controller.tare_pressure()   # Tare pressure.
await flow_controller.reset_totalizer() # Reset totalizer, if totalizer functionality included.

Addressing

You can have multiple controllers on the same port by using Alicat's A-Z addresses and an RS-232 splitter.

flow_controller_1 = FlowController(address='A')
flow_controller_2 = FlowController(address='B')

await flow_controller_1.set_flow_rate(1.0)
await flow_controller_2.set_flow_rate(0.5)

await flow_controller_1.close() # /dev/ttyUSB0 is still open!
await flow_controller_2.close()

Breaking changes

0.5.0

  • Support only asyncio. The last version with synchronous code was 0.4.1.
  • Rename address/-a to unit/-u to match Alicat's documentation
  • Rename -u to -ul (for --unlock)

0.4.1 Remove TCP support. Use pip install alicat==0.3.1 if needed

alicat's People

Contributors

alexrudd2 avatar avichalk avatar brad-houska avatar gwen-noya avatar jamesjeffryes avatar joshmaybell avatar lsgunth avatar marinapalese avatar patrickfuller avatar renovate[bot] avatar treychaffin avatar unidan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alicat's Issues

Unable to pass kwargs to FlowController

The FlowMeter constructor allows passing arbitrary keyword arguments that get passed through to the underlying client. This could be used, for instance, to change the default baud.

alicat/alicat/driver.py

Lines 31 to 41 in 32de621

def __init__(self, address: str = '/dev/ttyUSB0', unit: str = 'A', **kwargs: Any) -> None:
"""Connect this driver with the appropriate USB / serial port.
Args:
address: The serial port or TCP address:port. Default '/dev/ttyUSB0'.
unit: The Alicat-specified unit ID, A-Z. Default 'A'.
"""
if address.startswith('/dev') or address.startswith('COM'): # serial
self.hw: Client = SerialClient(address=address, **kwargs)
else:
self.hw = TcpClient(address=address, **kwargs)

The **kwargs passthrough isn't present in the FlowController constructor for some reason.

alicat/alicat/driver.py

Lines 304 to 311 in 32de621

def __init__(self, address: str='/dev/ttyUSB0', unit: str='A') -> None:
"""Connect this driver with the appropriate USB / serial port.
Args:
address: The serial port or TCP address:port. Default '/dev/ttyUSB0'.
unit: The Alicat-specified unit ID, A-Z. Default 'A'.
"""
FlowMeter.__init__(self, address, unit)

DRY

This code was written for RS-232/USB support, and then the Ethernet gateway support was bolted on by copy-pasting the implementation.

This would be better organized as a Protocol-Transport model, where an abstract base class implements the protocol and stubs the transport.

Quick question

How to give command on Alicat MFC to be in stream mode through python?

unexpected behavior from is_connected method after 0.5.0 release

Hello! I've been using this package inside my own automation system, and I wrote a script to find all of my connected MFCs addresses. The latest update broke my script at first through the name change between 'address' and 'unit'. I fixed that, but I'm getting unexpected behavior in the is_connected method. I'm posting a screenshot of the results using 0.4.0 and 0.5.0 where the only thing i'm changing in the script is unit/address. It seems like is_connected is no longer returning False for incorrect conditions? I tried looking through the commit history but it doesn't seem that the method code has changed since 0.4.0 besides the asynchio additions. I'm not sure why that would break this. Do you have thoughts?
image

mfc.set_flow_rate() returning error when used with Alicat MCVS

I have a setup that uses 2 Alicat MCVS MFCs (MCVS-500SCCM-D/5M), 1 MC and 1 Flow Meter (M). I can initialise all the devices fine and can change various settings (ie change gas), and get a response from mfc.get(). However, when updating the MCVS's, I get an error (see below):

mfc11.set_flow_rate(1.0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/dist-packages/alicat/serial.py", line 273, in set_flow_rate  self._set_control_point('flow', retries)
  File "/usr/local/lib/python3.7/dist-packages/alicat/serial.py", line 334, in _set_control_point
    value = int(line.split('=')[-1])
ValueError: invalid literal for int() with base 10: 'B +014.74 +024.46 +0000.2 -0000.1 0000.0      N2'

The MC MFC updates fine. Anyone else had issues here?

For reference, here is the test code

from alicat import *

mfc11 = FlowController(port='/dev/ttyUSB0', address='B')
print(mfc11.get())
mfc12 = FlowController(port='/dev/ttyUSB0', address='A')
print(mfc12.get())

mfc11.set_flow_rate(1.0)

Improve `is_connected` error handling

Related to #7.

Right now, a flow controller will return False if initialized as a FlowMeter. We should consider a more verbose approach to is_connected covering the following scenarios:

  • Nothing's connected
  • Nothing's communicating
  • Something's communicating, but it's not an Alicat
  • An Alicat is communicating, but it's not a FlowMeter / FlowController

Handle very old (GP) firmware more robustly

All versions of the firmware work great, except GP. [Marina has] mixed feelings about this since it's 10 years old now and these devices aren't circulating much. The loop type can't be changed (and register 85 doesn't exist yet) so that messes get_pid(), though set_pid() can be used if the loop isn't specified. The totalizer command is missing the dollar signs ({addr}T\r instead of {addr}$$T\r so it doesn't like this. Only GP actually uses the dollar signs, though everything else is backwards compatible. And lastly, the {addr}VE command also wasn't around yet, so GP isn't recognized to stop it from continue to create_mix() function. {addr}??m8 would work, but only for GP which is annoying.

Originally posted by @marinapalese in #15 (comment)

Can you connect Alicats to BPODs?

Working on a project that will be controlled by a BPOD, more specifically PyBpod, and wanted to know if it could be directly integrated with State Machines?

Occasional bad reads with `=` are not handled well

File "/Users/a.ruddick/Documents/github/alicat/alicat/tcp.py", line 310, in print_state
   state = await flow_controller.get()
 File "/Users/a.ruddick/Documents/github/alicat/alicat/tcp.py", line 213, in get
   state = await FlowMeter.get(self)
 File "/Users/a.ruddick/Documents/github/alicat/alicat/tcp.py", line 90, in get
   return {k: (v if k == self.keys[-1] else float(v))
 File "/Users/a.ruddick/Documents/github/alicat/alicat/tcp.py", line 90, in <dictcomp>
   return {k: (v if k == self.keys[-1] else float(v))
ValueError: could not convert string to float: '='

The above Exception is thrown about 10-20% of the time when using the command line to read a kilo lab flowmeter through the serial gateway. I suspect my command line driver is actually intercepting responses intended for the kilo lab controller when its asking for e.g. control point. I believe Alicats respond to such requests with R{register}=xyz or something similar. The protocol was never meant to handle multiple simultaneous connections, but it could at least catch and log the unexpected value.

Custom Mix: could not convert string to float

I am trying to communicate with an MFC which is using a custom mix of gas. I set up the mix on the MFC, but when reading the device via serial, I get the following error:

>>> print(flow_controller2.get())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/.local/lib/python3.9/site-packages/alicat/serial.py", line 389, in get
    state = FlowMeter.get(self, retries)
  File "/home/pi/.local/lib/python3.9/site-packages/alicat/serial.py", line 126, in get
    return {k: (v if k == self.keys[-1] else float(v))
  File "/home/pi/.local/lib/python3.9/site-packages/alicat/serial.py", line 126, in <dictcomp>
    return {k: (v if k == self.keys[-1] else float(v))
ValueError: could not convert string to float: 'Mix2'

MFC OSError: Could not read control point

Alicat MC-500SCCM
Firmware: 7v22.0-R22
Comm setup: RS-232 Serial, Baud 19200
Setpoint Source: Serial / Front Panel

I have the MFC connected to a raspberry Pi4 and can see device at /dev/ttyUSB0. The MFC is connected via USB to 8 Pin Mini Din Male Serial Adapter

from alicat import FlowController

ADDRESS = '/dev/ttyUSB0'
unit = 'E'

mfc = FlowController(address=ADDRESS, unit=unit)

async def get():
    async with FlowController(address=ADDRESS, unit=unit) as flow_controller:
        print(await flow_controller.get())
await get()

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Cell In[12], line 1
----> 1 await get()

Cell In[11], line 3
      1 async def get():
      2     async with FlowController(address=ADDRESS, unit=unit) as flow_controller:
----> 3         print(await flow_controller.get())

File ~/devel/python_envs/sampler/lib/python3.11/site-packages/alicat/driver.py:344, in FlowController.get(self)
    328 async def get(self) -> dict:
    329     """Get the current state of the flow controller.
    330 
    331     From the Alicat mass flow controller documentation, this data is:
   (...)
    342         The state of the flow controller, as a dictionary.
    343     """
--> 344     state = await super().get()
    345     if state is None:
    346         return None

File ~/devel/python_envs/sampler/lib/python3.11/site-packages/alicat/driver.py:121, in FlowMeter.get(self)
    104 """Get the current state of the flow controller.
    105 
...
--> 468     raise OSError("Could not read control point.")
    469 value = int(line.split('=')[-1])
    470 try:

OSError: Could not read control point.

Driver does not support FP-25 air quality monitors

All I am trying to do is get a reading:
from cal import Old_tables
from alicat import FlowMeter

flow = FlowMeter(port="/dev/ttyUSB0")
value = flow.get()
print(str(value))
and I get the error message:
Traceback (most recent call last):
File "test.py", line 6, in
value = flow.get()
File "/home/pi/.local/lib/python3.7/site-packages/alicat/serial.py", line 127, in get
for k, v in zip(self.keys, values)}
File "/home/pi/.local/lib/python3.7/site-packages/alicat/serial.py", line 127, in
for k, v in zip(self.keys, values)}
ValueError: could not convert string to float: '2022-12-01'

command line does not work with TCP FlowControllers

The FlowMeter class in tcp.py was ported from serial to TCP/IP and works ok. The FlowController class, which subclasses FlowMeter, was copied over and never modified.

Through luck, the positional arguments line up if instancing FlowController from Python code, except address is never passed and therefore defaults to A. However, this luck does not hold when using the command line.

Inlet Controller Raises an exception on "set_flow_rate"

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-7885e597e1f4> in <module>()
     19 
     20 # Close everything up
---> 21 inlet_controller.set_flow_rate(0.0)
     22 outlet_controller.set_flow_rate(0.0)
     23 inlet_controller.close()

/usr/local/lib/python2.7/dist-packages/alicat/__init__.pyc in set_flow_rate(self, flow)
     84         self.connection.write(command)
     85         line = self.ser.readline()
---> 86         if not line or abs(float(line) - flow) > 0.01:
     87             raise Exception("Could not set flow. Is your controller in "
     88                             "serial mode?")

ValueError: could not convert string to float: A +059.30 +024.48 +000.12 +000.50 000.50      N2 

Numeric values are incorrectly returned as strings

6e6c1ad was overzealous, and returns numeric values as strings.

❯ alicat /dev/tty.usbserial-FTCJ5EK9
{
  "control_point": "pressure,
  "gas": "Air",
  "mass_flow": "-000.00",
  "pressure": "+014.60",
  "setpoint": 0.05,
  "temperature": "+028.24",
  "volumetric_flow": "-000.00"
}

FlowMeter is_connected method in serial.py

Hi, I'm new to GitHub (I'm an intern). I'm not sure if this is an issue, but I will report it in case:

In your is_connected method, you assert that 'flow_setpoint' is in 'device.keys' to check if connected:

                if cls.__name__ == 'FlowMeter':
                    assert c and 'flow_setpoint' not in device.keys
                elif cls.__name__ == 'FlowController':
                    assert c and 'flow_setpoint' in device.keys

However, in your FlowMeter constructor, you initialize 'setpoint' instead of 'flow_setpoint':

self.keys = ['pressure', 'temperature', 'volumetric_flow', 'mass_flow',
                     'setpoint', 'gas']

I do not see any line in your code where you could have added 'flow_setpoint' to' device.keys'. This makes me think that is_connected will always return False for FlowController objects.

Enhancement Request: Set ramp rate

Alicat MFCs allow you to set a ramp rate on device – it would be great if we could set that through the python API as well.

Thanks!

CLI not using await on set_flow_rate()

a.ruddick@Alexs-laptop alicat % alicat tcp://192.168.1.212:4000 --set-flow-rate 1
/Users/a.ruddick/Documents/github/alicat/alicat/tcp.py:310: RuntimeWarning: coroutine 'FlowController.set_flow_rate' was never awaited
  flow_controller.set_flow_rate(args.set_flow_rate)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
{
  "control_point": "flow",
  "gas": "N2",
  "mass_flow": -0.0,
  "pressure": 14.29,
  "setpoint": 0.0,
  "temperature": 21.66,
  "volumetric_flow": 0.0
}

https://github.com/numat/alicat/blob/master/alicat/tcp.py#L309-L312

It looks like the lack of await causes some sort of race condition where the flow doesn't actually get set. Compare to the below version (with await added in)

a.ruddick@Alexs-laptop alicat % alicat tcp://192.168.1.212:4000 --set-flow-rate 1
{
  "control_point": "flow",
  "gas": "N2",
  "mass_flow": 0.0,
  "pressure": 14.3,
  "setpoint": 1.0,
  "temperature": 21.68,
  "volumetric_flow": 0.0
}

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • Update ruff to v0.5.0 (charliermarsh/ruff-pre-commit, ruff)

Detected dependencies

github-actions
.github/workflows/python-package.yml
  • actions/checkout v4@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-python v5
pip_setup
setup.py
  • pytest >=8,<9
  • pytest-cov >=5,<6
  • pytest-asyncio >=0.23.5
  • pytest-xdist ==3.*
  • ruff ==0.4.7
  • mypy ==1.10.1
pre-commit
.pre-commit-config.yaml
  • pre-commit/pre-commit-hooks v4.6.0
  • charliermarsh/ruff-pre-commit v0.4.7

  • Check this box to trigger a request for Renovate to run again on this repository

Interface/Transport Separation

Most of the use case of Alicats is through a serial/USB connector. I have an asyncio TCP adapter which we use internally but the implementation is a full duplication of the interface.

Rewriting as interface vs. transport would be DRY and allow extending to other transports if needed.

Cannot Read two Flow Meters/controllers at the same time

Hi,

I have two Alicat flow meters. When I connect each one individually to my computer through a BB9-232 multi-drop breakout box, I can read their outputs through the alicat python module (see my test code below). However, when I connect both controllers to the box and run the same code, I see the following error. How can I solve this issue?

UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 12: ordinal not in range(128)

import alicat
import time

i = 0
while True:
   try:
       flow_meter_1 = alicat.FlowMeter(port = 'COM4', address = 'A')
       flow_meter_2 = alicat.FlowMeter(port='COM4', address='B')
       if i == 0:
           print("Flow meter's numbers: ")
       print (flow_meter_1.get())
       print(flow_meter_2.get())
       time.sleep(2)
       i+=1
   except KeyboardInterrupt:
       flow_meter_1.close()
       flow_meter_2.close()
       break

Why is the setpoint only configured to two decimal points of precision?

We're encountering an issue with our test system where we divide a fixed total flow between various MFC's that have different max flow capabilities. The total flow often shows small, but noticeable errors that are degrading our experimental data.

I finally tracked the problem down to the fact that _set_setpoint() in serial.py only sets the setpoint to two decimal places of precision. Our flow rates are getting rounded up by this function. e.g. 0.376 SLPM is being set as 0.38 SLPM. This flow controller is a 1 SLPM max flow device, so the code is artificially limiting its precision to 1 part in 100, whereas the actual nominal capability is 1 part in 64,000. The driver is effectively degrading the precision of the device.

To my mind, this is clearly a bug.

In the documentation, I see that the serial protocol of these MFC's allows for the setpoint to be configured as an integer between one and 64000. So I can work around the problem by writing my own version of set_flow_rate(), but it's really frustrating that the standard API doesn't provide a way to access this capability.

set_flow_rate throws error when maximum ramp rate != 0

A maximum ramp rate can be set on Alicat flow controllers. When this ramp rate is set to a non-zero value, the set_flow_rate command throws an error since the current setpoint does not equal the commanded setpoint. TheAlicay _unit_id_LS command returns both the current setpoint and the commanded setpoint. Using this command to verify that the instrument has correctly received the commanded setpoint would allow the set_flow_rate command to work while a maximum flow rate is set.

"OSError: Could not read from flow controller" when setting setpoints on GP firmware

While communicating with an Alicat Mass Flow Controller I get the following error when I try to set the flow rate or pressure setpoint :
OSError: Could not read from flow controller. The complete error message from Python is :

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Maxime\AppData\Local\Programs\Python\Python310\lib\site-packages\alicat\serial.py", line 274, in set_flow_rate
    self._set_setpoint(flow, retries)
  File "C:\Users\Maxime\AppData\Local\Programs\Python\Python310\lib\site-packages\alicat\serial.py", line 298, in _set_setpoint
    line = self._write_and_read(command, retries)
  File "C:\Users\Maxime\AppData\Local\Programs\Python\Python310\lib\site-packages\alicat\serial.py", line 189, in _write_and_read
    raise IOError("Could not read from flow controller.")
OSError: Could not read from flow controller.

I am able to use get() and set_gas() successfully but not set_flow_rate() or set_pressure(). This happens both with the 0.3.1 and 0.4.0 versions of the package.

The code I currently use is :

from alicat import FlowController
flow_controller = FlowController(port='COM9')
print(flow_controller.get())
flow_controller.set_gas('Air')
flow_controller.set_flow_rate(1.0)

ARMv7l: error on start

On a Raspberry Pi 3 B+, alicat fails to run with both Python 2.7.15 and 3.7.1.

Traceback (most recent call last):
  File "/home/alarm/.local/bin/alicat", line 10, in <module>
    sys.exit(command_line())
  File "/home/alarm/.local/lib/python2.7/site-packages/alicat/__init__.py", line 47, in command_line
    command_line(args)
  File "/home/alarm/.local/lib/python2.7/site-packages/alicat/serial.py", line 345, in command_line
    flow_controller = FlowController(port=args.port, address=args.address)
  File "/home/alarm/.local/lib/python2.7/site-packages/alicat/serial.py", line 234, in __init__
    FlowMeter.__init__(self, port, address)
  File "/home/alarm/.local/lib/python2.7/site-packages/alicat/serial.py", line 40, in __init__
    self.connection = serial.Serial(port, 19200, timeout=1.0)
AttributeError: 'module' object has no attribute 'Serial'
Traceback (most recent call last):
  File "/home/alarm/.local/bin/alicat", line 6, in <module>
    from alicat import command_line
  File "/home/alarm/.local/lib/python3.7/site-packages/alicat/__init__.py", line 44
    from alicat.async import command_line
                    ^
SyntaxError: invalid syntax

Batch mode

Hi! I'm just starting to work with Alicat flow controller.
And I want to use batch mode for my application. Unfortunately I haven't found solution in this driver.
Is it possible to use batch mode via python?
Thanx in advanse!

Cant get info through BB3-232 Alicat platform

Hi Guys,

I am trying to access alicat information through python in anaconda. I have my code written like this:
import asyncio
import nest_asyncio
from alicat import FlowController

nest_asyncio.apply()
async def get():
async with FlowController(address="COM9", unit='A',baudrate=19200) as flow_controller:
flow_controller.timeout=None
data = await flow_controller.get()

    return data       

loop = asyncio.get_event_loop()
ans = loop.run_until_complete(get())
massflow = ans['mass_flow']

it works when I connect a single MFC through 8-pin din cable to RS-232 to PC, but it did not work when I try to use this code to get data through alicat BB3-232 platform that allows me to connect multiple MFCs together. it gives me this error message:
File ~\anaconda3\Lib\site-packages\alicat\driver.py:474 in _get_control_point
value = int(line.split('=')[-1])

ValueError: invalid literal for int() with base 10: ' 37\r\x00'

it seems like when the signal goes through the platform, extra data was generated. Please help me solve this issue. Thank you so much!!

Reading control point does not work on old firmware

_read
    await self._init_task
  File "/Users/a.ruddick/Documents/github/alicat/alicat/driver.py", line 314, in _init_control_point
    self.control_point = await self._get_control_point()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/a.ruddick/Documents/github/alicat/alicat/driver.py", line 479, in _get_control_point
    raise ValueError(f"Unexpected register value: {value:d}") from None
ValueError: Unexpected register value: 4

S/N 105527

firmware 4v25

Incorrect readings from locked devices

❯ alicat /dev/tty.usbserial-FTCJ5EK9 --lock
{
  "control_point": null,
  "gas": "LCK",
  "mass_flow": "+000.00",
  "pressure": "+014.46",
  "setpoint": "000.00",
  "temperature": "+026.54",
  "total flow": "Air",
  "volumetric_flow": "+000.00"
}

"OSError: Could not read control point" when calling flow_controller.get() and totalizer

Hi, I was simply just logging the "mass_flow" by calling
image

It has been continously running for while, but alsway interupped by "OSError: Could not read control point."
problem1

It has happened for "reset_totalizer" function, too. Then I used
try:
asyncio.run(reset_totalizer(MFC2))
except OSError:
continue
to ignore it, though I am not sure it's the best way to do so. But it bypassed the error.

But now it occurs at "asyncio.run(get_mfc()" that I cannot bypass it.

I read another thread about the same OSError, but on GP firmware. My firmware is 10v09.0-R24.

'MOV', 'VOV' extra cases

in the get method "def get(self, retries=2):", you have a check for MOV and VOV conditions.
I have an alicat where the VOV was in capital case from the alicat instrument, and therefore caused issues in the check farther down, causing the float(v) operation to be done on a string:
return {k: (v if k == self.keys[-1] else float(v))
for k, v in zip(self.keys, values)}

The fix is to check for capital case as well:
while values[-1] in ['MOV', 'VOV', 'Mov', 'Vov']:
del values[-1]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.