Go Down

Topic: I have ran out of talent with automated filtration system (Read 2352 times) previous topic - next topic

wildbill

Looking at the schematic, it seems to me that Vcc is the 3.3V connection.

RealHousewifeofIdaho

After testing I have learned a few things...

First I changed the code to just print the pressure difference so I can easily see it as it comes across the monitor, instead of pre and post psi.

Code: [Select]
if (!inFlush)
  {
    ManageManualFlush();
  }
  prePsi = GetPsi(preSensorPin);
  //Serial.print("Pre-filter psi: ");
  //Serial.print(prePsi);
  postPsi = GetPsi(postSensorPin);
  //Serial.print("  Post-filter psi: ");
  //Serial.println(postPsi);
  Serial.println("Pressure Drop");
  Serial.println(prePsi - postPsi);
  delay(2000);                                                      //delay in between reads for stability
  ManageFlush();
  CheckFilter();
  ManageFilterLeds();
}


Next I put a dirty filter, which I would consider being a filter in between the order and change state, and my yellowLED threshold does not light up consistently, even though I see a pressure difference that should trigger the yellow LED come across the monitor. Based on the testing so far, I have yellowLEDThreshold at 1.25psi and redLEDThreshold at 1.50psi. My best guess as to why the LED is not coming on when the difference is greater than the set threshold is the input data is too sporadic??

My best guess for a solution to this is to add the smoothing library to the sketch. I am not sure which type of value store would be better, smoothed average or smoothed exponential. I am just not sure how to add the smoothed values into the code smoothly(dad joke). Here is what I got so far.

Code: [Select]
/*
REV_5
Automated Water Filter System
2/8/19
*/

//#define BLYNK_PRINT Serial
#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
#include <Smoothed.h>

enum FilterStatus {FilterOk, OrderFilter, ChangeFilter};

//float prePsi;      //declaring pre-filter sensor psi
//float postPsi;     //declaring post-filter sensor psi
Smoothed <float> prePsi;
Smoothed <float> postPsi;

byte preSensorPin = A3;   //assigning pre-filter sensor to A0
byte postSensorPin = A1;  //assigning pre-filter sensor to A1

const byte yellowLEDPin = 2;            //assigning pin number to yellow LED
const byte redLEDPin = 5;               //assigning pin number to red LED
const byte flushValveSolenoidPin = 7;   //assigning pin number to flush valve
const byte buttonPin = A2;              //assigning a pin number to button
const byte hotPin = 6;                  //assigning a pin to hot wire

float redLEDThresholdPsi = 1.5;       //assigning a pressure threshold for red LED to illuminate
float yellowLEDThresholdPsi = 1.25;     //assigning a pressure threshold for yellow LED to illuminate
int flushValveThresholdPsi = 55;   //assinging a pressure threshold for flush out valve to open

const uint32_t flushValveDelay = 5000UL;  //assigning a delay for flush out valve
const uint32_t minFlushInterval = 2UL * 60UL * 1000UL; // Minimum time between flushes, however invoked

uint32_t flushValveOnAtMs = 0 ;  // flush timer
bool inFlush = false ;           // flush timer status
FilterStatus FilterCondition = FilterOk;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "42b088f5285542f0aeced22e4cce6ee4";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "";


