Data transmission to ThingSpeak (with Uno and SIM900) stops after few days

Hello all,

i am using an arduino uno an sim 900 modul, for sending water level to ThingSpeak. (for monitoring a small hydroelectric power plant) But after a few days of perfect data transmission, it stops working. After reconnecting the power supply it starts again.

I am using vodafone germany as network provider. Power is supplyed by an 5V/12V power supply. 5V for Sim modul an 12V for the Arduino.

I am also using the "GPRS_Shield_Arduino.h" libary.

I think the network connection ist being lost and because of this the Arduino cannot send data any more. How can i check if the connection is still doning fine, in the loop. And maybe start reconnection again?

I hope anybody can help me this projekt is part of of my bachelor thesis.

Thanks a lot.

The code is a upgrated (for my conditions) Version of this example:

//Einbindung der erforderlichen Bibliotheken
#include <GPRS_Shield_Arduino.h>
#include <SoftwareSerial.h>

//Pins und Geschwindigkeit der Verbindungs-
//Kommunikation mit der SIM900 - Modul
//Serielle Verbindung, TX und RX PINS 7 und 8
//Power on Pin 9, Einschalten des Sim Moduls
#define pinTX 7
#define pinRX 8
#define pinPower 9
#define BaudrateSim 9600

//Paramenter fuer die Verbindung zu Thingspeak
//Setze den Namen des Servers, mit dem wir uns verbinden wollen
char gprsServer[] = "api.thingspeak.com";
//Setze Speicher-API für ThingSpeak
String API = "VZZ****";
//Die Variable, die verwendet wird, um die Boolean Server Response Dump- Anweisung auszuloesen
boolean vypis = 0;

//Initialisierung des SIM900-Moduls aus der GPRS- Bibliothek
GPRS sim900(pinTX, pinRX, BaudrateSim);

//Variablen initailisieren
int pegel = 0.0;

//Setup wird nur einmal durchlaufen
void setup() {

// Kommunikation über die serielle Leitung initiieren
Serial.begin(9600);

// die Stromversorgung des SIM900-Moduls überprüfen, wenn das Modul ausgeschaltet ist
if (!sim900.checkPowerUp()) {
sim900.powerUpDown(pinPower);
}
// Warten zum Initialisieren des SIM-Moduls
while (!sim900.init()) {
Serial.println( "Initialisierungsfehler!" );
delay(4000);

```
// Zusaetzliche Prüfung ob Sim-Modul eingeschaltet ist,
// falls Arduino Stromversorgung vor der des Sim-Moduls einschaltet
    if (!sim900.checkPowerUp()) {
    sim900.powerUpDown(pinPower);
  } 
```

}
delay(15000);
Serial.println("Initialisierung erfolgreich");
Serial.println("");

//Zugangsdaten für Internetverbindung, abhaenig vom Provider
//Siehe: https://praxistipps.chip.de/apn-einstellungen-mobiles-internet-richtig-einrichten_46068
//Standardparameter ist der APN-Name, der zweite Anmeldename und das dritte Kennwort
//("")bedeutet dieses Feld bleibt leer
//Beispiel: sim900.join (F ("apn"), F ( "user"), F ( "Passwort"))

//Für Vodafone
while (!sim900.join(F("web.vodafone.de"),F(""),F(""))) {

```
Serial.println("Fehler beim Verbinden mit GPRS!");
Serial.println("");
Serial.println("Starte SIM Modul neu!");

    // Modul neustarten wenn Verbindung scheitert
    // Modul ausschalten
    digitalWrite(9, HIGH);
    delay(3000);
    digitalWrite(9, LOW);
    delay(3000);
    //Modul einschalten
    digitalWrite(9, HIGH);
    delay(3000);
```

Serial.println("SIM Modul neugestartet!");
delay(20000);
}

// Die zugewiesene oeffentliche IP Adresse abrufen
Serial.print("Oeffentliche IP Adresse: ");
Serial.println(sim900.getIPAddress());
}

