Good morning everyone,
I created with a Mega 2560 a small circuit in order to manage a small bioreactor for gas powered at 12 V in direct current (I use a power supply from a PC 220V-12V at 12A) which manages: two Burkert valves (12V - 0.4 A ) and a small peristaltic pump (12V - 80mA) with a relay bank; an Atlas Scientific pH sensor managed by an EZO pH circuit Version 5.0. A gas pump (12V - 1A) via PWM using a FQP30N06L mosfet and modifying one of the three clocks to use a higher frequency (+ 12V fan to keep the mosfet cool).
the sketch is divided into 4-hour cycles so that: activates the gas pump (2.5 sec ON and 7.5 sec OFF) by default, every 5 minutes takes a pH reading, every 4 hours starts the loading / unloading bioreactor with in order: valve opening, peristaltic pump activation, second valve activation (one at a time not overlapping). After which the cycle restarts.
In order to trace the various phases and to take the output data of the pH meter, I print from Serial0, separated by ";" , the information on the time and the type of operation done (I don't use an external RTC but the time.h library).
I then communicate with the atlas scientific EZO via UART on Serial2.
PROBLEM
When I tried the sketch without connecting anything (only the pH meter) everything works, but when I connect pumps and valves, even if the sketch works perfectly with the right times, the Serial monitor or any COM manager (use terminal. exe) does not go; or better, it records the first operation or at most the first 4-5 and then stops, while for the rest everything works (timer, activation of pumps and valves with the right times).
I have read several QA in the forum but I have not come to the head, I tried to use different COMs and I also tried to power the mega with the power supply as well as with the USB, as I thought it could not manage everything. .. but it does not change history.
A doubt that arises to me is that there is interference given the proximity of motors to DC, and somehow it interferes with the serial, but I don't understand why the rest continues to work ...
I leave you the links to components similar to those I have in the lab and a pdf with the electrical connection diagrams at this google drive link.
Below instead I leave the sketch.
Sketch
/***MADE FOR ARDUINO ATmega2560***/
#include <Time.h> //used to track time (<50gg)
#include <TimeLib.h> //used to track time (<50gg)
//#include <SoftwareSerial.h> //we have to include the SoftwareSerial library, or else we can't comunicate with the sensor
//#define rx 2 //define what pin rx is going to be.
//#define tx 3 //define what pin Tx is going to be.
/*
This code is divided into different functions, each of them make a measure/process of the bioreactor.
The loop is 4 hours long and is repeted 6 times for day.
From the PARAMETER BOX in the head space of the script there is the possiblity to change the most important parameters.
This script allows pH measures which are recorded also providing date and time. The data otained can be imported in excel and can be separated by ";".
Further more, if a pH measure is made after a liquid input (possible pH modification) it will print this information in the report to allow a better understand of the data.
IMPORTANT!
-Before to start the operation pH prob has to be calibrated. This script is made for pH EZO chip V 1.2
-The total duration in milliseconds of the FWD cycle (Feeding of gas and liquid, and WithDrow) must be determine to corectly
set all the variables (follow the FWD_time comments instruction below in the PARAMETER BOX).
-The liquid temperature has to be specify to allow correct pH measure, edit it in the PARAMETER BOX
-All the variables in the information box has to be checked
-Use a third serial monitor software to be able to record the data (eg Termilan.exe)
PIN CONNECTION SUMMARY:
pin 2: connected to the tx of the EZP chip
pin 3: connected to the rx of the EZP chip
pin 6: gas pump for the recirculation to mosphet
pin 9: hydrogen valve for feeding rele
pin 10: liquid feeding peristaltic pump rele
pin 11: liquid wihdrow valve rele
*/
/*________________________PARAMETER BOX START_________________________*/
int se = 0, mi = 00, ho = 00, da = 14, mo = 3, ye = 22; //set time in which the automatic reactor starts: se=seconds, mi=minute, ho=hour, da=day, mo=month, ye=year (only last 2 numbers, eg 2022=22) ::ATTENTION:: max time garantee is 49.7 days!
char pH_temperature[] = "36\r"; //::CHECK CODE::this parameter can be edit before to start the code. Insert the Temperature of the liquid to have more precise readings, do not dele \r!
const unsigned long gas_pump_ON_time = 2500; //time of gas pump on during normal cycle
const unsigned long gas_pump_OFF_time = 7500; //time of gas pump off during normal cycle, can be adjust based on the pH and FWD cycle duration
int PWM_pump = 235; //PWM which regulate the ml/min of the gas pump
const unsigned long CYCLE_HOUR = 4 * 60 * 60 * 1000L; //duration of a single cycle in milliseconds, here is in total 4 hours (6 times x day repeted)::ATTENTION:: KEEP L LETTER AFTER THE NUMBERS
const unsigned long FWD_time = 264000; //duration of all the feeding and withdrow sequence in one cycle in milliseconds, to determine it follow the instruction in the MAIN LOOP BOX
const unsigned long pH_reading_time = 300000; //MILLISECONDS time difference between each pH readings, 300000 = 5 min in millisecond
const unsigned long H2_feeding_time = 800; //duration of the hydrogen feeding (valve open) in milliseconds
const unsigned long liquid_feeding_time = 3509; //duration of the liquid feeding (peristaltic pump on) in milliseconds
const unsigned long liquid_WD_time = 180000; //duration of the liquid withdrow in milliseconds
/*_________________________PARAMETER BOX END___________________________*/
//PUMPS PINS
const int gas_pump = 8; //6 for position1, 7 for position 2, 8 for position 3
const int H2_valve = 9;
const int liquid_feed_valve = 10;
const int liquid_WD_valve = 11;
//TIME VARIABLES NOT TO BE EDIT
unsigned long t_pH = 0, dt_pH = 0, t_FWD = 0, dt_FWD = 0 ;
const unsigned long normal_time = CYCLE_HOUR - FWD_time ; //4h in milliseconds - FWD_time
//OTHER VARIABLES
const int enable_pH = 30;
char read_onepoint[] = "R,1\r";
boolean start_feeding = false;
//SENSOR VARIABLES
//SoftwareSerial Serial2(rx, tx); //define how the soft serial port is going to work.
char pH_data[30];
char computerdata[20];
byte received_from_computer = 0;
byte received_from_sensor = 0;
byte arduino_only = 0;
byte startup = 0;
float EC = 0;
//Declaration of the functions
void gas_rec(); //main cycle
void read_pH(); //main cycle
void H2_feed(); //FWD cycle
void liquid_feed(); //FWD cycle
void liquid_WD(); //FWD cycle
/*Declaration of the Serial monitor inputs*/
/*void serialEvent() {
received_from_computer = Serial.readBytesUntil(13, computerdata, 20);
computerdata[received_from_computer] = 0;
Serial2.print(computerdata);
Serial2.print('\r');
}*/
/*Declaration of the Setup*/
void setup() {
TCCR4B = TCCR4B & 0b11111000 | 0x01; //set the pins 6, 7, 8 at higher PWM speed
setTime(ho, mi, se, da, mo, ye);
pinMode(enable_pH, OUTPUT);
digitalWrite(enable_pH, LOW);
Serial.begin(9600);
Serial2.begin(9600);
Serial2.print("C,0\r");
Serial2.print("RESPONSE,0\r");
Serial2.print(pH_temperature);
pinMode(gas_pump, OUTPUT);
pinMode(H2_valve, OUTPUT);
pinMode(liquid_feed_valve, OUTPUT);
pinMode(liquid_WD_valve, OUTPUT);
digitalWrite(gas_pump, LOW);
digitalWrite(H2_valve, HIGH);
digitalWrite(liquid_feed_valve, HIGH);
digitalWrite(liquid_WD_valve, HIGH);
t_FWD = millis();
t_pH = millis();
}
/*____________________________________________MAIN LOOP BOX starts____________________________*/
/*To make easier the FWD determination set the dime to 00:00:00*/
void loop() {
if (start_feeding == false) { //made only after first start
H2_feed();
start_feeding = true;
}
dt_FWD = millis() - t_FWD;
//Serial.print("Feeding start in: "); //uncomment to determine FWD_time
//digitalClockDisplay(); //uncomment to determine FWD_time
//Serial.println(""); //uncomment to determine FWD_time
if (dt_FWD > normal_time) { //comment to determine FWD_time
H2_feed();
delay(5000);
liquid_feed();
unsigned long dt_HyBa = 0; //wait one minute to allow liquid to be static
unsigned long HyBa_start = millis();
while (dt_HyBa < 60000) {
dt_HyBa = millis() - HyBa_start;
}
liquid_WD();
delay(5000);
gas_rec();
delay(500);
read_pH();
t_pH = millis();
t_FWD = millis();
} //comment to determine FWD_time
//Serial.print("Feeding end in: "); //uncomment to determine FWD_time
//digitalClockDisplay(); //uncomment to determine FWD_time
//Serial.println(""); //uncomment to determine FWD_time
dt_pH = millis() - t_pH;
if (dt_pH > pH_reading_time) { //to determine FWD_time comment all the following lines (<-- included these)
read_pH();
t_pH = millis();
}
gas_rec();
/*:::TEST AREA:::*/
// Serial.println("ciao");
// gas_rec();
// delay(1000);
// H2_feed();
// delay(1000);
// liquid_feed();
// delay(1000);
// liquid_WD();
// delay(1000);
// read_pH();
}
/*____________________________________________MAIN LOOP BOX ends____________________*/
/*Declaration of the funtions*/
void gas_rec() { //cycle which regulates the normal gas recyrculation //ADD LED OPENING
unsigned long dt_gas_pump_on = 0;
unsigned long dt_gas_pump_off = 0;
unsigned long t_gas_pump = millis();
while (dt_gas_pump_on <= gas_pump_ON_time) {
analogWrite(gas_pump, PWM_pump);
dt_gas_pump_on = millis() - t_gas_pump;
}
digitalWrite(gas_pump, LOW);
t_gas_pump = millis();
while (dt_gas_pump_off <= gas_pump_OFF_time) { //POSSIBLE TO INSERT THE INTERUPTION HERE FOR THE PWM REGULATION
dt_gas_pump_off = millis() - t_gas_pump;
}
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::MAKE SOME INITIAL pH READING TO ALLOW STABILIZATION:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::since pH is read while there is nothing else opened in terms of electrical things maybe is not influenced!::::::::::::::::::::::::::::::::::::::*/
void read_pH() { //cycle which comand the pH reading
Serial2.flush();
/*int n = 0; //possible code to remove first ten readings
while (n < 10) {
Serial2.print("R,1\r");
Serial2.flush(); //check if serial.flush() work to clean the serial port
n++;
}*/
Serial2.print(read_onepoint);
if (Serial2.available()) { // if (Serial2.available()>0) {
received_from_sensor = Serial2.readBytesUntil('\r', pH_data, 30);
pH_data[received_from_sensor] = 0;
Serial.print("pH reading;");
digitalClockDisplay();
Serial.print(pH_data);
if (dt_FWD > normal_time) {
Serial.println("; made after fresh liquid addition");
}
else {
Serial.println("");
}
}
}
void H2_feed() { //cycle which comand the hydrogen valve opening
/*Serial.print("Hydrogen feeding START;");
digitalClockDisplay();
Serial.println("");
delay(1000);*/
Serial.println("Hydrogen feed");
unsigned long dt_H2_feed = 0;
unsigned long t_H2_feed = millis();
while (dt_H2_feed <= H2_feeding_time) {
digitalWrite(H2_valve, LOW);
dt_H2_feed = millis() - t_H2_feed;
}
digitalWrite(H2_valve, HIGH);
/*delay(1000);
Serial.print("Hydrogen feeding END;");
digitalClockDisplay();
Serial.println("");*/
}
void liquid_feed() {
/*Serial.print("Liquid feeding START;");
digitalClockDisplay();
Serial.println("");//cycle which comand the liquid feeding peristaltic pump
delay(1000);*/
unsigned long dt_liquid_feed = 0;
unsigned long t_liquid_feed = millis();
while (dt_liquid_feed <= liquid_feeding_time) {
digitalWrite(liquid_feed_valve, LOW);
dt_liquid_feed = millis() - t_liquid_feed;
}
digitalWrite(liquid_feed_valve, HIGH);
/*delay(1000);
Serial.print("Liquid feeding END;");
digitalClockDisplay();
Serial.println("");*/
}
void liquid_WD() {
/* Serial.print("Liquid withdrow START;");
digitalClockDisplay();
Serial.println("");
delay(1000);*/
unsigned long dt_liquid_WD = 0;
unsigned long t_liquid_WD = millis();
while (dt_liquid_WD <= liquid_WD_time) {
digitalWrite(liquid_WD_valve, LOW);
dt_liquid_WD = millis() - t_liquid_WD;
}
digitalWrite(liquid_WD_valve, HIGH);
/*delay(1000);
Serial.print("Liquid withdrow END;");
digitalClockDisplay();
Serial.println("");*/
}
void digitalClockDisplay() { //time function
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(";");
Serial.print(day());
Serial.print("/");
Serial.print(month());
Serial.print("/");
Serial.print(year());
Serial.print(";");
}
void printDigits(int digits) { //time function
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
The code is made like that since a college has to use it and is not familiar at all with programming.
Any suggestion will be appreciated