void setup()
{
  Serial.begin(115200);
  Serial.println("\nStarting...");
  pinMode(preSensorPin, INPUT);        //sets pre-filter sensor value as input
  pinMode(postSensorPin, INPUT);       //sets post-filter sensor value as input
  pinMode(yellowLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(flushValveSolenoidPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(hotPin, OUTPUT);
  Blynk.begin(auth, ssid, pass);
  prePsi.begin(SMOOTHED_EXPONENTIAL, 10);
  postPsi.begin(SMOOTHED_EXPONENTIAL, 10);
}

void loop()
{
   Blynk.run();
   
   digitalWrite(hotPin, HIGH);
   
  if (!inFlush)
  {
    ManageManualFlush();
  }
  prePsi = GetPsi(preSensorPin);
  //Serial.print("Pre-filter psi: ");
  //Serial.print(prePsi);
  postPsi = GetPsi(postSensorPin);
  //Serial.print("  Post-filter psi: ");
  //Serial.println(postPsi);
  Serial.println("Pressure Drop");
  Serial.println(prePsi - postPsi);
  delay(2000);                                                      //delay in between reads for stability
  ManageFlush();
  CheckFilter();
  ManageFilterLeds();
}

float GetPsi(byte AnalogPin)
{
  int SensorValue = analogRead(AnalogPin);                       //read raw reading from sensor
  float Voltage = (5.0 / 1023.0) * SensorValue;                  //calculating voltage from raw reading
  return (Voltage - 0.5) * (100.0) / (4.5 - 0.5);                //calculating psi from voltage
}

void CheckFilter()  // Filter condition state machine
{
  // All we can do is go from OK to order or from Order to change
  switch (FilterCondition)
  {
    case FilterOk:
      if (prePsi - postPsi > yellowLEDThresholdPsi)      //  if the pressure drop is greater than Order threshold
      {
        Serial.println("Order filter");
        FilterCondition = OrderFilter;
      }
      break;
    case OrderFilter:
      if (prePsi - postPsi > redLEDThresholdPsi)        //if the pressure drop is greater than replace threshold
      {
        Serial.println("Change filter");
        FilterCondition = ChangeFilter;
      }
      break;
    case ChangeFilter:  // Once we're in this state, only a reset will change it.
      break;
  }
}

void ManageFilterLeds()
{
  switch (FilterCondition)
  {
    case FilterOk:
    //Serial.println("Leds off - filter ok");
      digitalWrite(redLEDPin, LOW);
      digitalWrite(yellowLEDPin, LOW);
      break;
    case OrderFilter:
    //Serial.println("Show yellow - order filter");
      digitalWrite(redLEDPin, LOW);
      digitalWrite(yellowLEDPin, HIGH);
      break;
    case ChangeFilter:
    //Serial.println("Show red - replace filter");
      digitalWrite(redLEDPin, HIGH);
      digitalWrite(yellowLEDPin, LOW);
      break;
  }
}

void ManageManualFlush()
{
  if (digitalRead(buttonPin) == LOW && !inFlush)
  {
    Serial.println(F("Manual flush"));
    StartFlush();
  }
}

void ManageFlush()
{
  if ( inFlush && millis() - flushValveOnAtMs >= flushValveDelay )  // if flush timer expired stop flushing
  {
    StopFlush();
  }
  if (!inFlush && prePsi < flushValveThresholdPsi)    // if the psi is lower than threshold see if it's time for an auto flush
  {
    FlushIfWeMay();
  }
}

void StartFlush()
{
  {
    inFlush = true;
    digitalWrite(flushValveSolenoidPin, HIGH);   // open flush out valve
    flushValveOnAtMs = millis();                 // start flush timer
    Serial.println(F("Start flush timer"));
  }
}

void StopFlush()
{
  digitalWrite(flushValveSolenoidPin, LOW);         //close flush out valve
  inFlush = false;
  Serial.println(F("Stop flush timer"));
}

void FlushIfWeMay()  // Flush if enough time has passed since the last one or if we don't know when the last one was
{
  if ((millis() - flushValveOnAtMs > minFlushInterval) || flushValveOnAtMs == 0)  // Honour an initial request for flush - who knows when we did it last
  {
    Serial.println(F("Auto flush"));
    StartFlush();
  }
  else
  {
    Serial.print(F("Flush request denied - did one too recently. Next opportunity in: "));
    Serial.print((minFlushInterval - (millis() - flushValveOnAtMs)) / 1000UL);
    Serial.println(F(" seconds."));
  }
}


If folks have a better idea to solve the issue I am all ears.

wildbill

The FilterCondition variable is used to run a little state machine in CheckFilter and to light the appropriate LED in ManageFilterLeds.

By design, once you break the order threshold (yellow) once, the code does not have a path back to filterok. Similarly, there's no way out of the change filter state other than a restart. There should be no need for any smoothing.

Possible issues:
  • There is a power issue and the Arduino is getting restarted - existing serial prints should tell you that
  • Something is writing outside its bounds and corrupting FilterCondition
  • Wiring issue with the LEDs


I'd suggest that you uncomment the print statements in ManageFilterLeds and use them to see what state the code thinks it has. You may want to add a default case to the end to catch unexpected values.

Also, for now, comment all that blynk stuff out - you're not using it anyway.

RealHousewifeofIdaho

Thank you for the response. I am getting a chance to do some more testing today, this week has been crazy with finals.
This is copied from the serial monitor, with water pressure coming in, but no water coming out. So the system is closed off, and there should be no pressure drop across the filter.

Code: [Select]
Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.59
Pressure Drop
0.61


Leds off - filter ok
Pre-filter psi: 71.08  Post-filter psi: 70.59
Pressure Drop
0.49


Leds off - filter ok
Pre-filter psi: 71.08  Post-filter psi: 70.34
Pressure Drop
0.73


Leds off - filter ok
Pre-filter psi: 70.47  Post-filter psi: 70.83
Pressure Drop
-0.37


Leds off - filter ok
Pre-filter psi: 71.32  Post-filter psi: 71.08
Pressure Drop
0.24


Leds off - filter ok
Pre-filter psi: 71.08  Post-filter psi: 71.20
Pressure Drop
-0.12


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.83
Pressure Drop
0.37


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.96
Pressure Drop
0.24


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 71.08
Pressure Drop
0.12


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.71
Pressure Drop
0.49


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.47
Pressure Drop
0.73


Leds off - filter ok
Pre-filter psi: 70.96  Post-filter psi: 70.71
Pressure Drop
0.24


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.22
Pressure Drop
0.98


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 70.83
Pressure Drop
0.37


Leds off - filter ok
Pre-filter psi: 71.08  Post-filter psi: 70.71
Pressure Drop
0.37


Leds off - filter ok
Pre-filter psi: 71.44  Post-filter psi: 70.96
Pressure Drop
0.49


Leds off - filter ok
Pre-filter psi: 71.20  Post-filter psi: 71.08
Pressure Drop
0.12


Leds off - filter ok
Pre-filter psi: 72.06  Post-filter psi: 70.71
Pressure Drop
1.34


Order filter
Show yellow - order filter
Pre-filter psi: 71.32  Post-filter psi: 70.47
Pressure Drop
0.86


Show yellow - order filter
Pre-filter psi: 71.20  Post-filter psi: 70.96
Pressure Drop
0.24


Show yellow - order filter
Pre-filter psi: 71.20  Post-filter psi: 70.83
Pressure Drop
0.37




As you can see, with the system closed off, the numbers are dancing around like crazy. Any ideas what I can do? With the threshold values being 1.25 and 1.5, I need these sensors to input more precise readings.

RealHousewifeofIdaho

For the sensor-
Specifications:
Supply voltage:5 VDC
Output voltage :0.5 ~ 4.5 V
Working pressure :0 ~ 1 MPA
Performance Guarantee pressure range:3 MPA
Burst Pressure : 5 MPA
Overall accuracy :1% FS
Long-term stability : 0.2% FS / year
Works for oil,fuel,diesel,gas,water,air pressure
Operating temperature: -40 ~ 125 degree Centigrade
Storage temperature : -40 ~ 130 degree Centigrade
Package Include: 1 X Pressure Transducer

I have added a quick wiring schematic to my pictures in the album

https://photos.app.goo.gl/vxqa8HkuvFk7Mw977

6v6gt

You appear to have connected pin 6 and pin A2 together. Pin 6 is an output pin and set HIGH in the loop. Pin A2 is an input pin (internal pull up resistor activated) with a button switch on it to ground. When the button is pressed, pin 6 will be directly shorted to ground.


You may not be using the Smoothed.h library correctly according to my understanding of the example in the help information.

For example:

Code: [Select]
prePsi = GetPsi(preSensorPin);

should be:

Code: [Select]
prePsi.add( GetPsi(preSensorPin) ) ;


and

Code: [Select]
Serial.print(prePsi);

should be:

Code: [Select]
Serial.print(prePsi.get() );

RealHousewifeofIdaho

You appear to have connected pin 6 and pin A2 together. Pin 6 is an output pin and set HIGH in the loop. Pin A2 is an input pin (internal pull up resistor activated) with a button switch on it to ground. When the button is pressed, pin 6 will be directly shorted to ground.


You may not be using the Smoothed.h library correctly according to my understanding of the example in the help information.

For example:

Code: [Select]
prePsi = GetPsi(preSensorPin);

should be:

Code: [Select]
prePsi.add( GetPsi(preSensorPin) ) ;


and

Code: [Select]
Serial.print(prePsi);

should be:

Code: [Select]
Serial.print(prePsi.get() );
I am using pin 6 has a hot 3.3v for a pull-up resistor, as the flush out control button is set to see LOW for the the valve to open. The button seems to be working fine with the wiring/code set up that way.

As for the smoothed.h library, another poster above mentioned that smoothing out my inputs would not solve my problem. I tend to agree since my inputs are dancing everywhere, which seems more like an interference issue.

RealHousewifeofIdaho

So after thinking about it, I realize that I am trying to shoot for something I am not going to hit with those sensors. The accuracy of those sensors are 1%, so it can swing about .7psi at my working pressure. With the yellow threshold at 1.25psi, there is no way they will work. I did find some Honeywell units-

https://www.alliedelec.com/product/honeywell/px3an1bh150psaax/70838333/

Which have .25% accuracy, so .178 psi swing at aprox working pressure, which is getting closer to what I need. 

6v6gt

You've activated the pull-up resistor on A2 so the connection between A2 and 6 should not required. Anyway, you can't short an output high pin directly to ground without risking damage.

Are your pressure measurements static or is there water running through the system like a water tap turned on at the time you did the measurements? In a static situation, I would not have expected to see a really measureable pressure difference even with a partially blocked filter.

It is possible to get differential pressure measurement devices, but these are expensive.

To rule out any problems with your current sketch causing the erratic readings, maybe write a simple sketch which just outputs in the loop() the analog value read from one sensor to see how stable it is. Sometimes it can help to do two analogRead() statements together and ignore the first one if there is a delay between readings because the ADC takes time to stabilize. Also, if the voltages you are measuring are low, and depending on the resolution of the ADC, even a change of +/- one analog unit could be interpreted as a significant change in pressure.

Edit

I've just looked at the ADC of SAMD based boards of which your MKR WIFI 1010 is one.
It has a 12 bit ADC but the default resolution for the analogRead() is 10 bit so the range returned is 0 to 1023. You can set a better resolution by using analogReadResolution(). The voltage reference is 3.3 volts.

There are some problems with your function GetPsi()

Code: [Select]

float GetPsi(byte AnalogPin)
{
  int SensorValue = analogRead(AnalogPin);                       //read raw reading from sensor
  float Voltage = (5.0 / 1023.0) * SensorValue;                  //calculating voltage from raw reading
  return (Voltage - 0.5) * (100.0) / (4.5 - 0.5);                //calculating psi from voltage
}


which I have corrected with comments based on the specification of the pressure sensor.

Code: [Select]

float GetPsi(byte AnalogPin)
{
  int SensorValue = analogRead(AnalogPin);                       //read raw reading from sensor
  float Voltage = (3.3 / 1024.0) * SensorValue;                  //calculating voltage from raw reading (3.3v ref)
  return (Voltage - 0.5) * (145.0) / (4.5 - 0.5);                //calculating psi from voltage (10MPA is 145PSI)
  // hopefully, the pressure is low enough that the limit of 3.3 volts on the MKR1010 analog pin is not exceeded.
  // If in doubt, use a voltage divider and adjust the formula accordingly.
}


So I guess you'll now be seeing pressures around 62 PSI.

So, with the ADC resolution of 10 bits (ie range 0-1023) a single unit is equivalent to about 0.11 PSI.
If that is too coarse, then set the resolution to 12 bits and adjust the formula.

Is the 5 volt supply for the pressure sensors is derived from the PC's USB ?  If that is not very stable that could also affect the analogRead() values.

Go Up