//Programmschleife
void loop() {

// TCP - Verbindung zu einem definierten Server auf Port 80,
// wenn ein Problem auftritt, Fehlermeldung über die serielle Leitung
// und nach einer Pause 2 Sekunden versuchen , die Verbindung wieder aufzubauen
if (!sim900.connect(TCP, gprsServer, 80)) {
Serial.println("Fehler bei TCP - Verbindung");
delay(2000);
}
// Bei erfolgreicher Verbindung folgende Meldung
else {
Serial.print("Verbindung mit dem Server " );
Serial.print(gprsServer);
Serial.println(" gelungen!");
Serial.println("");

```
// Nachricht für Thingspeak erstellen    
//h0 = Hoehe Beckenboden bis Sensorkopf
float h0 = 3.95;
//Analogeingang einlesen
int pegel = analogRead(A1);
Serial.println(pegel);
//Messhoehe (Sensorkopf bis Wasseroberflaeche) aus 0-5V Eingangssignal 
//Umrechnungsfaktor ADC = 5m/1023
//+0,35m für Blindzone Sensor
float hmess = ((pegel*0.004887585)+0.35); 
Serial.println(hmess);
//Messhoehe - absoluten Sensorhoehe, um Wasserstand zu erhalten
float hwasser = (h0 - hmess); 
//Korrekturfaktor nach manueller Messung
hwasser = hwasser + 0.06;
Serial.println("Berechneter Pegel:");
Serial.println(hwasser);
float fuellstand = ((hwasser/3.2)*100);
Serial.println("Berechneter Fuellstand [%]:");
Serial.println(fuellstand);

// Erstellen Sie eine gesamte Nachricht, die gesendet werden soll. 
String str = "GET /update?api_key=";
str += API;
str += "&field1=";
str += hwasser;
str += "&field2=";
str += fuellstand;
str += " HTTP/1.0\r\n\r\n";
// Erstelle ein Zeichenfeld der Groesse 
// Nachricht + 1, um alle Zeichen 
char strChar[str.length() + 1];
// Konvertiere eine Nachricht von String in das richtige Groessenfeld 
str.toCharArray(strChar, str.length() + 1);
// Die erstellte Nachricht über die TCP-Verbindung senden
sim900.send(strChar, str.length());
// in der Schleife, während wir die gesamte Antwort abrufen, 
// vom Server, wenn der Daten-Dump aktiviert ist 
// empfangene Nachricht nach der seriellen Leitung 
char Antwort[512];
while (true) {
// Erstelle ein Zeichenfeld der Groesse 
// Nachricht + 1, um alle Zeichen
  int Zeichen = sim900.recv(Antwort, sizeof(Antwort) - 1);
// Konvertiere eine Nachricht von String in das richtige Groessenfeld
  if (Zeichen <= 0) {
    if (vypis) {
      Serial.println("-> Ende der Antwort.");
    }
    break;
  }
  Antwort[Zeichen] = '\0';
  if (vypis) {
    Serial.print("Received: ");
    Serial.print(Zeichen);
    Serial.print( "byte: " );
    Serial.println(Antwort);
  }
}
// Aktuelle Verbindung beenden und TCP Sim900 trennen
sim900.close();
sim900.disconnect();
Serial.println( "-> Verbindung der Datenverbindung trennen ." );
Serial.println(""); 

// pausiert , bevor die neuen Daten zu senden an Thingspeak 
// erforderlich , minimale Verzögerung von 15 Sekunden bei kostenloser Nutzung 
Serial.println("Pause 30s");
Serial.println("");
delay(30000);
```

}
}

Most probably your problem lies in this code part:

String str = "GET /update?api_key=";
str += API;
str += "&field1=";
str += hwasser;
str += "&field2=";
str += fuellstand;
str += " HTTP/1.0\r\n\r\n";

The String class fragments the memory (RAM) quite fast and sooner or later you ran out of memory although you theoretically have enough of it. Don't use this class, change to use C-style strings (character arrays) only (as you do to get the response).

Thanks for the answer, but unfortunately this part of the code as mentioned above does not come from me.
Unfortunately, I'm wondering how to change that. I thought this part could not be changed and is given by ThingSpeak.

edit 05.57pm: Do you mean using directly a char array for the message? Convert the "floats" into "char" and putting these together and send these? Instead making the "str" String first and than making an char with "toCharArray".

Thank a lot.

Do you mean using directly a char array for the message?

Yes.

Convert the "floats" into "char" and putting these together and send these? Instead making the "str" String first and than making an char with "toCharArray".

It would be much easier if you'd use integers instead of floats (in that case you can simply use snprintf()) but you can convert floats with the dtostrf(). It's a bit more complex but it saves you RAM.