I have made sketch with arduino uno and esp8266 in which i send measures of HC-SR04 to a website. I have two same projects in two different parts with different internet connections. After a month the one of them stop working. Τhe two of them have been operating normally for over seven months and only one of them is causing the problem. Where can the problem arise in one of the two arduino? Is it due to poor internet connection of this part the above problem? My code is:
#include <SoftwareSerial.h>
SoftwareSerial espSerial = SoftwareSerial(2,3);
//Wifi network SSID password
String ssid="ffffff";
String password ="*******";
boolean DEBUG=true;
int echoPin = 12;
int trigPin = 13;
long duration, distance;
int alarm;
String alarms;
String data;
String server = "www.example.com"; // Send data to this site
String uri = "/add2.php";
int error = 0;
int cancel = 0;
void showResponse(int waitTime){
long t=millis();
char c;
while (t+waitTime>millis()){
if (espSerial.available()){
c=espSerial.read();
if (DEBUG) Serial.print(c);
}
}
}
void websiteWrite(long value1, int value2){
if (value2 == 0){
alarms = "OFF";
}else{
alarms = "ON";
}
data = "distance=" + String(value1) + "&alarm=" + alarms;
espSerial.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.
if( espSerial.find("OK")) {
Serial.println("TCP connection ready"); cancel = 0;
}
else{
cancel = cancel + 1; Serial.println("cancel="); Serial.println(cancel);
}
delay(1000);
String postRequest =
"POST " + uri + " HTTP/1.0\r\n" +
"Host: " + server + "\r\n" +
"Accept: *" + "/" + "*\r\n" +
"Content-Length: " + data.length() + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"\r\n" + data;
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
espSerial.print(sendCmd);
espSerial.println(postRequest.length() );
delay(500);
if(espSerial.find(">")) { Serial.println("Sending.."); espSerial.print(postRequest);
if( espSerial.find("SEND OK")) { Serial.println("Packet sent");
while (espSerial.available()) {
String tmpResp = espSerial.readString();
Serial.println(tmpResp);
}
// close the connection
espSerial.println("AT+CIPCLOSE");
}
error = 0;
}else{
error = error + 1;
Serial.println("error=");
Serial.println(error);
}
if(cancel >=15 || error >= 15){software_Reset() ;}
}
void setup() {
delay(150000);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
DEBUG=true;
Serial.begin(9600);
espSerial.begin(9600);
//espSerial.println("AT+RST");
//showResponse(1000);
//espSerial.println("AT+UART_DEF=9600,8,1,0,0");
//showResponse(1000);
espSerial.println("AT+CWMODE=1");
showResponse(1000);
espSerial.println("AT+CWJAP=\""+ssid+"\",\""+password+"\"");
showResponse(5000);
if (DEBUG) Serial.println("Setup completed");
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration/58.2;
if (distance<=8){
alarm=1;
}else{
alarm=0;
}
if (isnan(distance)) {
if (DEBUG) Serial.println("Failed of calculation the distance");
}
else {
if (DEBUG) Serial.println("Distance="+String(distance)+" cm");
websiteWrite(distance,alarm); // Write values to website
}
//Needs 60 sec delay between updates
delay(60000);
}
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
Disconnecting/connecting the device solved the issue temporarily, but this can't be a solution, as the device is supposed to be used permanently and fully automatically. Αnd since both are the same by code and link because one works normally while the other stops?
It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).
prikok:
Disconnecting/connecting the device solved the issue temporarily, but this can't be a solution
I wasn't suggesting it as a solution. I was asking because this can provide helpful diagnostic information. If a power cycle doesn't resolve the problem then it might be caused by faulty hardware, lack of network connectivity, etc. A problem like the memory fragmentation caused by the use of String will always be resolved (temporarily) by a power cycle.
"Stop working" does not say much. What are the symptoms?
I think a first step would be to add some diagnostics ( in the beginning of loop() ).
If you have a PC connected permanently you can add code that sends every N seconds a message over the serial port; you'll need to keep e.g. Serial Monitor open (because opening serial monitor resets the Uno).
If that's not the case, you can implement a blink without delay.
In both cases, you will have an indication if it's just the communication that fails or if your code crashed.
You have two equivalent setups; are they in the same location?
I can not connect it to a PC and they are in different locations. That is why I am impressed that one works properly and the other stops after some time.
While not the solution to a faulty implementation... if your project is a low duty-cycle application, you could use the WDT to buy some time while you develop a proper solution.
The watchdog should be used to catch exceptional failures, not as a band-aid. But it can help with getting through short term obligations!
prikok:
Do you think there is a problem with using strings or something else?
TL/DR: Strings are bad and will crash your program. Use character arrays.
Not strings, but the String class is the problem. Sting is a part of the C libraries. They work just fine on computers with garbage collection (generally any operating system has garbage collection - it cleans up the heap, ie free memory area periodically. But an Arduino has no garbage collection, and it's heap is quite minuscule.
So when you run a sketch using Strings, they slowly, but surely eat up all of the heap, until there are no two consecutive bytes available. At that point you cannot store an integer value, and your program crashes. When it does, the reasons are complex and not usually repeatable. It can crash anywhere from a few hours after starting to several weeks, depending on how often it creates and (incompletely) destroys the Strings.
This matches the circumstances of your issue exactly. Try to re-write your code to use character arrays instead of Strings. There are plenty of functions that manipulate character arrays as strings, however they work differently than do Strings, so you will need to do some additional programming to use them.
Strings simply use malloc() and free() (or the new() and delete() c++ equivalents) behind the scenes. Any intense use of such dynamic memory allocation features in c/c++ (and this applies not only to Strings) will lead to potential heap fragmentation. This is not so much an issue of missing garbage collection because this could still happen even all the items in the heap are still wanted and Arduino Strings are anyway cleaned up if they go out of scope etc. I don’t believe that any form of automatic heap defragmentation is even possible in c/c++ because the language allows the program to maintain direct pointers into the heap.
The Arduino String class has a reserve() method which creates a dedicated pool of heap space which can help to minimize this problem of fragmentation.
ChrisTenone:
So when you run a sketch using Strings, they slowly, but surely eat up all of the heap, until there are no two consecutive bytes available. At that point you cannot store an integer value, and your program crashes. When it does, the reasons are complex and not usually repeatable. It can crash anywhere from a few hours after starting to several weeks, depending on how often it creates and (incompletely) destroys the Strings.
I think you need to rephrase that. They do not necessarily "slowly but surely eat up all the heap" but it might happen.
I did a quick-and-dirty hack of OPs code using global c-strings of sufficient size. I do not think it is as much the use of String as all concatenations are in sequence so there will not be fragmentation. Though I do agree on the comments on the use of String.
But I think that OP is actually running out of memory in the websiteWrite. With the hack, I get a "low on memory" warning.
One reason for the code crashing is that tmpResp can chew away lots of memory depending on the actual response. Looking at the succesfull response in A typical HTTP session - HTTP | MDN, it would be 450 for the header and 650 for the total. As OP does not seem to be interested in the actual result, I would just read and print byte-by-byte instead of using a String variable. I suspect that that will solve the issue but not knowing the exact responses it will be a bit of a guess.
Of course the OP should attempt to make the sketch as reliable as possible and attempt to optimize the use of resources etc. However, the watchdog timer suggestion is also good and the sketch anryway contains a crude restart function. Important would also be to ensure that the restart of the Arduino also forces a restart of the ESP device (which I guess is using the standard firmware supporting AT commands). Since one of the installations functions correctly and the wlans are different, the problem may well be due to the way the ESP reacts to certain failure conditions to which one wlan is more prone (say for example the temporary loss of DNS or something more subtle ) and a complete restart may be the only answer.
Τhe problem still remains. After long time one of them arduino stops. Where can this now be due?
But in the OP, you said this problem showed up after one month. For how long did you test your new "String free" code before the problem occurred this time ?