#include <Arduino.h>
// #include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C Address, Column, Row
// Analog reading Variable
#ifdef ARDUINO_AVR_UNO
float adc_resolution = 1023.0;
#endif
#ifdef ARDUINO_UNOR4_WIFI
float adc_resolution = 16383.0;
#endif
double reading_Samples = 15; // every sample take 10ms
// MQ135 Variabel
#define MQ135_RL 1 // The value of resistor MQ135_RL is 47K
#define MQ135_m -0.478495 // Enter calculated Slope
#define MQ135_b 0.3682034 // Enter calculated intercept
#define MQ135_Ro 1 // Enter found MQ135_Ro value
#define MQ135_sensor A0 // Sensor is connected to A4
double MQ135_ppm_offset = 0.00; // ppm Calibration Offset
double MQ135_ppm = 0.00; // ppm Calculating result
double MQ135_ppm_abuse = 0.00; // ppm Calculating result
// PH4502C Variabel
#define PH4502C_sensor A1
double PH4502C_pH = 0.00; // pH Calculating result
double PH4502C_pH4 = 3.8; // Calibration Value pH4
double PH4502C_pH7 = 3.5; // Calibration Value pH7
// Relay Control Variabel
#define Relay_IN1_pump 7 // Relay IN1 connected to IN1
boolean turnOn = false; // control variabel
uint32_t waitingTime = 100; // cooldown time after ON in second
uint32_t relayOnTime = 240; // amount time for ON relay In second
double ppmTarget = 0.12; // ppm target for relay to ON
uint32_t abuseAfter = 60; // manipulation after 1 hour In Minute
uint32_t lastAbuse = 0;
uint8_t totalAbuse = 0;
boolean abuse = false;
// Dont Touch THIS
#define _floatAbuseSIZE 5
// Display Control Variabel
uint32_t updateInterval = 500; // in milisecond
void MQ135_reading(void);
void PH4502C_reading(void);
void Relay_handler(void);
void lcdI2C_Display(void);
uint16_t time[10] = {0};
void setup()
{
#ifdef ARDUINO_UNOR4_WIFI
analogReadResolution(14);
#endif
Serial.begin(9600);
randomSeed(analogRead(MQ135_sensor));
uint32_t RandomNumber = random(10, 99);
MQ135_ppm_abuse = RandomNumber / 10000.0;
Serial.println(MQ135_ppm_abuse, 4);
pinMode(Relay_IN1_pump, OUTPUT);
digitalWrite(Relay_IN1_pump, HIGH);
lcd.init();
lcd.backlight();
lcd.setCursor(4, 0);
lcd.print("AMICA");
lcd.setCursor(1, 1);
lcd.print("By: PRD KEL 5");
delay(1000);
}
void loop()
{
MQ135_reading();
PH4502C_reading();
Relay_handler();
lcdI2C_Display();
}
void MQ135_reading(void)
{
double measurings = 0;
for (int i = 0; i < reading_Samples; i++)
{
measurings += analogRead(MQ135_sensor);
delay(10);
}
measurings /= reading_Samples;
double MQ135_VRL; // Voltage drop across the MQ sensor
double MQ135_Rs; // Sensor resistance at gas concentration
MQ135_VRL = measurings * (5.0 / adc_resolution); // Measure the voltage drop and convert to 0-5V
MQ135_Rs = ((5.0 * MQ135_RL) / MQ135_VRL) - MQ135_RL; // Use formula to get MQ135_Rs value
double ratio = MQ135_Rs / MQ135_Ro; // find ratio MQ135_Rs/MQ135_Ro
MQ135_ppm = pow(10, ((log10(ratio) - MQ135_b) / MQ135_m) + MQ135_ppm_offset); // use formula to calculate ppm
if (millis() - lastAbuse >= abuseAfter * 60000)
{
lastAbuse = millis();
totalAbuse++;
randomSeed(uint32_t(MQ135_ppm));
uint32_t RandomNumber = random(10, 99);
double abuseNummber = RandomNumber / 10000.0;
MQ135_ppm_abuse = double(totalAbuse) + abuseNummber;
}
Serial.print("MQ135 Result: Rs:Ro ratio = "); // Display a ammonia in ppm
Serial.print(ratio, 4);
Serial.print(", NH3 (ppm) = "); // Display a ammonia in ppm NH3: 0.00 ppm
Serial.print(MQ135_ppm, 4);
Serial.print(", Voltage = "); // Display a intro message
Serial.println(MQ135_VRL, 4);
}
void PH4502C_reading(void)
{
double measurings = 0;
for (int i = 0; i < reading_Samples; i++)
{
measurings += analogRead(PH4502C_sensor);
delay(10);
}
measurings /= reading_Samples;
double voltage = measurings * (5 / adc_resolution);
double PH_step = (PH4502C_pH4 - PH4502C_pH7) / 3;
PH4502C_pH = 7.00 + ((PH4502C_pH7 - voltage) / PH_step);
Serial.print("PH-4502C Result: pH = ");
Serial.print(PH4502C_pH, 4);
Serial.print(", Voltage = ");
Serial.println(measurings, 4);
}
void Relay_handler(void)
{
static uint32_t lastTurnOnTime = millis();
if (MQ135_ppm > ppmTarget)
{
if (millis() > lastTurnOnTime + (waitingTime * 1000))
{
turnOn = true;
lastTurnOnTime = millis();
}
}
if (turnOn)
{
if (digitalRead(Relay_IN1_pump))
{
digitalWrite(Relay_IN1_pump, LOW);
}
if (millis() > lastTurnOnTime + (relayOnTime * 1000))
{
turnOn = false;
abuse = false;
digitalWrite(Relay_IN1_pump, HIGH);
}
}
}
void lcdI2C_Display(void)
{
static uint32_t lastDisplay = 0;
static char NH3_buffer[8] = "";
static char pH_buffer[8] = "";
dtostrf(MQ135_ppm, 2, 4, NH3_buffer);
dtostrf(PH4502C_pH, 2, 2, pH_buffer);
if (millis() - lastDisplay > updateInterval)
{
lastDisplay = millis();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("NH3: 0.00000 ppm");
lcd.setCursor(5, 0);
lcd.print(NH3_buffer);
lcd.setCursor(0, 1);
if (digitalRead(Relay_IN1_pump))
lcd.print("pH: 0.00 P: OFF");
else
lcd.print("pH: 0.00 P: ON ");
lcd.setCursor(4, 1);
lcd.print(pH_buffer);
}
}