0

I have a water pump with pressure sensors. One on the input (low) and one on the output (high). My problem is my low pressure sensor. Sometimes the low pressure is just at the cut-off point causing the motor to start and stop quickly - this is not desirable. The system is running on a home-made PLS.

I'm a beginner at programming, 3 months, but the system is working for the most part. I need help on creating a timer between low pressure alarm events. I am thinking that the system can have 3 events within 30 seconds, but if any one event occurs in less than 5 seconds the system should shut down.

So if less than 5 seconds between the first event and second event the motor shuts down for good. The same goes for for second to third and third to fourth event. On the fourth event if less than 30 seconds occurs between first event and the fourth, the system also shuts down for good. Keep in mind that this is a part of a much larger loop. Here is the code I was able to create:

def Systemofftimer():
    EventCounter = (0)
    OneTimeLoopVarable = (0)
    While True
        if (is_low_pressure_alarm_on() and (OneTimeLoopVarable ==0)):
            Timer = time.time()
            EventCounter = EventCounter + (1)
            OneTimeLoopVarable = 1


            if EventCounter == (2) and (time.time() - Timer >= (10))
                EventCounter = EventCounter + (1)
                stop_motor()


            if EventCounter == (3) and (time.time() - Timer >= (20))
                EventCounter = EventCounter + (1)
                stop_motor()

            if EventCounter == (4) and (time.time() - Timer >= (30))
                EventCounter = EventCounter + (1)
                stop_motor()
        else:
            start_motor()
Anthony Pham
  • 3,096
  • 5
  • 29
  • 38
RuneM
  • 3
  • 2
  • A little more info. low pressure sensor is for water pressure going into the pump - High pressure sensor is for water leaving the pump. – RuneM Jul 05 '15 at 20:46

1 Answers1

0

I would actually use a different approach for this: simply make your threshold for turning on larger than your threshold for turning of. For example: graph

That way you don't need to deal with the timing of it and can still eliminate the jittery nature around your state transition. You can also tune this to account for how noisy your sensors are.

Edit:

Below I've mocked up the piece of your system you're asking about. It's probably way more than you were initially looking for, but I wanted to test make sure it all worked properly before I posted so you're welcome to use it in whole or in part. As for the timer you asked about, it's based on Hans Then's post from this thread. To trigger the alarm, you just call TriggerAlarm() on the PumpSystem class. It will log that an alarm was triggered and then check the two conditions you mentioned in your question (5 sec and 30 sec errors). Each element of self.alarms contains the number of alarms that happened in a particular second, and each second the timer triggers to remove the oldest second from the list and create a fresh one. If you run the program, you can trigger alarms by pressing spacebar and see how the list is updated. The MockUp class is just meant to test and demonstrate how this works. I imagine you'll remove it if you decide to plug some portion of this into what you're working on. Anyway, here's the code.

from threading import Timer, Thread, Event

class PumpSystem():
    def __init__(self):
        self.alarms = [0 for x in range(30)]
        self.Start()
        return None

    def SetUpdateFlag(self, flag):
        self.update_flag = flag
        return True

    def Start(self):
        self.stop_flag = Event()
        self.thread = ClockTimer(self.OnTimerExpired, self.stop_flag)
        self.thread.start()
        return True

    def Stop(self):
        self.stop_flag.set()
        return True

    def TriggerAlarmEvent(self):
        self.alarms[-1] += 1
        self.CheckConditions()
        self.update_flag.set()
        return True

    def OnTimerExpired(self):
        self.UpdateRunningAverage()

    def CheckConditions(self):
        # Check if another error has triggered in the past 5 seconds
        if sum(self.alarms[-5:]) > 1:
            print('5 second error')

        # Check if more than 3 errors have triggered in the past 30 seconds
        if sum(self.alarms) > 3:
            print('30 second error')

        return True

    def UpdateRunningAverage(self):
        self.alarms.append(0)
        self.alarms.pop(0)
        self.update_flag.set()
        return True

