Hello all,
I have recently finished a project where I try to make a water sampler using a pre programmed sampling protocol that a user initiates with the push of a button. The protocol is set to collect 35mL of fluid every 15 minutes. I realized I had made a mistake and while testing overnight, the water source had been empty and the DC motor had been running continuously for hours trying to collect 35mL of fluid. Because of this, I modified my sketch so that pump runs until it collects 35mL of fluid, OR, the pump has been running for 45000 millis
case PumpState:
if (totalMilliLitres > 35 || currentMillis - startMillis > 45000) /// did we collect 35mL? if not, go to next stage after 45000 millis
state = PausingState;
else
I also became worried that the pump would still continue its cycle after collection a gallon of fluid, so I implemented a float switch which is supposed to keep the state change from going to pump state if the float switch is open
case RestState:
if (currentMillis - startMillis > 900000 && (digitalRead(floatSwitchPin) == LOW)) // has it been 15 minutes AND the float switch is still open?
{
state = PumpState;
startMillis = currentMillis; // Reset the start time of the pumping sequence.
totalMilliLitres = 0; //reset totalMilliLitres so it can start counting up from 0 again
}
else
pumpOff();
lcd.setCursor(0, 0);
lcd.print("REST ");
break;
I know this isn't the best solution, as the sketch immediately resumes if the float switch is closed again. I'd like the float switch to act as a trigger which stops the loop similarly to how the program stops if the sampling button is pressed again after starting the sampling protocol.
But what I figured would be very beneficial is to implement a system where the Arduino sends a SMS message that says "Missed sample" if the loop does not collect 35mL before going to the next state, and also an SMS message when the collection jar is full and the normally closed float switch is opened. Id also like to learn if it is possible to send SMS messages from the arduino when certain volumes of fluid are detected. for example, if the volume collected is 946mL, could the arduino send a SMS that says "1/4 full"? Im not exactly sure what equipment I'd need for this integration either and would appreciate advice on that as well.
I do know that for this project, I will be using a Nano Board ATmega328P instead of an uno like my last project as id like to place the nano and pcb in a small enclosure within a larger/main enclosure so that instead of having the pump protruding from the enclosure, it is contained within, saving space inside the enclosure for further expanding and ensuring a small footprint. I do understand the risks of leaks within the enclosure however, which is why I'd also like to implement water detector sensors inside the enclosure to stop the sampling program and send an SMS alert that says "Leak detected".
So in summary I would like to inegrate the following features:
- Integrate SMS capability that sends alert when a sample is missed
- integrate SMS capability that send alert when float switch is open
*Integrate SMS capability that sends alert when leak is detected
*Integrate program stop capability when float switch is open or water sensor detects water. I know this is a lot, but I've been stuck on this for a few days now. I've also included the code for the sampling protocol in this post. Any advice or suggestions are appreciated.
#include <LiquidCrystal.h>
// using Pololu DRV8876 (QFN) Single Brushed DC Motor Driver Carrier
const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 4;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
unsigned long startMillis; // Keeps track of millis() when the pumping cycle starts.
unsigned long currentMillis; // millis() of the current loop.
unsigned long currentMilliss;
// constants for Arduino IO-Pins with SELF-explaining names
const byte samplingBtnPin = 7;
const byte primeBtnPin = 5;
const byte purgeBtnPin = 6;
const byte floatSwitchPin = 3;
const byte DRV8876_IN1_PIN = A0;
const byte DRV8876_IN2_PIN = A1;
// constants for the states with SELF-explaining names
const byte OffState = 0;
const byte PumpState = 1;
const byte PausingState = 2;
const byte ReverseState = 3;
const byte RestState = 4;
const byte FullState = 5;
byte state;
#define pressed HIGH
#define released LOW
#define closed HIGH
#define open LOW
// flow sensor and float switch//
byte statusLed = 13;
byte sensorInterrupt = 0; //0 = digital pin 2
byte sensorPin = 2; //flow sensor input
//byte floatSwitch = 3;
//pulse count and flow settings//
float calibrationFactor = 123; //F=79*Q
volatile byte pulseCount; // counts the pulses of flow sensor
float flowRate;
unsigned int flowMilliLitres; //totaltotalMilliLitres used for the interrupts
unsigned long totalMilliLitres;
unsigned long oldTime;
unsigned long cloopTime; // to count pulses per second
unsigned long vol; //vol tracks total volume throughout loop
void pulseCounter()
{
// Increment the pulse counter
pulseCount++;
}
void setup()
{
lcd.begin(16 , 2); // screen size
// lcd.print("Ready ");
pinMode(primeBtnPin, INPUT_PULLUP); // pinMode(5, INPUT);
pinMode(purgeBtnPin, INPUT_PULLUP); // pinMode(6, INPUT);
pinMode(samplingBtnPin, INPUT_PULLUP); // pinMode(7, INPUT);
pinMode(DRV8876_IN1_PIN, OUTPUT); // pinMode(A0, OUTPUT);
pinMode(DRV8876_IN2_PIN, OUTPUT); // pinMode(A1, OUTPUT);
// Set up the status LED line as an output
pinMode(statusLed, OUTPUT);
digitalWrite(statusLed, HIGH);
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);
pinMode(floatSwitchPin, INPUT_PULLUP);
digitalWrite(floatSwitchPin, HIGH);
pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0.0;
totalMilliLitres = 0;
vol = 0;
cloopTime = currentMillis;
currentMillis = millis();
// The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
// Configured to trigger on a FALLING state change (transition from HIGH
// state to LOW state)
attachInterrupt(sensorInterrupt, pulseCounter, RISING);
}
void loop()
{
currentMillis = millis(); // Get the current value of millis().
if (digitalRead(samplingBtnPin) == released)
if (state > OffState) // Are we already in a pumping cycle?
state = OffState;
else
state = PumpState;
delay(200); // Small delay to debounce the button.
///////////////////
//flow rate loop//
/////////////////
if (currentMillis >= (cloopTime - 1000))
{
cloopTime = currentMillis;
if (pulseCount != 0) {
flowRate = (pulseCount / calibrationFactor);
//oldTime = millis();
flowMilliLitres = (flowRate / 60) * 1000;
totalMilliLitres += flowMilliLitres;
vol += flowMilliLitres;
//((1000.0 / (millis() - currentMillis)) *
;
lcd.begin(16, 2);
lcd.print("Rate: ");
lcd.setCursor(5, 0);
lcd.print(flowRate);
lcd.setCursor(11, 0);
lcd.print("L/Min");
lcd.setCursor(0, 1);
// print total volume
lcd.print("Vol: ");
lcd.print(totalMilliLitres);
lcd.print(" mL");
pulseCount = 0;
}
else {
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("Rate: ");
lcd.print ( pulseCount); // resets flow rate to 0
lcd.print (" L/m");
lcd.setCursor(0, 1);
lcd.print("Vol:");
lcd.print(vol);
lcd.print(" mL");
}
}
switch (state) // Check which state we are in.
{
case OffState:
while (digitalRead(primeBtnPin) == released) // Prime button being pressed?
PumpForward(); // Turn on the pump.
while (digitalRead(purgeBtnPin) == released) // Purge button being pressed?
PumpReverse(); // Reverse the pump
startMillis = currentMillis; // Keep resetting the start time of the pumping sequence.
pumpOff();
break;
case PumpState:
if (totalMilliLitres > 35 || currentMillis - startMillis > 45000) /// did we collect 35mL? if not, go to next stage after 45000 millis
state = PausingState;
else
PumpForward();
lcd.setCursor(0, 0);
lcd.print("PUMP ");
break;
case PausingState:
if (currentMillis - startMillis > 52000) // Have we been in this state too long?
state = ReverseState;
else
pumpOff();
lcd.setCursor(0, 0);
lcd.print("REST ");
break;
case ReverseState:
if (currentMillis - startMillis > 90000) // Have we been in this state too long?
state = RestState;//state++;
else
PumpReverse();
lcd.setCursor(0, 0);
lcd.print("PURGE");
break;
case RestState:
if (currentMillis - startMillis > 900000 && (digitalRead(floatSwitchPin) == LOW)) // has it been 15 minutes AND the float switch is still open?
{
state = PumpState;
startMillis = currentMillis; // Reset the start time of the pumping sequence.
totalMilliLitres = 0; //reset totalMilliLitres so it can start counting up from 0 again
}
else
pumpOff();
lcd.setCursor(0, 0);
lcd.print("REST ");
break;
}
}