i have an arduino, an RTC (time), a DHT (humidity and temp sensor), oled screen (128x32 ; microoled 1306) and 4 relais ;
all seems to work perfectly for hours, but sometime (1 or 2 per day..) everything stop working ;
- screen i frozen on last info displayed
- relais stay stuck in a random position (somtimes turning everythings ON (on=LOW with thoses relay.))
i obviously made a mistake, but don t know what... what can cause a loop to stay stuck randomly ??? plz save me :)
EDIT => A REWORK OF THAT TERRIBLE CODE AVAILABLE IN ANSWER, THE PROBLEM IS STILL THERE
// GND GND
// A4 SCL
// A5 SDA
// VCC 5V
// for DHT11,
// VCC: 5V or 3V
// GND: GND
// DATA: A7+
// YL-39 + YL-69 humidity sensor
const byte humidity_sensor_pin = A1;
const byte humidity_sensor_vcc = 6;
// ecran SDA / SDL
// RELAIS Pin D8
// RELAIS2 Pin D9
// RELAIS3 Pin D10
// RELAIS4 Pin D11
// Relais reboot D5 ?
#include <SimpleDHT.h>
#include <Wire.h>
#include "U8glib.h"
#include "RTClib.h"
const int pinDHT11 = 7;
SimpleDHT11 dht11;
RTC_DS1307 RTC;
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);
const int relay = 8; // Light
const int relay2 = 9; // Wind
const int relay3 = 10; // Heat
const int relay4 = 11; // Humidity
// Time Variable
DateTime InitTime ;
int InitHour;
const int startHour = 20;
const int startMin = 01;
const int startTime = startHour *100 + startMin;
const int endHour = 8;
const int endMin = 01;
const int endTime= endHour *100 + endMin;
const int maxWind = 5;
const int startWind = 05;
int lastWind ;
const int dayMinTemp = 18;
const int dayMaxTemp = 20;
const int nightMinTemp = 16;
const int nightMaxTemp = 19;
const int minhum = 50;
void drawInit(DateTime InitD){
String text = String(InitD.day());
text += " ";
text += String(InitD.month());
String text2 = String(InitD.hour());
text2 += ":";
text2 += String(InitD.minute());
text2 += ":";
text2 += String(InitD.second());
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0,16);
u8g.print(text);
u8g.setPrintPos(0,32);
u8g.print(text2);
}
void drawTemp(float temp, int hum, int nowT){
String text = "Temp: ";
text += temp;
text += "*C";
String text2 = "Hum: ";
text2 += hum;
text2 += "% :";
text2 += nowT;
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0,16);
u8g.print(text);
u8g.setPrintPos(0,32);
u8g.print(text2);
}
void draw(String staT, String endT, String nowT){
String iotxt;
if (digitalRead(relay) == LOW){iotxt="On";}else{iotxt="Off";}
String text = "S: ";
text += staT;
text += " E: ";
text += endT;
String text2 = "H: ";
text2 += nowT;
// text2 += " L: ";
// text2 += iotxt;
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0,16);
u8g.print(text);
u8g.setPrintPos(0,32);
u8g.print(text2);
}
void drawerror(String error){
String text = "err mod: ";
text += error;
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0,16);
u8g.print(text);
}
void draw2(int nowTime){
String iotxt;
String hottxt;
String lumtxt;
String humtxt;
if (digitalRead(relay) == LOW){lumtxt="On";}else{lumtxt="Off";}
if (digitalRead(relay2) == LOW){iotxt="On";}else{iotxt="Off";}
if (digitalRead(relay3) == LOW){hottxt="On";}else{hottxt="Off";}
if (digitalRead(relay4) == LOW){humtxt="On";}else{humtxt="Off";}
String text = "Hot: ";
text += hottxt;
text += " Lum: ";
text += lumtxt;
String text2 = "Hum: ";
text2 += humtxt;
text2 += " Win: ";
text2 += iotxt;
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0,16);
u8g.print(text);
u8g.setPrintPos(0,32);
u8g.print(text2);
}
void setup () {
pinMode(relay, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
digitalWrite(relay, HIGH);
digitalWrite(relay2,HIGH);
digitalWrite(relay3,HIGH);
digitalWrite(relay4,HIGH);
Serial.begin(9600);
Wire.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
RTC.begin();
DateTime now = RTC.now();
InitTime = now ;
InitHour = now.hour()*100 + now.minute();
}
void loop () {
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read(pinDHT11, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
// Serial.print("Read DHT11 failed, err="); Serial.println(err);delay(1000);
u8g.firstPage();
do {
drawerror("DHT");
} while( u8g.nextPage() );
delay(3000);
return;
}else{
// Serial.print("Sample OK: ");
// Serial.print((int)temperature); Serial.print(" *, ");
// Serial.print((int)humidity); Serial.println(" H");
// Relay Chaleur
if (digitalRead(relay)==LOW){
if((int)temperature < dayMinTemp){
digitalWrite(relay3,LOW);
// Serial.print("HEAT : On");
}else{digitalWrite(relay3,HIGH);
// Serial.print("HEAT : Off");
}
}else{
if((int)temperature < nightMinTemp){
digitalWrite(relay3,LOW);
// Serial.print("HEAT : On");
}else{
digitalWrite(relay3,HIGH);
// Serial.print("HEAT : Off");
}
}
// fin relay chaleur
if (! RTC.isrunning()) {
drawerror("RTC");}else{
DateTime now = RTC.now();
int nowTime= now.hour()*100 + now.minute();
// § WIND
if(now.minute() >= startWind && now.minute() <= startWind+maxWind ){
digitalWrite(relay2,LOW);
// Serial.println("Wind ON");
lastWind = nowTime;
}else if(now.minute()>startWind+5 || now.minute()<startWind){
digitalWrite(relay2,HIGH);
// Serial.println("Wind OFF");
}
// § END WIND
// START humidity
if(int(humidity)<minhum){
digitalWrite(relay4,LOW);
}else{ digitalWrite(relay4,HIGH);
}
//
// § LIGHT START
if(startTime<endTime){
if(startTime <= nowTime && endTime >= nowTime){
digitalWrite(relay,LOW);
// Serial.println("Light ON");
}else{
digitalWrite(relay,HIGH);
// Serial.println("Light OFF");
}}else{
if(endTime <= nowTime && startTime >= nowTime){
digitalWrite(relay,HIGH);
// Serial.println("Light OFF");
}else{
digitalWrite(relay,LOW);
// Serial.println("Light ON");
}}
// if(nowTime >= startTime && nowTime <= 2359){
// digitalWrite(relay, LOW);
// Serial.println("Light ON");
// }
// else if(nowTime < endTime ){
// digitalWrite(relay, LOW);
// Serial.println("LIGHT ON");}
// else if(nowTime >= endTime && nowTime < startTime){
// digitalWrite(relay, HIGH);
// Serial.println("Light OFF");}
// }
// § LIGHT END
u8g.firstPage();
do {
draw(String(startTime),String(endTime),String(nowTime));
} while( u8g.nextPage() );
delay(3000);
u8g.firstPage();
do {
drawInit(InitTime);
} while( u8g.nextPage() );
delay(3000);
u8g.firstPage();
do {
draw2(nowTime);
} while( u8g.nextPage() );
delay(3000);
u8g.firstPage();
do {
drawTemp(float(temperature), int(humidity),int(NowT));
} while( u8g.nextPage() );
delay(3000);
}}}
-
you may want to fix your identation, that will help clarify the logic flow of each functionratchet freak– ratchet freak2018年02月16日 15:52:51 +00:00Commented Feb 16, 2018 at 15:52
-
I present you the "?:" operator: lumtxt = digitalRead(relay) ? "On" : "Off";user31481– user314812018年02月16日 15:58:37 +00:00Commented Feb 16, 2018 at 15:58
-
3At a quick guess I'd say your heap is swiss cheese. Ditch String.Majenko– Majenko2018年02月16日 16:09:29 +00:00Commented Feb 16, 2018 at 16:09
-
i will rework that to made it more digest xD sry, let me few min :)Evans Padnom– Evans Padnom2018年02月16日 16:10:40 +00:00Commented Feb 16, 2018 at 16:10
-
1your code is horribly formatted ... it is a mess ... it is very difficult to determine how all the parts interactjsotola– jsotola2018年02月16日 20:39:24 +00:00Commented Feb 16, 2018 at 20:39
2 Answers 2
While it makes logical sense to use the String
type to hold strings of text, it's really a very poor choice for a low-RAM device like an Arduino.
You are using the string concatenation operator (+
) a lot. The String
type handles this by grabbing a new block of RAM that is equal to the sum of the 2 strings you are concatenating, puts the new string in that RAM, and marks the previous block of RAM that held one of the strings as empty and available for re-use.
The problem is that when you keep concatenating bits to the same string variable, it has to keep finding longer and longer continuous blocks of RAM into which to put the new string. All the previous blocks that are "available" for use, are also too short, as they are all the length of previous strings prior to your new, longer string requirement.
As @Majenko noted, this means your RAM is "swiss cheese" -- full of holes that can't be used by the program for more strings.
One solution is to avoid the String
variable type and instead use what are called C-Style Strings - arrays of char
type. It's a whole new, old world of doing things, and can be more challenging than the String
type, but it has a distinct advantage of not shredding the device's RAM.
The C-style string world is ruled by monsters like strnlen()
and strncpy()
, and making sure you have remembered to allocate enough RAM at the start of your program, and making sure you null-terminate your array.
Of the myriad tutorials and descriptions on using C-style strings, one is at https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
-
Are you saying that Arduino doesn't merge back contiguous RAM blocks?user31481– user314812018年02月16日 16:24:10 +00:00Commented Feb 16, 2018 at 16:24
-
No, but often some other action takes place that puts another block on the heap.jose can u c– jose can u c2018年02月16日 16:33:14 +00:00Commented Feb 16, 2018 at 16:33
-
That s seem s realy logical ! i will dig this and apply the change :)Evans Padnom– Evans Padnom2018年02月16日 16:50:37 +00:00Commented Feb 16, 2018 at 16:50
-
arf, till a small problem, i don t achieve to concat in any way my char[] and my INT :/ char screen[16] ; char text[3] = "abc" ; int i = 12 ; screen[16] = text + i ;Evans Padnom– Evans Padnom2018年02月16日 19:58:23 +00:00Commented Feb 16, 2018 at 19:58
-
1You can't use
+
to concat c-style strings. Usestrncat()
.jose can u c– jose can u c2018年02月16日 19:59:25 +00:00Commented Feb 16, 2018 at 19:59
after rewrite all code, rewire all relay, bypass the relay card (using another relay), the problem is still there, but i finally found other people with the same problem, and the solution seem to be adding a "snubber" on each relay, i m waiting for it and will give u a return if it work : link to arduino forum for a common problem