Interest in a liquid level sensor plugin?

Would it be useful to have a plugin for liquid level sensors? To halt dosing if a media bottle is about to run dry, or to prevent a waste container overflowing, etc. For example, these are pretty cheap and work at 5V: Non-contact Capacitive Liquid Level Sensor for container OD>11mm (5~12V,IP65) - DFRobot

That’s a pretty neat device. I’ve never used one, but I can see the device and an associated plugin being useful (ex: stop/pause dosing jobs when media gets low or waste too high, etc).

The one you linked wouldn’t work however. The output is a binary signal with high being 5.0V. That voltage is too high for the RPi’s GPIO pins which are rated for 3.3V or less. Something like this has the right specs.

Oh duh, yeah - I didn’t find any 3.3V ones initially, so I have just been using a voltage divider (it’s a really slow signal so it seems fine), but that would be much nicer. I might try to make a plugin for it, in that case.

Edit: adding, the board I linked above actually has a DIP to set output to 3.3V or Vin (that I ignored initially due to poor documentation…), so my poor little circuit wasn’t even necessary…

1 Like

Yea the docs are seriously lacking on that, but it does look like there is a switch for 3.3V output! Have you purchased one yet, then?

I did! I ordered one to maybe make an FPLC buffer monitor, and it seemed like it might be useful here as well. It seems to detect liquid levels reasonably well from some initial messing around.

Neat! I’d be happy to help green needle with plugin development:

  1. You could make this a separate job that users run from the UI to monitor their liquid levels. The job can check every N seconds (using the RepeatedTimer class) and if it detects a liquid level change, can perform some actions. I suggested above that useful actions might be to stop any future dosing. This can be done by asking the dosing job to pause, ex:

    def trigger_stop_dosing(self):
      self.publish(f"pioreactor/{self.unit}/{self.experiment}/dosing_control/$state/set", "sleeping")

    A configuration parameter would also be needed to alert is liquid rises too much (waste bin), or liquid falls too much (media bin). Background jobs can add to the config.ini to set a parameter that controls this.

    Monitoring both media and waste is possible, too. Probably requires some duplication of code and configuration.

  2. Another idea to implement this: the base class for DosingAutomations has “hooks” for doing actions before any pumping occurs. Ex:

from pioreactor.automations.dosing.base import DosingAutomationJob
from pioreactor.actions.pump import add_media
from pioreactor.actions.pump import remove_waste

class LiquidLevelError(Exception):

def check_level_of_media_is_okay():
   # TODO
   return True

def check_level_of_waste_is_okay():
   # TODO
   return False

def check_levels_before_adding_media(cls, ml, unit, experiment, source_of_event):
    if check_level_of_media_is_okay() and check_level_of_waste_is_okay():
        return add_media(ml=ml, unit=unit, experiment=experiment, source_of_event=source_of_event)
        raise LiquidLevelError("Check liquid levels of waste or media")

def check_level_before_remove_waste(cls, ml, unit, experiment, source_of_event):
    if check_level_of_waste_is_okay():
        return remove_waste(ml=ml, unit=unit, experiment=experiment, source_of_event=source_of_event)
        raise LiquidLevelError("Check liquid levels of waste")

DosingAutomationJob.add_media_to_bioreactor = check_levels_before_adding_media
DosingAutomationJob.remove_waste_from_bioreactor = check_level_before_remove_waste

This way, the logic is always applied to all media & waste automations and the user doesn’t need to start any new activities from the UI. OTOH, maybe users want to manually turn on detection from the UI.