Dear All,
I am having a trouble with Arduino where I have assembled a project, at various stages it worked, but at the moment after a while loop breaks, OLED screen freezes and loop no longer works.
Project in a nutshell:
There are 2 sensors: MQ135 for air quality reading & Moisture sensor
There are 2 relays connected to Arduino
There is also an RTC & OLED screen both connected though I2C
What code does in a loop:
Take air & moisture readings and display on screen,
Take RTC reading, and depending on values switch relays on or off depending on predefined time parameters.
Because code works for a while, and does exactly what intended I have pinned the problem to one of the following problems:
-
When I2C devices disconnect while Arduino is running, loop breaks. Maybe there is a loose connection, although I have checked it over and over again.
-
Problem with the code (this is my weakness, as it is my first Arduino project). Tried to check variables, but not sure what can cause the problem
-
Incorrect circuit - missing resistors?
Any help and advice is highly appreciated. Code is below and circuit is attached.
Please excuse my lack of proficiency in the way code is written and circuit is built, this is my first project.
Many thanks!
//-----below is definition of relay pins
int rly_1 = 12;
int rly_3 = 11;
//-----variable for moisture
float moist_v;
float min_mst = 100;
float max_mst = 0;
//-----below are LCD library setups-----
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C
// Define proper RST_PIN if required.
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
//-----below are RTC library setups-----
#include <DS3231.h>
// Init the DS3231 using the hardware interface
DS3231 rtc(SDA, SCL);
Time t;
//-----CO2 sensor setup------
#define anInput A1 //analog feed from MQ135
#define co2Zero 0
float co2_min = 5000;
float co2_max = 0;
void setup()
{
//-----below is setup for RTC------
Serial.begin(9600);
// Uncomment the next line if you are using an Arduino Leonardo
//while (!Serial) {}
// Initialize the rtc object
rtc.begin();
//The following lines can be uncommented to set the date and time
// rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY
// rtc.setTime(17, 33, 40); // Set the time to 12:00:00 (24hr format)
// rtc.setDate(4, 11, 2018); // Set the date to January 1st, 2014
//-----below is setup for LCD-----
#if RST_PIN >= 0
oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else // RST_PIN >= 0
oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif // RST_PIN >= 0
oled.setFont(Adafruit5x7);
uint32_t m = micros();
oled.clear();
//-----below is setup pf relays-----
pinMode(rly_1, OUTPUT);
digitalWrite(rly_1, HIGH);
pinMode(rly_3, OUTPUT);
digitalWrite(rly_3, HIGH);
}
void loop()
{
//-----int for co2-----
int co2now[10];
int co2raw = 0;
int co2comp = 0;
int co2ppm = 0;
int zzz = 0;
int grafX = 0;
//-----below are variables for co2 measurement
for (int x = 0;x<10;x++){ //samplpe co2 10x over 1 seconds
co2now[x]=analogRead(A1);
delay(100);
}
oled.clear(); // clear display after 1 sec delay above
for (int x = 0;x<10;x++){ //add samples together
zzz=zzz + co2now[x];
}
co2raw = zzz/10; //divide samples by 10
co2comp = co2raw - co2Zero; //get compensated value
co2ppm = (map(co2comp,0,1023,400,5000) - 100); //map value for atmospheric levels
if(co2ppm < co2_min) {
co2_min = co2ppm;
}
if(co2ppm > co2_max) {
co2_max = co2ppm;
}
//-----below is code for moisture sensor-----
int mst_sens = analogRead(A0);
moist_v = (((1023 - mst_sens)*100L / 1023 ));
if(moist_v > max_mst) {
max_mst = moist_v;
}
if(moist_v < min_mst) {
min_mst = moist_v;
}
//-----below are variables for relays-----
int cycle_1 = (12 * 60); //time in minutes
int cycle_3 = (1 * 60); //time in minutes
int on_1 = 35; //time in seconds to be on -> water
int on_3 = 20; //time in seconds to be on
int start_r1_h = 9; //first time start of relay 1 in hours
int start_r1_m = 0; //first time start of relay 1 in minutes
int start_r3_h = 9; //first time start of relay 3 in hours
int start_r3_m = 0; //first time start of relay 3 in minutes
// Get data from the DS3231
t = rtc.getTime();
int rtc_in_min = t.hour * 60 + t.min;
int start_r1 = ((start_r1_h * 60) + start_r1_m);
int start_r3 = ((start_r3_h * 60) + start_r3_m);
int disp_rly1 = cycle_1 - (mod((rtc_in_min - start_r1), cycle_1)); //to display relays time left to screen
int disp_rly3 = cycle_3 - (mod((rtc_in_min - start_r3), cycle_3)); //to display relays time left to screen
//-----print time-----
oled.print("Time: ");
char s1[2] = "";
char s2[10] = "";
dtostrf(t.hour, 2, 0, s1);
strcat(s2, s1);
strcat(s2, ":");
dtostrf(t.min, 2, 0, s1);
strcat(s2, s1);
strcat(s2, ":");
dtostrf(t.sec, 2, 0, s1);
strcat(s2, s1);
oled.print(s2);
//-----turn relay 1 on/off-----
if(mod((rtc_in_min - start_r1), cycle_1) < 1) { //below this is screen refresh time
if(t.sec <= on_1) {
digitalWrite(rly_1, LOW);
//-----below if text for display-----
char on_time[2] = "";
oled.println();
oled.print("R1 eng'd for ");
int t_left = on_1 - t.sec;
dtostrf(t_left, 2, 0, on_time);
oled.print(on_time);
oled.print(" sec");
}
else{
digitalWrite(rly_1, HIGH);
//-----below if text for display-----
char s_rly1[3] = "";
char relay_num[5] = "R1 in";
oled.println();
oled.print(relay_num);
dtostrf(disp_rly1, 5, 0, s_rly1);
oled.print(s_rly1);
oled.print(" min. (");
oled.print(on_1);
oled.print("s)");
}
}
else {
digitalWrite(rly_1, HIGH);
//-----below if text for display-----
char s_rly1[3] = "";
char relay_num[5] = "R1 in";
oled.println();
oled.print(relay_num);
dtostrf(disp_rly1, 5, 0, s_rly1);
oled.print(s_rly1);
oled.print(" min. (");
oled.print(on_1);
oled.print("s)");
}
//-----turn relay 3 on/off + display relevant text-----
if(mod((rtc_in_min - start_r3), cycle_3) < 1) { //below this is screen refresh time
if(t.sec <= on_3) {
digitalWrite(rly_3, LOW);
//-----below if text for display-----
char on_time[2] = "";
oled.println();
oled.print("R3 eng'd for ");
int t_left = on_3 - t.sec;
dtostrf(t_left, 2, 0, on_time);
oled.print(on_time);
oled.print(" sec");
}
else{
digitalWrite(rly_3, HIGH);
//-----below if text for display-----
char s_rly3[3] = "";
char relay_num[5] = "R3 in";
oled.println();
oled.print(relay_num);
dtostrf(disp_rly3, 5, 0, s_rly3);
oled.print(s_rly3);
oled.print(" min. (");
oled.print(on_3);
oled.print("s)");
}
}
else {
digitalWrite(rly_3, HIGH);
//-----below if text for display-----
char s_rly3[3] = "";
char relay_num[5] = "R3 in";
oled.println();
oled.print(relay_num);
dtostrf(disp_rly3, 5, 0, s_rly3);
oled.print(s_rly3);
oled.print(" min. (");
oled.print(on_3);
oled.print("s)");
}
//-----print CO2 + min/max values & moisture-----
char str_co2_now[4] = "";
char str_moist[4] = "";
oled.println();
oled.println();
oled.print(" CO2 ");
oled.print("% wet");
dtostrf(co2ppm, 4, 0, str_co2_now);
oled.println();
oled.print("now:");
oled.print(str_co2_now);
oled.print(" now:");
dtostrf(moist_v, 4, 0, str_moist);
oled.print(str_moist);
char str_co2_min[4] = "";
char str_mst_min[4] = "";
oled.println();
oled.print("min:");
dtostrf(co2_min, 4, 0, str_co2_min);
oled.print(str_co2_min);
oled.print(" min:");
dtostrf(min_mst, 4, 0, str_mst_min);
oled.print(str_mst_min);
char str_co2_max[4] = "";
char str_mst_max[4] = "";
oled.println();
oled.print("max:");
dtostrf(co2_max, 4, 0, str_co2_max);
oled.print(str_co2_max);
oled.print(" max:");
dtostrf(max_mst, 4, 0, str_mst_max);
oled.print(str_mst_max);
}
int mod(int k, int n) {
return ((k %= n) < 0) ? k+n : k;
}