#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
int address = 105;
char data[64] = {0};
int y100;
int y200;
float y[19];
int commandEStop = 9110;
int commandStart = 1200;
int display_1 = 1201;
int display_2 = 1202;
int display_3 = 1203;
int display_4 = 1204;
int commandDisplay = 1250;
int commandStop = 1300;
int commandATO = 1401;
int commandAWC = 1402;
int commandBacklight = 1403;
int commandNoBacklight = 1404;
int packet1 = 201;
int packet2 = 202;
int packet3 = 203;
int packet4 = 204;
int packet5 = 205;
int packet6 = 206;
int comRelease = 207;
int a;
int b;
// RX 0
// TX 1
#define ena 4
#define manual_3 8
#define lowLevel 9
#define highLevel 10
#define txEnable 11
// #define xx 13
// #define xx 14
// #define xx 15
// #define xx 16
// #define xx 17
// #define xx 20
// #define xx 21
// dosing pump variables
float stepDegrees = 1.8;
float pumpRate = 0.317; // in mL/rev.
int seq;
int w;
// Exchange Pump Variables
#define pulse1 2
#define dir 5
#define manual_1 6
#define manual_2 7
int microstep_1 = 2;
int Exchange = 200; // in mL
float revsPerDose_1;
long pulPerDose_1;
int frequency_AWC = 3000;
int uSec_AWC;
int topOff = 10; // in mL
float revsPerDose_4;
long pulPerDose_4;
int frequency_ATO = 1000;
int uSec_ATO;
// Chemical Pump 1 Variables
#define pulse2 3
int microstep_2 = 32;
float doseAdditive_2; // in mL
float doseRate_2 = 0.0625; // in mL/L
float additiveConcentrate_2 = 100; // mL
float additiveWater_2 = 1900; // mL
float dilutionRate_2; // in ml/mL
float revsPerDose_2;
long pulPerDose_2;
int frequency_dose_2 = 1000;
int uSec_dose_2;
// Chemical Pump 2 Variables
#define pulse3 12
int microstep_3 = 32;
float doseAdditive_3; // in mL
float doseRate_3 = 0.0625; // in mL/L
float additiveConcentrate_3 = 100; // mL
float additiveWater_3 = 1900; // mL
float dilutionRate_3; // in ml/mL
float revsPerDose_3;
long pulPerDose_3;
int frequency_dose_3 = 1000;
int uSec_dose_3;
void setup() {
lcd.init();
lcd.backlight();
uSec_dose_2 = 500000 / frequency_dose_2;
uSec_dose_3 = 500000 / frequency_dose_3;
uSec_AWC = 500000 / frequency_AWC;
uSec_ATO = 500000 / frequency_ATO;
dilutionRate_2 = additiveConcentrate_2 / (additiveConcentrate_2 + additiveWater_2);
doseAdditive_2 = ((doseRate_2 / 1000) * Exchange) / dilutionRate_2;
revsPerDose_2 = doseAdditive_2 / pumpRate;
pulPerDose_2 = ((360 / stepDegrees) * microstep_2) * revsPerDose_2;
dilutionRate_3 = additiveConcentrate_3 / (additiveConcentrate_3 + additiveWater_3);
doseAdditive_3 = ((doseRate_3 / 1000) * Exchange) / dilutionRate_3;
revsPerDose_3 = doseAdditive_3 / pumpRate;
pulPerDose_3 = ((360 / stepDegrees) * microstep_3) * revsPerDose_3;
revsPerDose_1 = Exchange / pumpRate;
pulPerDose_1 = ((360 / stepDegrees) * microstep_1) * revsPerDose_1;
revsPerDose_4 = topOff / pumpRate;
pulPerDose_4 = ((360 / stepDegrees) * microstep_1) * revsPerDose_3;
pinMode(pulse1, OUTPUT);
pinMode(pulse2, OUTPUT);
pinMode(pulse3, OUTPUT);
pinMode(ena, OUTPUT);
pinMode(dir, OUTPUT);
pinMode(txEnable, OUTPUT);
pinMode(manual_1, INPUT_PULLUP);
pinMode(manual_2, INPUT_PULLUP);
pinMode(manual_3, INPUT_PULLUP);
pinMode(lowLevel, INPUT);
pinMode(highLevel, INPUT);
Serial.begin(9600);
Serial.println("...");
seq = 1;
w = 0;
a = 0;
b = 0;
lcd.setCursor(0,0);
lcd.print("ATO ");
lcd.print(frequency_ATO);
lcd.print("Hz 1/");
lcd.print(microstep_1);
lcd.setCursor(0,1);
lcd.print("AWC ");
lcd.print(frequency_AWC);
lcd.print("Hz 1/");
lcd.print(microstep_1);
lcd.setCursor(0,2);
lcd.print("Chem.1 ");
lcd.print(frequency_dose_2);
lcd.print("Hz 1/");
lcd.print(microstep_2);
lcd.setCursor(0,3);
lcd.print("Chem.2 ");
lcd.print(frequency_dose_3);
lcd.print("Hz 1/");
lcd.print(microstep_3);
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ATO ");
lcd.print(topOff);
lcd.print("mL");
lcd.setCursor(0,1);
lcd.print("AWC ");
lcd.print(Exchange);
lcd.print("mL");
lcd.setCursor(0,2);
lcd.print("Chem.1 ");
lcd.print(doseAdditive_2);
lcd.print("mL");
lcd.setCursor(0,3);
lcd.print("Chem.2 ");
lcd.print(doseAdditive_3);
lcd.print("mL");
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ATO ");
lcd.print("RO/DI");
lcd.setCursor(0,1);
lcd.print("AWC ");
lcd.print("RO/DI");
lcd.setCursor(0,2);
lcd.print("Chem.1 ");
lcd.print("Fresh Trace");
lcd.setCursor(0,3);
lcd.print("Chem.2 ");
lcd.print("Stability");
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Serial Begin");
lcd.setCursor(0,1);
lcd.print("9600 Baud");
delay(4000);
lcd.clear();
}
void loop() {
// controll loop
while(seq == 1) {
updateDisplay();
digitalWrite(ena, HIGH);
delay(20);
byte n = Serial.available();
if (n != 0) {
byte m = Serial.readBytesUntil('\n', data, 64);
data[m] = '\0'; //null-byte
y100 = atoi(strtok(data, ","));
y200 = atoi(strtok(NULL, ","));
if(y100 == address) {
if(y200 == packet1) {
y[1] = atof(strtok(NULL, ","));
y[2] = atof(strtok(NULL, ","));
y[3] = atof(strtok(NULL, ","));
}
}
}
if(y[1] == commandStart) {
if(y[2] == commandATO) {
// what to do if ATO is called
seq = 20;
w = 0;
break;
}
if(y[2] == commandAWC) {
// what to do if Auto water change is called
seq = 30;
break;
}
}
if(y[1] == commandDisplay) {
if(y[2] == display_1) {
a = 1;
}
else if(y[2] == display_2) {
a = 2;
}
else if(y[2] == display_3) {
a = 3;
}
else if(y[2] == display_4) {
a = 4;
}
if(y[3] == commandBacklight) {
lcd.backlight();
}
else if(y[3] == commandNoBacklight) {
lcd.noBacklight();
}
updateDisplay();
}
if(y[1] == commandStop) {
// what to do if stop command is called
}
if(digitalRead(lowLevel) == HIGH) {
seq = 20;
w = 0;
break;
}
if(digitalRead(manual_1) == LOW || digitalRead(manual_2) == LOW || digitalRead(manual_3) == LOW) {
seq = 40;
break;
}
}
// Auto Top Off
while(seq == 20) {
updateDisplay();
if((digitalRead(highLevel) == HIGH) || (digitalRead(lowLevel) == HIGH)) {
w++;
digitalWrite(ena, LOW);
digitalWrite(dir, HIGH);
for(long x = 0; x < pulPerDose_4; x++) {
digitalWrite(pulse1,HIGH);
delayMicroseconds(uSec_ATO);
digitalWrite(pulse1,LOW);
delayMicroseconds(uSec_ATO);
}
delay(2000);
}
else if(digitalRead(highLevel) == LOW) {
digitalWrite(ena, HIGH);
digitalWrite(dir, LOW);
digitalWrite(txEnable, HIGH);
Serial.print(address); // y100
Serial.print(",");
Serial.print(packet1); // y200
Serial.print(",");
Serial.print(commandStop); // y[1]
Serial.print(",");
Serial.println(commandATO); // y[2]
digitalWrite(txEnable, LOW);
delay(20);
y[1] = 0;
y[2] = 0;
seq = 1;
}
}
// Auto Water Change
while(seq == 30) {
updateDisplay();
delay(500);
digitalWrite(ena, LOW);
digitalWrite(dir, LOW);
for(long x = 0; x < pulPerDose_1; x++) {
digitalWrite(pulse1,HIGH);
delayMicroseconds(uSec_AWC);
digitalWrite(pulse1,LOW);
delayMicroseconds(uSec_AWC);
}
delay(1000);
digitalWrite(dir, HIGH);
for(long x = 0; x < pulPerDose_1; x++) {
digitalWrite(pulse1,HIGH);
delayMicroseconds(uSec_AWC);
digitalWrite(pulse1,LOW);
delayMicroseconds(uSec_AWC);
}
delay(1000);
for(long x = 0; x < pulPerDose_2; x++) {
digitalWrite(pulse2,HIGH);
delayMicroseconds(uSec_dose_2);
digitalWrite(pulse2,LOW);
delayMicroseconds(uSec_dose_2);
}
delay(1000);
for(long x = 0; x < pulPerDose_3; x++) {
digitalWrite(pulse3,HIGH);
delayMicroseconds(uSec_dose_3);
digitalWrite(pulse3,LOW);
delayMicroseconds(uSec_dose_3);
}
delay(100);
digitalWrite(ena, HIGH);
digitalWrite(txEnable, HIGH);
Serial.print(address); // y100
Serial.print(",");
Serial.print(packet1); // y200
Serial.print(",");
Serial.print(commandStop); // y[1]
Serial.print(",");
Serial.println(commandAWC); // y[2]
delay(20);
y[1] = 0;
y[2] = 0;
seq = 1;
}
// Manual opperation
while( seq == 40) {
if(digitalRead(manual_1) == LOW || digitalRead(manual_2) == LOW || digitalRead(manual_3) == LOW) {
seq = 40;
digitalWrite(ena, LOW);
}
else {
seq = 1;
break;
}
while(digitalRead(manual_1) == LOW) {
delay(10);
updateDisplay();
digitalWrite(dir, HIGH);
for(long x = 0; x < 100; x++) {
digitalWrite(pulse1,HIGH);
delayMicroseconds(uSec_ATO);
digitalWrite(pulse1,LOW);
delayMicroseconds(uSec_ATO);
}
if(digitalRead(manual_1) == HIGH) {
digitalWrite(ena, HIGH);
}
}
while(digitalRead(manual_2) == LOW) {
delay(10);
updateDisplay();
digitalWrite(dir, LOW);
for(long x = 0; x < 100; x++) {
digitalWrite(pulse1,HIGH);
delayMicroseconds(uSec_ATO);
digitalWrite(pulse1,LOW);
delayMicroseconds(uSec_ATO);
}
if(digitalRead(manual_2) == HIGH) {
digitalWrite(ena, HIGH);
}
}
while(digitalRead(manual_3) == LOW) {
delay(10);
updateDisplay();
for(long x = 0; x < 20; x++) {
digitalWrite(pulse2, HIGH);
digitalWrite(pulse3, HIGH);
delayMicroseconds(uSec_dose_2);
digitalWrite(pulse2, LOW);
digitalWrite(pulse3, LOW);
delayMicroseconds(uSec_dose_2);
}
if(digitalRead(manual_3) == HIGH) {
digitalWrite(ena, HIGH);
}
}
}
}
void updateDisplay() {
int volumeATO = w * topOff;
if(seq == 1 || seq == 2) {
lcd.setCursor(0,0);
lcd.print("Idle ");
}
if(seq == 20) {
lcd.setCursor(0,0);
lcd.print("Top Off ");
lcd.setCursor(0,1);
lcd.print(volumeATO);
lcd.print("mL");
}
if(seq == 30) {
lcd.setCursor(0,0);
lcd.print("Water Change");
}
if(seq == 40) {
lcd.setCursor(0,0);
if(digitalRead(manual_1) == LOW) {
lcd.print("Manual Fill ");
}
else if(digitalRead(manual_2) == LOW) {
lcd.print("Manual Drain ");
}
else if(digitalRead(manual_3) == LOW) {
lcd.print("Manual Purge ");
}
else {
lcd.print(" ");
}
}
if((a == 1) && (b == 0)) {
lcd.clear();
lcd.setCursor(0,1);
lcd.print("ATO: ");
lcd.print(topOff);
lcd.print(" mL/cycle");
lcd.setCursor(0,2);
lcd.print(frequency_ATO);
lcd.print("Hz");
b = 1;
}
else if((a == 2) && (b == 1)) {
lcd.clear();
lcd.setCursor(0,1);
lcd.print("AWC: ");
lcd.print(Exchange);
lcd.print("mL");
lcd.setCursor(0,2);
lcd.print(frequency_AWC);
lcd.print("Hz");
b = 2;
}
else if((a == 3) && (b == 2)) {
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Fresh Trace ");
lcd.print(doseAdditive_2);
lcd.print("mL");
lcd.setCursor(0,2);
lcd.print((doseRate_2 / dilutionRate_2), 4);
lcd.print(" mL/L");
b = 3;
}
else if((a == 4) && (b == 3)) {
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Stability ");
lcd.print(doseAdditive_3);
lcd.print("mL");
lcd.setCursor(0,2);
lcd.print((doseRate_3 / dilutionRate_3), 4);
lcd.print(" mL/L");
b = 0;
}
}