class ClockTimer(Thread):
    def __init__(self, callback, event):
        Thread.__init__(self)
        self.callback = callback
        self.stopped = event
        return None

    def SetInterval(self, time_in_seconds):
        self.delay_period = time_in_seconds
        return True

    def run(self):
        while not self.stopped.wait(1.0):
            self.callback()
        return True


## START MOCKUP CODE ##

import tkinter as tk
class MockUp():
    def __init__(self):
        self.pump_system = PumpSystem()
        self.update_flag = Event()
        self.pump_system.SetUpdateFlag(self.update_flag)
        self.StartSensor()
        return None

    def StartSensor(self):
        self.root = tk.Tk()
        self.root.protocol("WM_DELETE_WINDOW", self.Exit)
        self.alarms = tk.StringVar()
        w = tk.Label(self.root, textvariable=self.alarms, width=100, height=15)
        self.alarms.set(self.pump_system.alarms)
        w.pack()
        self.root.after('idle', self.ManageUpdate)
        self.root.bind_all('<Key>', self.ManageKeypress)
        self.root.mainloop()
        return True

    def ManageUpdate(self):
        if self.update_flag.isSet():
            self.alarms.set(self.pump_system.alarms)
            self.update_flag.clear()
        self.root.after(1, self.ManageUpdate)
        return True

    def ManageKeypress(self, event):
        if event.keysym == 'Escape':
            self.Exit()
        if event.keysym == 'space':
            self.pump_system.TriggerAlarmEvent()
        return True

    def Exit(self):
        self.pump_system.Stop()
        self.root.destroy()


mockup = MockUp()

This may look like a lot, but half is the mockup class that you can probably just ignore. Let me know if there's anything that you're confused about and I'd be happy to explain what's happening.

Community
  • 1
  • 1
user2027202827
  • 1,234
  • 11
  • 29
  • HI hobenkr Yes i agree I have tried the approach, but the input pressure slowly lowers (going through filters that slowly get clogged) so no matter where I put the cut-off sooner or later the pressure will be hovering there. Thanks for the quick reply :) – RuneM Jul 05 '15 at 19:45
  • I think I accidentally made my graphic backwards :) if you turn the pump on at the lower threshold, wouldn't that push the pressure back up to the upper threshold where it will turn off and then drift back down? Maybe I'm not understanding your problem completely. – user2027202827 Jul 05 '15 at 19:56
  • I am pumping water from a well some distance away, When it gets to my home i have a booster pump that feeds a fancy filter system before going into my home. The problem is there are filters at the well that get clogged. causing my booster pump to turn off and on. So i am making a pls to control the well pump and the booster pump. low pressure sensor is before the booster pump high pressure is after the booster pump. – RuneM Jul 05 '15 at 20:35
  • The sensor is a digital input on or off - on at 5psi off at zero psi, is was a poor choice, but it's what i have. – RuneM Jul 05 '15 at 20:52
  • Thanks for the added info. Sorry to push an alternative to what you're trying to do. I'd just like to see you end up with a good result. I updated my answer to include a mockup of what you describe. Let me know if you have any other questions. – user2027202827 Jul 06 '15 at 08:27
  • WOW!!!! Thanks for the MAJOR effort here!! Absolutely no need for apologies! I must say this is a bit over my abilities, I will need to sit down and try to under stand your code. Ill get back when i get as far as i can understanding your art work :) should not be long :) – RuneM Jul 06 '15 at 11:24
  • No problem, one aspect of this that you may not be familiar with is that it is using events to drive the system (an event loop is kind of like the for loop you were using, it just constantly checks for new events). It adds a bit complexity, but is difficult to avoid if you want to do time based tasks. – user2027202827 Jul 06 '15 at 16:55
  • This works perfect and is a cool solution! I am in the process of integrating it. But I am having a little trouble integrating it into my code. It seems like StackOverFlow is not happy with the extended questions so ill ask a new question with the trouble I am having. Hope to see you there :) – RuneM Jul 06 '15 at 17:26