The first state machine "ODStateMachine" appears to get stuck in the "else" (pump 1 & 2 off) statement of the "ST_ODP1_RUNNING" state once the optical density drops below the set threshold.
What I am seeing:
Once the ODVal drops below threshold, pumps 1 & 2 shut off as expected and the optical density is continuing to be read at it's defined intervals but because pump1 is not turning back on prior each OD reading, the sensor is effectively reading the same sample repeatedly--thus keeping pump1 off.
What I'm trying to accomplish:
When the ODVal is below the threshold to not take another OD reading until the ODStateMachine has reset/pump1 has started its run time anew.
This is only through the ODStateMachine portion:
// Adjustable time points
#define ODP1PUMP_INTERVAL 60000ul // 1 minutes
#define ODP1OD_INTERVAL 30000ul // 0.5 min
const byte OD_HIGH_THRESH = 400; // arbitrary (will change for in-sito testing)
#define ByProductPUMP3_INTERVAL 60000ul // 1 min
#define ByProductPUMP3_RUNTIME 30000ul // 30 sec
#define ByProductPUMP4_INTERVAL 120000ul // 2 min
#define ByProductPUMP4_RUNTIME 60000ul // 1 min
//#include <SD.h> //SD card library
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h> //Real Time Clock library
#include <hd44780.h> //LCD library
#include <hd44780ioClass/hd44780_I2Cexp.h> // include i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config display for hd44780 chip
// LCD
const byte LCD_VCC = 13;
// Optical Density Sensor
const byte ODAnalogIN = A14;
const byte ODVCC = 51;
const byte ODGND = 50;
// Motors & Motor Drivers
const byte P1A = 35;
const byte P1B = 33;
const byte P1PWM = 8;
const byte P2A = 39;
const byte P2B = 41;
const byte P2PWM = 45;
const byte P3A = 38;
const byte P3B = 40;
const byte P3PWM = 46;
const byte P4A = 34;
const byte P4B = 32;
const byte P4PWM = 7;
const byte Driver1STBY = 36;
const byte Driver1VCC = 52;
const byte Driver2STBY = 37;
const byte Driver2VCC = 53;
// GATE VALVES
const byte GV1 = 15; // TO chamber (CHECK PIN#)
const byte GV2 = 29; // TO Hydrocyclone
const byte GV3 = 23; // TO chamber from resin column
const byte GV4 = 22; // TO MeOH collection
const byte GV5 = 25; // FROM flush reservoir
const byte GV6 = 24; // FROM MeOH reservoir
const byte GV7 = 16; // TO flush collection (PIN# SUBJECT TO CHANGE)
void setup()
{
Serial.begin(9600);
//LDC set up
pinMode(LCD_VCC, OUTPUT);
digitalWrite (LCD_VCC, HIGH);
// if (! rtc.begin()) //DS3231 is intialized
// {
// while (1);
// }
//rtc.adjust(DateTime(F(_DATE_), F(_TIME_))); //auto update from computer time
// rtc.adjust(DateTime(2019, 10, 29, 10, 01, 30)); //set date-time manually; yr, mo, day, hr, min, sec
// initialize LCD with number of columns and rows:
lcd.begin(20, 4);
// Print initial message to LCD
lcd.print("RUNNING ");
//set up OD sensor
pinMode (ODVCC, OUTPUT);
pinMode (ODGND, OUTPUT);
digitalWrite (ODVCC, HIGH);
digitalWrite (ODGND, LOW);
//set up Gate Valves
pinMode (GV1, OUTPUT);
pinMode (GV2, OUTPUT);
pinMode (GV3, OUTPUT);
pinMode (GV4, OUTPUT);
pinMode (GV5, OUTPUT);
pinMode (GV6, OUTPUT);
pinMode (GV7, OUTPUT);
//set up motor control pins
pinMode (P1A, OUTPUT);
pinMode (P1B, OUTPUT);
pinMode (P1PWM, OUTPUT);
pinMode (P2A, OUTPUT);
pinMode (P2B, OUTPUT);
pinMode (P2PWM, OUTPUT);
pinMode (P3A, OUTPUT);
pinMode (P3B, OUTPUT);
pinMode (P3PWM, OUTPUT);
pinMode (P4A, OUTPUT);
pinMode (P4B, OUTPUT);
pinMode (P4PWM, OUTPUT);
pinMode (Driver1STBY, OUTPUT);
pinMode (Driver1VCC, OUTPUT);
pinMode (Driver2STBY, OUTPUT);
pinMode (Driver2VCC, OUTPUT);
digitalWrite (Driver1STBY, HIGH);
digitalWrite (Driver1VCC, HIGH);
digitalWrite (Driver2STBY, HIGH);
digitalWrite (Driver2VCC, HIGH);
//set motor speeds to 0% duty
analogWrite(P1PWM, 0);
analogWrite(P2PWM, 0);
analogWrite(P3PWM, 0);
analogWrite(P4PWM, 0);
}//setup
void loop()
{
// DateTime nowTime = rtc.now();
//main loop runs very fast, peeking into each state machine function to see if any need attention
ODStateMachine(); // Pump1, GV1 & GV2
ByProductStateMachine(); // Pump3 & Pump4, GV3-GV7
}//loop
//ODP1 state names
#define ST_ODP1_INIT 0
#define ST_ODP1_INTERVAL_TIMING 1
#define ST_ODP1_RUNNING 2
//
void ODStateMachine( void )
{
int
ODVal;
static byte
stateODP1 = ST_ODP1_INIT;
static unsigned long
timeODP1_RunPeriod,
timeODP1_RunTimer,
timeODP1_ODTimer;
unsigned long
timeNow;
timeNow = millis();
switch ( stateODP1 )
{
case ST_ODP1_INIT:
//out of reset we start here and just initialize our start timer
timeODP1_RunTimer = timeNow;
//then move to the interval timing state
stateODP1 = ST_ODP1_INTERVAL_TIMING;
break;
case ST_ODP1_INTERVAL_TIMING:
//has the interval time elapsed?
if ( (timeNow - timeODP1_RunTimer) >= ODP1PUMP_INTERVAL )
{
//yes; start the pump, and...
digitalWrite(GV1, LOW); // OPEN
digitalWrite(GV2, LOW); // CLOSED
digitalWrite(P1A, LOW); // Motor Counter Clockwise
digitalWrite(P1B, HIGH);
analogWrite(P1PWM, 130); //set motor speed
//...initialize the optical density check timer, and...
timeODP1_ODTimer = timeNow;
//...save the motor start time to ensure the correct period is produced after the first pass, and...
timeODP1_RunPeriod = timeNow;
//...set state to running
stateODP1 = ST_ODP1_RUNNING;
Serial.println( "Pump1 running..." );
}//if
break;
case ST_ODP1_RUNNING:
//pump is running now; check for optical density check intervals
if ( (timeNow - timeODP1_ODTimer) >= ODP1OD_INTERVAL )
{
//check the density
ODVal = analogRead( ODAnalogIN );
Serial.print( "Optical density val: " );
Serial.println( ODVal );
//LCD Print values
lcd.setCursor(0, 1);
lcd.print("OD Val: ");
//delay(1);
lcd.setCursor(8, 1);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print( ODVal );
//if LOWER than the threshold, keep running and cycle GV1 CLOSED & GV2 OPEN
if ( ODVal >= OD_HIGH_THRESH ) //ODVal = returned voltage
{
//threshold reached. pump1 continues to run, fluid to hydrocyclone, pump2 on to replace lost volume
digitalWrite (P1A, LOW); // PUMP 1 ON
digitalWrite (P1B, HIGH);
analogWrite (P1PWM, 130);
digitalWrite (GV1, HIGH); // CLOSED
digitalWrite (GV2, HIGH); // OPEN
digitalWrite (P2A, LOW); // PUMP 2 ON
digitalWrite (P2B, HIGH);
analogWrite (P2PWM, 130); // PUMP 2 speed--will change to match flow of PUMP 1
Serial.println( "Pump2 running..." );
//repeat again
timeODP1_RunTimer = timeODP1_RunPeriod; //set our period based on the last time we started the motor
stateODP1 = ST_ODP1_INTERVAL_TIMING; //go back to interval timing
}//if
else
{
// PUMP 1 & 2 OFF, GV1 & GV2 CLOSED
digitalWrite (P1A, LOW); // PUMP 1 OFF
digitalWrite (P1B, LOW);
analogWrite (P1PWM, 0);
digitalWrite (P2A, LOW); // PUMP 2 OFF
digitalWrite (P2B, LOW);
analogWrite (P2PWM, 0);
digitalWrite (GV1, HIGH); // CLOSED
digitalWrite (GV2, LOW); // CLOSED
Serial.println( "Pump 1 & Pump 2 off..." );
//OD reading still showing too much density; set up for another check in a couple of minutes
timeODP1_ODTimer = timeNow;
}//else
}//if
break;
}//switch
}//ODStateMachine
(full code is attached due to being > 9000 characters)
sketch_sep04_g.ino (11.7 KB)