Arduino Forum

International => Deutsch => Topic started by: GastAnfaenger0815 on Jul 16, 2019, 06:40 pm

Title: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 16, 2019, 06:40 pm
Hallo liebe Gemeinde,
das ist meine erste Spielerei mit dem Arduino, und zwar folgends.

Ich habe das Sim800L Modul (https://www.amazon.de/AZDelivery-%E2%AD%90%E2%AD%90%E2%AD%90%E2%AD%90%E2%AD%90-SIM800L-Antenne-Arduino/dp/B07D361WZV/ref=sr_1_2?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&keywords=arduino+sms+modul&qid=1563294738&s=instant-video&sr=8-2) und möchte damit, wenn ich einen bestimmten Text bekomme, eine SMS an mich senden. Die Library (https://github.com/cristiansteib/Sim800l) benutze ich. Die Beispiel sketche funktionieren ohne Probleme. Das Lesen und das Schreiben von SMS'se kriege ich hin. Nun möchte ich aber den Inhalt der SMS die ich lese mit einem Text z.b. "Temp" vergleichen um dann zum testen eine Temperatur an mich zu senden. Die zu sendende Temperatur simuliere ich zunächst nur mit einem Text der mir gesendet wird sobald ich eine SMS mit dem Inhalt "Temp" an das Modul sende. Leider weiß ich allerdings nicht, wie ich Strings mit anderen Variablen oder Inhalten vergleichen kann. Über Hilfe wäre ich sehr dankbar.

Hier noch mein Aktueller Code, so wie ich es da versucht habe, wird mir nie eine SMS gesendet. Ich denke mal das ich da was grundlegendes falsch verstehe.
Wenn noch weitere Informationen benötigt werden, werde ich diese selbst verständlich noch zu Verfügung stellen. Solltet ihr Librarys kenne, mit dem mein Vorhaben leichter zu realisieren ist, kann ich mir auch vorstellen umzusteigen.


 
Code: [Select]
#include <Sim800l.h>
#include <SoftwareSerial.h> //is necesary for the library!!

Sim800l Sim800l;  //to declare the library
String text;     // to storage the text of the sms
uint8_t index;   // to indicate the message to read.
char Temp = "a";

void setup(){
Serial.begin(9600); // only for debug the results .
Sim800l.begin(); // initializate the library.
index=1; // first position in the prefered memory storage.
text=Sim800l.readSms(index);   
Serial.println(text);
  Sim800l.delAllSms();
}

void loop(){
  text=Sim800l.readSms(index);   
  Serial.println(text);
  Sim800l.delAllSms();
  if (text == "a"){
    Serial.println("Hallo");
    Sim800l.sendSms("Meine Nummer xxxxxxxxxxxxxx","the text go here");
  }
}
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 16, 2019, 06:57 pm
Auf dem Aeduino Nano/MEGA/UNO solltest Du Dir Gebrauch der Klasse String abgewöhnen, wenn Du länger Gefallen daran haben willst. Verwende stattdessen char-Arrays. Infos dazu gibt es hier (https://www.wikinger-tommy.de/arduino/tut_zeichenketten.html).

Zum Vergleich nutze strcmp oder strncmp.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 16, 2019, 07:24 pm
Vielen Dank für deine Antwort, ich werde mir das mal genauer angucken.
Ich habe grade noch festgestellt, wenn ich eine SMS an das Modul sende, dann wird wohl nicht nur der Text den ich gesendet habe an den String übergeben. Sonder noch weitere Daten.
Hier die Serielle Ausgabe nach dem Senden einer sms Empfangen einer SMS am Sim800L Modul.

Code: [Select]
AT+CMGR=1

+CMGR: "REC UNREAD","+49176xxxxxxxx","","19/07/16,19:22:38+08"
temp

OK




Im Internet fand ich dann noch folgendes:

Code: [Select]

at+cmgr=x Auslesen der mit x angegebenen Kurznachricht aus dem mit +CPMS eingestellten
                        Speicherbereich. Die Nachrichten werden im folgenden Format ausgegeben:
                        +CMGL: index, status, length
                        .......PDU.......
at+cmgr=? Zeigt an, welcher Bereich für x im gewählten Speicher unterstützt wird


Was wäre da der einfachste Weg, den von mir gesendeten von dem Rest der Daten zu trennen?
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 16, 2019, 08:08 pm
Das wirst Du doch wohl auf dem Empfangsgerät tun müssen.
Wie sieht die SMS denn da aus?

Welche SMS meinst Du denn nun? Die, Die Du auf dem SIM800 empfängst oder die, die Du sendest?
Mit den AT-Befehlen habe ich mich noch nicht beschäftigt, Deine Serielle Ausgabe passt aber nicht zu Deiner gefundenen Beschreibung.

Gruß Tommy

Edit:
Ich würde vermuten, Der Aufbau bedeutet:
Code: [Select]

+CMGR: "REC UNREAD" --> Kommandoantwort + Zustand (unread)
"+49176xxxxxxxx" --> Absendernummer
"" --> Inhalt (leer)
"19/07/16,19:22:38+08" --> Datum/Uhrzeit und Zeitzone

Das könnte man über strtok aufspalten und weiterverarbeiten. Da wäre aber ein Empfang mit Inhalt sinnvoll.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 16, 2019, 08:18 pm
Sorry, hatte mich da wohl missverständlich ausgedrückt, das was ich in Code Tags gesetzt hatte, war die Ausgabe von "text" nach dem das sms Modul eine SMS von mir mit dem Inhalt "temp" empfangen hat. Leider kenne ich mich mit dem SMS Modul nicht so gut aus, aber ich habe noch das gefunden

At Befehl für Textmode. (https://www.diafaan.com/sms-tutorials/gsm-modem-tutorial/at-cmgf/)
Da ist noch eine andere Verarbeitung des Sendens beschrieben. Ich weiß allerdings nicht, ob das auch das Empfangen von SMS beeinflusst.

Wenn ich die Lib die ich benutze richtig interpretiere unterstützt diese allerdings kein Textmode. Werde es aber jetzt erstmal gucken ob ich das ausprobieren kann. Hatte mir auch schon überlegt eigene Funktionen für die AT Kommandos zu schreiben um unabhängig von der Lib zu werden. Werde mich dafür aber erstmal ein wenig mehr in die Materie einarbeiten müssen.   
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 16, 2019, 08:24 pm
Der Inhalt "temp" ist aber in der Ausgabe nicht sichtbar. Da musst Du erst mal checken, was da noch nicht passt. Bei der SMS-Problematik kann ich Dir nicht helfen, bei der Aufbereitung des Char-Arrays dann wieder.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 16, 2019, 08:30 pm
Ich dachte das wäre so richtig, da das "temp" kommt sobald ich eine SMS an das Modul sende. Was mich verwirrt hatte, waren die Infos dazu. Aber deine Aufdröselung der Daten klingt schlüssig. Dann mache ich mich jetzt erstmal daran mich mehr in das Modul und in der Kommunikation zwischen dem Modul und dem Arduino rein zu arbeiten. Vielen Dank erstmal.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 18, 2019, 05:55 pm
Ich bin aus kosmetischen Gründen jetzt auf dem TC35 von Siemens umgestiegen. Und habe versucht alles in Char Variablen um zu ändern. Und meine eigenen Funktionen für die Kommunikation zwischen Modul und Arduino zu gestalten. Wenn ich meine Nummer nun versuche in ein char array zu packen kommt folgendes.

Code: [Select]
TC35_Test1:38:32: error: invalid operands of types 'const char [10]' and 'char [15]' to binary 'operator+'

   tcSerial.print("At+CMGS=\""+ nummer +"\"\r");

                                ^

exit status 1
invalid operands of types 'const char [10]' and 'char [15]' to binary 'operator+'


Mein Code sieht bis jetzt wie folgt aus.

Code: [Select]
//TC35 Siemens SMS Modul, erstes Testptrogramm.

#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
char text[] = "Test Test Test";
char nummer[] = "+4912345678910"; // Ziffern stimmen mit Anzahl der Zielnummer überein.


void setup()
{
pinMode(10,OUTPUT);  
Serial.begin(9600);  
while (!Serial){}  
tcSerial.begin(9600);
digitalWrite(10,0);
delay(1000);
digitalWrite(10,1);
Serial.println("Ready");
}

void loop() {
  SendeNachricht();
  ShowSerialData();
  delay(500000);
}
void LeseNachricht()
{
  
  
}
void SendeNachricht()
{
  Serial.println("Sende Nachricht...");
  tcSerial.println("AT+CMGF=1\r");
  delay(500);
  tcSerial.print("At+CMGS=\""+ nummer +"\"\r");
  delay(500);
  tcSerial.print(text);
  delay(500);
  tcSerial.println((char)26);
  delay(500);
}


void ShowSerialData() {
  while (tcSerial.available() > 0) {
    Serial.write(tcSerial.read());
  }
}



Wenn ich die Nummer wieder in ein String packe, dann funktioniert es. Und ich kriege die SMS geschickt, die in char text[] steckt. Jedoch möchte ich das mit den Char Arrays richtig verstehen.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 18, 2019, 06:26 pm
Dann schaue mal hier (https://www.wikinger-tommy.de/arduino/tut_zeichenketten.html) rein.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 18, 2019, 06:42 pm
Hmm, war mein Fehler das mit dem Char Array war richtig, ich bin wohl nur zu blöd die Serielle Kommunikation zu benutzen. Wenn ich das wie folgt gestalte funktioniert es auch mit dem Char Array.

Code: [Select]
  tcSerial.print("AT+CMGS=\"");
  tcSerial.print(nummer);
  tcSerial.print("\"\r");



Dann versuche ich mich jetzt mal daran, die SMS die das Modul von mir bekommt zu lesen und zu verarbeiten.

Vielen Dank soweit.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 18, 2019, 07:09 pm
Code: [Select]

char Temp = "a";

'a' ist ein Zeichen. "a" ist ein String. Das ist ein riesiger Unterschied
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 20, 2019, 08:51 pm
Guten Abend, erst einmal vielen Dank für die Hilfe bis jetzt.
Da das auslesen einer Nachricht vom Modul in der Seriellenausgebe so aussieht:

+CMGR: "SMS Status","Nummer",,"RTC"
Text

Dachte ich mir, ich könnte die *"* zählen, bis der Text kommt. das wären 6 Stück.
Desweiteren hatte ich mir gedacht eine SMS immer mit einem Punkt zu beenden.
Und das zählen der Zeichen für c damit zu beenden.
Code: [Select]
while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = (char)tcSerial.read();
      if (fuesseCount >= 6 && punktCount == 0) //Zählt bis anzahl der füße erreicht.
      {
        inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
      }
      if (c == '"') fuesseCount++;  // Zählt ["]
      if (c == '.') punktCount++;   // Zählt [.]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }

 

Mein Problem ist jetzt, ich kriege im Serielmonitur das ausgegeben für das Array char inhalt[160] = "";


Hallo.

Wenn ich das aber nun mit dem Array char text1[] = "Hallo.";

vergleichen möchte, dann habe ich absolut keine Ahnung wie das funktioniert. mit der If abfrage:


Code: [Select]
if (inhalt == text1)
  {
    Serial.println("Sende diesen Text.");
  }
  


geht es nicht. Könnte mir diesbezüglich noch mal Jemand den ein oder anderen Tipp geben?



Mein ganzer code sieht so aus:


Code: [Select]
//TC35 Siemens SMS Modul, erstes Testptrogramm.

#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
char text[] = "Test Test Test";
char nummer[] = "+4912345678910";
char inhalt[160] = "";
char c;
int fuesseCount = 0;
int punktCount = 0;
int charCounter = 0;
int count = 0;
char text1[] = "Hallo.";
//------------------------------------------------
void setup()
{
  pinMode(10, OUTPUT);
  tcSerial.begin(9600);
  Serial.begin(9600);
  //while (!Serial){}
  //tcSerial.begin(9600);
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  Serial.println("Bereit");
}
//------------------------------------------------
void loop()
{
  //SendeNachricht();
  //NachrichtenLoeschen();
  LeseNachricht();
  if (inhalt == text1)
  {
    Serial.println("Sende diesen Text.");
  }
  
  //ZeigeAusgabeModul();
  delay(5000);
}
//------------------------------------------------
void LeseNachricht()
{
  tcSerial.println("AT+CMGF=1"); // Setze Teextmode auf 1
  delay(500);
  tcSerial.println("AT+CMGR=1"); // Lese erste Nachricht im Speicher SM
  delay(500);

  while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = (char)tcSerial.read();
      if (fuesseCount >= 6 && punktCount == 0) //Zählt bis anzahl der füße erreicht.
      {
        inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
      }
      if (c == '"') fuesseCount++;  // Zählt ["]
      if (c == '.') punktCount++;   // Zählt [.]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }
  Serial.println(inhalt);
  Serial.println(charCounter);
  count = 0;
}
//------------------------------------------------
void NachrichtenLoeschen()
{
  tcSerial.print("AT+CMGD=4\r"); // CMGD Löscht nachrichten.
  delay(500);

}
//------------------------------------------------
void SendeNachricht()
{
  Serial.println("Sende Nachricht...");
  tcSerial.print("AT+CMGF=1\r"); // Setzt Textmode auf 1
  delay(500);
  tcSerial.print("AT+CMGS=\""); // Setzt Nummer.
  tcSerial.print(nummer);
  tcSerial.print("\"\r");
  delay(500);
  tcSerial.print(text);
  delay(500);
  tcSerial.print((char)26); // sendet CTRL+Z
  delay(500);
}
//------------------------------------------------
void ZeigeAusgabeModul()
{
  while (tcSerial.available() > 0)
  {
    Serial.write(tcSerial.read());
  }
}
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 20, 2019, 09:17 pm
Du kannst char Arrays nicht mit == vergleichen. Char Arrays zerfallen zu Zeigern auf das erste Element. Damit vergleicht du nur Zeiger, was immer schief läuft

Dafür gibt es strcmp() (string compare):
http://www.cplusplus.com/reference/cstring/strcmp/ (http://www.cplusplus.com/reference/cstring/strcmp/)

Außerdem darfst du beim Einlesen nicht die Null-Terminierung vergessen. C Strings müssen am Ende ein NULL/0/'\0' haben damit die Verarbeitung korrekt funktioniert. Das geht zufällig weil globale Variablen mit 0 initialisiert werden. Aber auch nur bis mal ein kürzerer String kommt
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 20, 2019, 09:29 pm
Du kannst char Arrays nicht mit == vergleichen. Char Arrays zerfallen zu Zeigern auf das erste Element. Damit vergleicht du nur Zeiger, was immer schief läuft

Dafür gibt es strcmp() (string compare):
http://www.cplusplus.com/reference/cstring/strcmp/ (http://www.cplusplus.com/reference/cstring/strcmp/)

Außerdem darfst du beim Einlesen nicht die Null-Terminierung vergessen. C Strings müssen am Ende ein NULL/0/'\0' haben damit die Verarbeitung korrekt funktioniert. Das geht zufällig weil globale Variablen mit 0 initialisiert werden. Aber auch nur bis mal ein kürzerer String kommt
Vielen Dank.
Ich hatte vorher das hier (http://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/strings-vergleichn/) gefunden daraus wurde ich aber nicht wirklich schlau. Bei deinem Link ist es viel besser erklärt. Was du mit Null-Terminierung meinst kann ich mir nicht wirklich vorstellen grade. Ich dachte wenn ich das Array mit char variable[] = "Text"; initialisieren lasse, dass die Null-Terminierung am Ende automatisch kommt. Oder meinst du in dem Moment wo ich mir den Inhalt für das Array char beispiel[] = ""; selbst irngedwo her hole?
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 20, 2019, 09:34 pm
Wenn Du char variable[] = "Text"; benutzt, wird die '\0' automatsch angehängt.
Wenn Du es Zeichenweise einliest, must Du es selbst anhängen, wenn Du das Ende der Übertrsagung erkannt hast.
Das kann z.B. ein NewLine sein.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 20, 2019, 09:43 pm
Das kann z.B. ein NewLine sein.
Ja. Unbedingt das. Die ganzen AT Kommandos werden mit einem CR + LF abgeschlossen. Darauf sollte man abfragen. Das CR kann man ignorieren und das LF als Endzeichen nehmen

Siehe Anleitung:
Code: [Select]

Commands are usually followed by a response that includes.
"<CR><LF><response><CR><LF>"

Wobei es das CR/LF am Anfang etwas komplizierter macht
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 20, 2019, 10:06 pm
Okay, ich komme da noch nicht so ganz hinter.

Wenn ich das Array char inhalt[160] = "";

so bestücke:
Code: [Select]
 while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = (char)tcSerial.read();
      if (fuesseCount >= 6 && punktCount == 0) //Zählt bis anzahl der füße erreicht.
      {
        inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
      }
      inhalt[charCounter] = '\0';
      if (c == '"') fuesseCount++;  // Zählt ["]
      if (c == '.') punktCount++;   // Zählt [.]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }


Und mir dann charCounter seriel ausgeben lasse, dann steht da das charCounter auf 8 gesetzt wurde.
Obwohl Hallo1. nur 6 zeichen hat. Ich vermute, dass noch Enter mit in das Array geschrieben werden. Denn wenn ich bei:
inhalt[charCounter] = '0';
charCounter durch die Zahl 5 ersetze, erscheint nur hal, also 3 zeichen + die Null-Terminierung, aber es müssten ja eigentlich 4 zeichen + Null-Terminierung sein. Oder?

in der Seriellenausgabe sieht es wie folgt aus:

Code: [Select]
Bereit
AT+CMGF=1

OK
AT+CMGR=1

+CMGR: "REC READ","+4912345678910",,"19/07/20,21:41:06+08"
Hallo.

OK  
      
Hallo.    
8
Hallo.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 20, 2019, 10:39 pm
Was willst du eigentlich genau auswerten? Es wird einfacher sein den kompletten String einzulesen und dann zu Parsen. Man kann z.B. mit strtok() an den Kommas teilen und dann mit einem die Teil-Strings weiterarbeiten. Oder mit strchr()/strrchr() nach einzelnen Zeichen suchen
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 20, 2019, 10:49 pm
Ich möchte die SMS die ich an das TC35 sende in das Array char inhalt[160] = "";
schreiben und dieses Array anschließend mit anderen Arrays vergleichen.
Wenn char inhalt[160] gleich dem Array char text1[] = "Hallo."; ist. Möchte ich eine Aktion ausführen. Mein Problem ist jetzt, dass das Array char inhalt[160] wohl erst noch mit einem "enter" beschrieben wird. Deswegen kann ich das nicht mit dem Array char text1[] vergleichen.

Im Moment wenn ich das array char inhalt[160] beschreibe schreibe ich da wohl eher
[
Enter
Hallo.
]

rein.
Title: Re: Arduino Nano TC35 SMS auswerten.
Post by: GastAnfaenger0815 on Jul 21, 2019, 02:13 am
Ich bin jetzt mit dem Auswerten von dem an den Modul gesendeten Nachrichten erst mal so zu frieden, nun würde ich mich daran versuchen den Code nicht blockierend zu schreiben. Wenn ich es richtig verstanden habe, wäre es mit der Funktion Millis(); mach bar. Doch da gestaltet sich für mich folgendes Problem, wenn ich es richtig verstanden habe müsste ich mit millis alles in if funktionen verschachteln. Gibt es da einfachere Möglichkeiten, die ich nicht sehe?

Hier mein code:
Code: [Select]
//TC35 Siemens SMS Modul, erstes Testptrogramm.

#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
char text[] = "Es sind";
char nummer[] = "+4912345678910";
char inhalt[160] = "";
char c;
int fuesseCount = 0;
int punktCount = 0;
int charCounter = 0;
int count = 0;
char text1[] = "Hallo.";
int temperatur = 147;
uint32_t requestMillis = 0;
int16_t ConvWait = 1000;
//------------------------------------------------
void setup()
{
  pinMode(10, OUTPUT);
  tcSerial.begin(9600);
  Serial.begin(9600);
  //while (!Serial){}
  //tcSerial.begin(9600);
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  delay(0000);
  Serial.println("Bereit");

}
//------------------------------------------------
void loop()
{
  LeseNachricht();
  if (strcmp(inhalt, text1) == 0)
  {
    Serial.println(inhalt);
    Serial.println("Sende diesen Text.");
    inhalt[charCounter] = '\0';
    NachrichtenLoeschen();
    Serial.println(charCounter);
    inhalt[0] = '\0';
    count = 0;
    SendeNachricht();
  }
  //Serial.println(inhalt);
  //ZeigeAusgabeModul();
  delay(5000);
}
//------------------------------------------------
void LeseNachricht()
{
  tcSerial.println("AT+CMGF=1"); // Setze Textmode auf 1
  delay(500);
  tcSerial.println("AT+CMGR=1"); // Lese erste Nachricht im Speicher SM
  delay(500);

  while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    charCounter = 0;
    fuesseCount = 0;
    punktCount = 0;
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = (char)tcSerial.read();
      if (fuesseCount >= 6 && punktCount == 1) //Zählt bis anzahl der füße erreicht.
      {
        inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
      }
      //inhalt[charCounter] = '\0';
      if (c == '"') fuesseCount++;  // Zählt ["]
      if (c == '.') punktCount++;   // Zählt [.]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }
  Serial.println(inhalt);
  Serial.println("hallo");
  NachrichtenLoeschen();
  //charCounter = 0;
  Serial.println(charCounter);
  count = 0;
}
//------------------------------------------------
void NachrichtenLoeschen()
{
  tcSerial.println("AT+CMGD=1"); // CMGD Löscht nachrichten.
  delay(1000);

}
//------------------------------------------------
void SendeNachricht()
{
  Serial.println("Sende Nachricht...");
  tcSerial.print("AT+CMGF=1\r"); // Setzt Textmode auf 1
  delay(1000);
  tcSerial.print("AT+CMGS=\""); // Setzt Nummer.
  tcSerial.print(nummer);
  tcSerial.print("\"\r");
  delay(1000);
  tcSerial.print(text);
  tcSerial.print(temperatur);
  delay(1000);
  tcSerial.print((char)26); // sendet CTRL+Z
  delay(1000);
}
//------------------------------------------------
void ZeigeAusgabeModul()
{
  while (tcSerial.available() > 0)
  {
    Serial.write(tcSerial.read());
  }
}
//------------------------------------------------
void Zeit()
{
  requestMillis = millis();
  if (millis() - requestMillis >= ConvWait)
  {


  }
}
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 21, 2019, 03:28 pm
Auch da gilt: werte das eigentliche Ende der Nachricht aus. Du bekommst am Anfang und am Ende ein CR + LF. Frage auf das LF ab. Nach dem zweiten LF ist Ende. Dann weißt du dass du fertig bist. Da nach dem Senden eine zeitlang zu warten ist völlig unnötig. Außerdem hängt diese Zeit von der Baudrate und der Anzahl der Zeichen ab und ist damit nicht konstant

Dann kann man bei jedem loop() Durchlauf abfragen ob was im seriellen Eingangspuffer ist. Wenn ja liest man das Zeichen aus. Wenn nein macht man nichts oder was anderes.
Hier ist ein einfaches Programm um was vom seriellen Monitor einzulesen bis ein LF kommt:
https://forum.arduino.cc/index.php?topic=622530.msg4217397#msg4217397 (https://forum.arduino.cc/index.php?topic=622530.msg4217397#msg4217397)

readLine() ist das relevante. Was in loop() steht ist größtenteils Auswertung. Da ist bei dir anders.
Und nicht von der while() Schleife verwirren lassen. i.d.R. wenn nichts blockiert wird nur ein Zeichen pro Aufruf ausgelesen. Deshalb muss man die Funktion in loop() ständig aufrufen


Man kann auch noch einen Zustands-Automaten bauen und zwischen Senden und Empfangen umschalten. Und dann nur Abfragen ob was da ist wenn man vorher was gesendet hat


Allgemein:
Verwende globale Variablen nur wenn wirklich nötig. Ansonsten lokale. Außerdem werden globale Variablen automatisch mit 0 initialisiert
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 21, 2019, 04:08 pm
Das mit den Globalen und Lokalen Variablen ist mir völlig fremd. Ich weiß, dass ich noch folgendes machen könnte, nur als Beispiel

:
Code: [Select]

void LeseNachricht(char inhalt[160] = "", char c, int charCounter, int punktCount, int fuesseCount)

{
  tcSerial.println("AT+CMGF=1"); // Setze Textmode auf 1
  delay(500);
  tcSerial.println("AT+CMGR=1"); // Lese erste Nachricht im Speicher SM
  delay(500);

  while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
   
    charCounter = 0;
    fuesseCount = 0;
    punktCount = 0;
    //inhalt[charCounter] = '\0';
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = (char)tcSerial.read();
      if (fuesseCount >= 2 && punktCount == 1) //Zählt bis anzahl der füße erreicht.
      {
        inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
      }
      inhalt[charCounter] = '\0';
      if (c == '\n') fuesseCount++;  // Zählt ["]
      if (c == '.') punktCount++;   // Zählt [.]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }
  NachrichtenLoeschen();
  count = 0;




Dann könnte ich auch im loop mit der Methode LeseNachricht:
Code: [Select]

void loop()
{
 LeseNachricht( hier alle Variablen befüllen.);
}


Aber da bin ich dann mit der Syntac komplett überfordert. Ich beschäftige mich jetzt auch zum ersten mal mit dem Thema Programmierung.

Aber nur Beispiele abzuarbeiten, ist nichts für mich. Ich brauche zum lernen immer ein reales Problem.

Mit dem warten nach dem Senden eines AT befehles an das Modul, hatte ich das eigentlich so verstanden, dass das Modul eine gewisse Zeit braucht um den Befehl zu verarbeiten. Was sich für mich bis jetzt auch so gezeigt hatte, denn wenn ich die Befehle zu schnell sende, dann macht das Modul nichts mehr und in der seriellen Ausgabe kommen nur komische Zeichen. Deswegen denke ich schon, dass ich da was mit Zeiten machen muss.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 21, 2019, 04:35 pm
Quote
Mit dem warten nach dem Senden eines AT befehles an das Modul, hatte ich das eigentlich so verstanden, dass das Modul eine gewisse Zeit braucht um den Befehl zu verarbeiten
Ja. Und die Übertragung selbst dauert auch etwas. Du brauchst 1 / Baudrate * 10 Sekunden pro Zeichen. Im Vergleich zur Geschwindigkeit des Prozessors ist das schon eine Ewigkeit. Das ist der Grund weshalb das normal nicht in einer while-Schleife geht. Die würde ein Zeichen einlesen und dann sofort abbrechen weil das nächste noch unterwegs ist.

Das mit dem Delay ist daher nicht grundlegend falsch. Dadurch wartet man einfach und kann so sicher sein dass die komplette Nachricht da ist. Grob geht das. Aber wenn du nicht-blockierend arbeiten willst, muss man es anders machen. Das die Nachrichten mit einem Endzeichen abgeschlossen werden hat schon seinen Grund.
Hier man muss man halt noch beachten dass am Anfang auch CR+LF kommt. Das kann man aber ähnlich wie du es schon gemacht hast mitzählen

Quote
Was sich für mich bis jetzt auch so gezeigt hatte, denn wenn ich die Befehle zu schnell sende, dann macht das Modul nichts mehr und in der seriellen Ausgabe kommen nur komische Zeichen.
Auch deshalb die Anmerkung mit dem Zustands-Automaten. So dass man erst das nächste Kommando sendet wenn die Antwort des vorherigen abgearbeitet ist


Insgesamt ist das nicht das einfachste Anfänger-Projekt. Da muss man schon einige Feinheiten beachten. Auch wenn man sich etwas auskennt
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 21, 2019, 04:45 pm
Ahh okay, also wenn ich dich richtig verstanden habe, könnte ich einfach die wie du schon sagtest LF mit

if ( c ==  '\n') LFZaehler++;

zählen und einfach jeden nächsten Schritt mit z.b.

if (LFZaehler == 0)

{
Tu das
}


if (LFZaehler == 1;

{
tu das
}

abarbeiten und den LFZaehler mit dem letzten Schritt wieder auf 0 setzen, oder?
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 21, 2019, 04:48 pm
Na, ja. Nicht ganz. Eine Antwort sieht laut Anleitung so aus:
<CR><LF>Text<CR><LF>

Das solltest du auch im seriellen Monitor sehen. Das CR macht da nichts, aber das LF erzeugt eine Leerzeile.
Du musst also die Linefeeds zählen und beim zweiten hast du das Ende.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 21, 2019, 07:21 pm
Vorausgesetzt ich habe dich jetzt richtig verstanden, habe ich hier jetzt ein kleinen testcode geschrieben.

Code: [Select]
// Software Serial test Sketch für TC35 SMS Modul.

#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);

int counter = 0;

void setup()
{
  pinMode(10, OUTPUT);
  Serial.begin(9600);
  tcSerial.begin(9600);
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  delay(500);
  tcSerial.print("AT+CMGF=1\r\n");
  delay(500);
  Serial.println("Bereit!");
}

void loop()
{
  while (tcSerial.available() > 0)
  {
    Serial.write(tcSerial.read());
    char c;
    c = (char)tcSerial.read();
    if (c == '\n') counter++;
    if (counter == 0)
    {
      tcSerial.println("AT+CMGR=1");
    }

  }
  Serial.println(counter);
  delay(5000);
}



Dazu kommt dann hier die Serielleausgabe am Monitor

Code: [Select]

3
3
3
3
3
3
3
3
3
3
3Bereit!
A+MF1
ERR
1
A+MR1A+MR1A+MR1
RO
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2


Was mich hier jetzt noch mehr verwirrt als die Tatsache dass, das was ich ausprobieren wollte nicht zu funktionieren scheint, ist dass schon vor das verlassen des Setups in dem int counter wohl eine 3 drinne steht. Uns später eine 2 obwohl nirgendwo was subtrahiert wird.

Nun ja ich hatte da gehofft, so lange in der If funktion zu bleiben, bis eine Antwort von dem Modul zurück kommt. Aber es kommen wie davor auch ohne delay komische Zeichen irgendwas muss ich da noch startk missverstehen.



Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 21, 2019, 10:32 pm
Das obere Phonemen scheint wohl andere Ursachen zu haben, die ich nicht mehr reproduziert bekomme.

Mit dem folgenden Code

Code: [Select]
// Software Serial test Sketch für TC35 SMS Modul.
#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
int Counter = 0;
int testCounter = 0;
void setup()
{
  pinMode(10, OUTPUT);
  Serial.begin(9600);
  tcSerial.begin(9600);
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  delay(500);
  //tcSerial.print("AT+CMGF=1\r\n");
  delay(500);
  Serial.println("Bereit!");
  delay(5000);
}
void loop()
{
  if (Counter == 0 && testCounter == 0)
  {
    //tcSerial.println("AT+CMGR=1");
    tcSerial.println("AT+CMGF=1");
    //Serial.println("Okay...");
    testCounter++;
  }
  while (tcSerial.available() > 0)
  {
    Serial.write(tcSerial.read());
    char c;
    c = (char)tcSerial.read();
    if (c == '\n') Counter++;


  }
  Serial.println(Counter);
  delay(5000);
}


Sieht die Serielle Ausgabe nun so aus.

Code: [Select]
Bereit!
0
A+MF1
O
2
2
2
2
2
2
2
2
2

 

Wobei es bei dem gesendeten AT - Befehl so aussieht, als würde beim Senden des Befehls nun jedes zweite Zeichen fehlen.
Was auch erstmal egal wäre, da das "O" das Teil vom "OK" sein wird. Also wenn ich das so weiter führe könnte es funktionieren, es wäre allerdings nur nicht so schön. Und so macht es ja auch wenig Sinn für weiterführende Probleme / Anwendungen oder sonstiges, wenn ich nicht feststelle warum es so ist und es gegebenenfalls auch löse.




Hmm, wenn ich die Zeilen:
  Serial.println(Counter);
  delay(5000);

weg lasse, dann kommt alles normal bei dem Seriellen monitor.

Code: [Select]
Bereit!
AT+CMGF=1

OK


Kann mir das einer erklären? Ich verstehe nicht warum die Ausgabe im seriellen Monitor von mir außerhalb der Schleifen so eine Wirkung haben sollte.
Oder ist es wirklich weil nahe zu direkt im gleichen Moment wo die If bedingung wahr wird das dann meine Ausgabe dafür sorgt das die Daten ein bisschen zusammen gewürfelt werden?
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 21, 2019, 10:58 pm
Code: [Select]

  Serial.write(tcSerial.read());
    char c;
    c = (char)tcSerial.read();
    if (c == '\n') Counter++;

Das ist Unsinn. Damit liest du zwei Zeichen aus und eines wird zwar ausgegeben aber nicht überprüft
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 22, 2019, 09:30 am
Also meinst du eher so:

Code: [Select]

Serial.write(tcSerial.read());
    char c;
    c =tcSerial.read();
    if (c == '\n') Counter++;



Also ohne (char) bei c=tcSerial.read(); sonst kann ich dir gar nicht mehr folgen.

Oder meinst du, dass ich mit

If (c =='\n') Counter++;

Den Counter um 2 erhöhen muss weil es im prinzip 2 zeichen sind?
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 22, 2019, 02:29 pm
Du machst zweimal read(). Da ist doch klar dass ja jedes zweite Zeichen anders behandelt wird
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 27, 2019, 09:38 pm
Danke Serenifly,

war mein Fehler im ursprungscode hatte ich

c = tcSerial.read();

durch

Serial.print(c);

getauscht.

Aber beim schreiben des testscetches nicht mehr daran gedacht.

Wenn ich mein Scetch jetzt auf einem NodeMCU laden möchte,
hatte ich gelesen, dass ich mir eine andere SoftwareSerial Librarie runterladen muss.
Diese hat allerdings den selben Namen wie die originale von Arduino.
Reicht es wenn ich diese nur umbennene oder muss ich da noch andere Sachen beachten?

Hier (https://github.com/plerup/espsoftwareserial) findet man die besagte SoftwareSerial librarie.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 27, 2019, 09:46 pm
Du hast 2 grundlegende Wege:

1. die alte Lib löschen/verschieben
2. für die Arbeit mit dem ESP zusätzlich eine eigene portable Version (https://www.arduino.cc/en/Guide/PortableIDE) der IDE benutzen.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 27, 2019, 09:55 pm
Du hast 2 grundlegende Wege:

1. die alte Lib löschen/verschieben
2. für die Arbeit mit dem ESP zusätzlich eine eigene portable Version (https://www.arduino.cc/en/Guide/PortableIDE) der IDE benutzen.

Gruß Tommy
Okay, das mit dem verschieben funktioniert schon mal, dann gucke ich morgen mal dabei eine portable Version zu machen, ist glaube für die Zukunft dann einfacherer. Vielen dank.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: noiasca on Jul 28, 2019, 07:58 am
Weiters könntest du:

3. die Dateien der weitere Lib lokal im Sketch speichern und lokal einbinden
4. die weitere Lib runterladen und einen anderen Namen geben
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 30, 2019, 11:43 pm
TEIL 1 von 2.


Vielen dank, mit der portablen Version funktioniert es auch.

Da ich jedoch gerne beim Arduino Nano bleiben würde, hätte ich noch eine Frage.

Ich habe jetzt 2 Sketche, einmal diesen hier:

Code: [Select]

#include <NewPing.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
#define ONE_WIRE_BUS
#define TRIG_PIN 3
#define ECHO_PIN 4
#define MAX_DIST 400
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DIST);
uint32_t requestMillis = 0;
bool requestStarted = false;
uint8_t bitResolution = 12;
int16_t ConvWait = 750;
char fuellstand[15] = "\nFuellstand?";
char tempTemp[15] = "\nTemperatur?";
char nummer[20] = "+49xxxxxxxxx";
char inhalt[160] = "";
char smsErhalten[3] = "";
char c;
float platzhalter = 0;
float temp = 0;
float abstand = 0;
int fuesseCount = 0;
int lnCount = 0;
int charCounter = 0;
int count = 0;
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void setup()
{
  pinMode(10, OUTPUT);
  tcSerial.begin(9600);
  Serial.begin(9600);
  while (!Serial) {}
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  delay(3000);
  tcSerial.println(F("AT+CMGF=1")); // Setze Textmode auf 1
  delay(1000);  
  tcSerial.println(F("AT+CMGD=1")); // CMGD Löscht nachrichten.
  delay(5000);
  Serial.println(F("Bereit"));
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void loop()
{
  abstand = sonar.ping_cm();
  if (!requestStarted)
  {
    sensors.requestTemperatures();
    requestStarted = true;
    requestMillis = millis();
  }
  if (millis() - requestMillis >= ConvWait)
  {
    temp = sensors.getTempCByIndex(0);
    requestStarted = false;  
  }
  LeseNachricht();
  if (strcmp(inhalt, fuellstand) == 0) // Wenn inhalt = char Array fuellstand dann mache:
  {
    platzhalter = abstand*25;
    Serial.println(F("Sende Nachricht mit aktuellen Wert des Fuellstandes."));
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    Serial.println(F("Sende Nachricht..."));
    tcSerial.print(F("AT+CMGS=\"")); // AT-Befehl für Nummer.
    tcSerial.print(nummer); // Gibt Nummer weiter an den AT-Befehl.
    tcSerial.print(F("\"\r")); // Sendet ein Enter.
    delay(1000);
    tcSerial.print(F("Der Fuellstand liegt bei")); // Übergibt zu sendenden Text an das Modul.
    tcSerial.print(platzhalter); // Übergibt den Platzhalter an das Modul.
    tcSerial.print(F("Liter"));
    delay(1000);
    tcSerial.print((char)26); // sendet CTRL+Z
    delay(5000);
  }
  else if (strcmp(inhalt, tempTemp) == 0) // Wenn inhalt = char Array tempTemp dann mache:
  {  
    Serial.println(F("Sende Nachricht mit aktuellen Wert der Temperatur."));
    platzhalter = temp;
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    Serial.println(F("Sende Nachricht..."));
    tcSerial.print(F("AT+CMGS=\"")); // AT-Befehl für Nummer.
    tcSerial.print(nummer); // Gibt Nummer weiter an den AT-Befehl.
    tcSerial.print(F("\"\r")); // Sendet ein Enter.
    delay(1000);
    tcSerial.print(F("Die Temperatur liegt bei:")); // Übergibt zu sendenden Text an das Modul.
    tcSerial.print(platzhalter); // Übergibt den Platzhalter an das Modul.
    tcSerial.print(F("Grad Celsius"));
    delay(1000);
    tcSerial.print((char)26); // sendet CTRL+Z
    delay(5000);
  }
  else if (strcmp(inhalt, smsErhalten) != 0) // Wenn inhalt != smsErhalten dann mache:
  {
    Serial.println(F("Hier ist noch ein Fehler"));
    platzhalter = 0;
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    Serial.println(F("Sende Nachricht..."));
    tcSerial.print(F("AT+CMGS=\"")); // AT-Befehl für Nummer.
    tcSerial.print(nummer); // Gibt Nummer weiter an den AT-Befehl.
    tcSerial.print(F("\"\r")); // Sendet ein Enter.
    delay(1000);
    tcSerial.print(F("Sende Fuellstand? fuer den aktuellen Wert des Fuellstandes, oder Temperatur? fuer den aktuellen Wert der Temperatur.")); // Übergibt zu sendenden Text an das Modul.
    delay(1000);
    tcSerial.print((char)26); // sendet CTRL+Z
    delay(5000);  
  }
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void LeseNachricht()
{
  tcSerial.println(F("AT+CMGR=1")); // Lese erste Nachricht im Speicher SM
  delay(750);
  while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    charCounter = 0;
    fuesseCount = 0;
    lnCount = 0;
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = tcSerial.read();
      if (fuesseCount >= 6) //Zählt bis anzahl der '"' erreicht.
      {
        inhalt[charCounter] = '\0';
        if (c == '\n') lnCount++; // Zählt [\n].
        if (lnCount == 1 && lnCount != 2)
        {
          inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
        }  
      }
      inhalt[charCounter] = '\0';
      if (c == '"') fuesseCount++;  // Zählt ["]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }
  Serial.println(inhalt); //
  Serial.println(charCounter);
  Serial.println(lnCount);
  count = 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void NachrichtenLoeschen()
{
  tcSerial.println(F("AT+CMGD=1")); // CMGD Löscht nachrichten.
  delay(1000);
}


Da habe ich nach dem kompilieren noch 487 bytes freien dynamischen Speicher. Dafür wird der Teil
void loop relativ lang und meiner Meinung nach unübersichtlich.

Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Jul 30, 2019, 11:48 pm
TEIL 2 von 2.

Und diesen Sketch:

Code: [Select]

#include <NewPing.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>
#define rxPin 9
#define txPin 8
#define ONE_WIRE_BUS
#define TRIG_PIN 3
#define ECHO_PIN 4
#define MAX_DIST 400
SoftwareSerial tcSerial = SoftwareSerial(rxPin, txPin);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DIST);
uint32_t requestMillis = 0;
bool requestStarted = false;
uint8_t bitResolution = 12;
int16_t ConvWait = 750;
char fuellstand[15] = "\nFuellstand?";
char tempTemp[15] = "\nTemperatur?";
char nummer[20] = "+49xxxxxxxxxxx";
char inhalt[160] = "";
char smsErhalten[3] = "";
char text[160] = "";
char c;
float platzhalter = 0;
float temp = 0;
float abstand = 0;
int fuesseCount = 0;
int lnCount = 0;
int charCounter = 0;
int count = 0;
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void setup()
{
  pinMode(10, OUTPUT);
  tcSerial.begin(9600);
  Serial.begin(9600);
  while (!Serial) {}
  digitalWrite(10, 0);
  delay(1000);
  digitalWrite(10, 1);
  delay(3000);
  tcSerial.println(F("AT+CMGF=1")); // Setze Textmode auf 1
  delay(1000);  
  tcSerial.println(F("AT+CMGD=1")); // CMGD Löscht nachrichten.
  delay(5000);
  Serial.println(F("Bereit"));
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void loop()
{
  abstand = sonar.ping_cm();
  if (!requestStarted)
  {
    sensors.requestTemperatures();
    requestStarted = true;
    requestMillis = millis();
  }
  if (millis() - requestMillis >= ConvWait)
  {
    temp = sensors.getTempCByIndex(0);
    requestStarted = false;  
  }
  LeseNachricht();
  if (strcmp(inhalt, fuellstand) == 0) // Wenn inhalt = char Array fuellstand dann mache:
  {
    platzhalter = abstand*25;
    Serial.println(F("Sende Nachricht mit aktuellen Wert des Fuellstandes."));
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    NachrichtSenden ("Der Fuellstand liegt bei");
  }
  else if (strcmp(inhalt, tempTemp) == 0) // Wenn inhalt = char Array tempTemp dann mache:
  {  
    Serial.println(F("Sende Nachricht mit aktuellen Wert der Temperatur."));
    platzhalter = temp;
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    NachrichtSenden ("Die Temperatur liegt bei:");
  }
  else if (strcmp(inhalt, smsErhalten) != 0) // Wenn inhalt != smsErhalten dann mache:
  {
    Serial.println(F("Hier ist noch ein Fehler"));
    platzhalter = 0;
    NachrichtenLoeschen();
    NachrichtenLoeschen();
    NachrichtSenden("Sende Fuellstand? fuer den aktuellen Wert des Fuellstandes, oder Temperatur? fuer den aktuellen Wert der Temperatur.");  
  }
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void LeseNachricht()
{
  tcSerial.println(F("AT+CMGR=1")); // Lese erste Nachricht im Speicher SM
  delay(750);
  while (count == 0) // Loop bis count nicht mehr gleich 0.
  {
    charCounter = 0;
    fuesseCount = 0;
    lnCount = 0;
    while (tcSerial.available() > 0)// Wenn dort Daten sind dann lese sie.
    {
      c = tcSerial.read();
      if (fuesseCount >= 6) //Zählt bis anzahl der '"' erreicht.
      {
        inhalt[charCounter] = '\0';
        if (c == '\n') lnCount++; // Zählt [\n].
        if (lnCount == 1 && lnCount != 2)
        {
          inhalt[charCounter++] = c; // Schreibt jedes Zeichen einzellnd in das Char Array
        }  
      }
      inhalt[charCounter] = '\0';
      if (c == '"') fuesseCount++;  // Zählt ["]
      Serial.print(c);
      count++; // Erhöhe die Variable count um 1
    }
  }
  Serial.println(inhalt); //
  Serial.println(charCounter);
  Serial.println(lnCount);
  count = 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void NachrichtenLoeschen()
{
  tcSerial.println(F("AT+CMGD=1")); // CMGD Löscht nachrichten.
  delay(1000);
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------
void NachrichtSenden(char text[160])
{
    Serial.println(F("Sende Nachricht..."));
    tcSerial.print(F("AT+CMGS=\"")); // AT-Befehl für Nummer.
    tcSerial.print(nummer); // Gibt Nummer weiter an den AT-Befehl.
    tcSerial.print(F("\"\r")); // Sendet ein Enter.
    delay(1000);
    tcSerial.print(text); // Übergibt zu sendenden Text an das Modul.
    tcSerial.print(platzhalter); // Übergibt den Platzhalter an das Modul.
    delay(1000);
    tcSerial.print((char)26); // sendet CTRL+Z
    delay(5000);
}



Da habe ich nur noch 310 bytes frei für den dynamischen Speicher.
Und hier ist der void loop deutlich kürzer und meiner Meinung nach schöner.
Ist ja auch klar, der größte Teil befindet sich dann in der Methode NachrichtSenden()

Gibt es einfache Möglichkeiten wie z.b. durch (F(....)) das was in den dynamsichen Speicher geschrieben wird in den Programmspeicher abzulegen?

Oder generell noch für einem Anfänger mittel und Wege mehr Speicher zu sparen?
"Anfänger" setze ich mal so, da ich durchaus gewillt bin mich auch mit komplexeren Sachen zu beschäftigen.
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Tommy56 on Jul 31, 2019, 02:26 pm
z.B. mal mit PROGMEM und strcmp_P beschäftigen und alles was konstant ist auch als const deklarieren.

Gruß Tommy
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Jul 31, 2019, 03:28 pm
Du solltest dir abgewöhnen ständig die Größe von Arrays vorzugeben wenn es gar nicht nötig ist. z.B. bei deinen Text-Konstanten und NachrichtSenden(). Bei Literalen kann der Compiler die Länge selbst ermitteln.
Und bei Funktionen übergibt man char Arrays als Zeiger! Ein Array zerfällt immer zu einem Zeiger auf das erste Element

Die Größe musst du nur bei Puffern angeben wo du nicht weißt wie lange der tatsächliche Inhalt sein wird

Code: [Select]

const char str[] PROGMEM = "PROGMEM String";

void setup()
{
  Serial.begin(9600);

  printText_P(str);
  printText_P(PSTR("PSTR() String"));
  printText_P_Alt(PSTR("PSTR() String Alternative"));

  printText_F(F("F() String"));

  if (strcmp_P("Test String", PSTR("Test String")) == 0)  //1. String im RAM, 2. String mit PSTR() oder PROGMEM im Flash
  {
    Serial.println("gleich");
  }
}

void loop()
{
}

//Text wird komplett Puffer kopiert. Hier kann man evtl. statt dessen einen gemeinsamen globalen Puffer für alles nehmen
void printText_P(const char* str)
{
  char buffer[20];
  strlcpy_P(buffer, str, sizeof(buffer));
  Serial.println(buffer);
}

//Alternative ohne speicherfressenden Puffer. Buchstaben werden Stück für Stück ausgegeben
void printText_P_Alt(const char* str)
{
  char c;
  for (byte i = 0; (c = pgm_read_byte(str + i)) != '\0'; i++)
    Serial.print(c);
  Serial.println();
}

//Verwendet statt dessen das F() Makro der Arduino Software
void printText_F(const __FlashStringHelper* str)
{
  Serial.println(str);
}


const char* kann nicht zwischen einem String im RAM und im Flash unterscheiden. Deshalb hat die Arduino Software noch F() und __FlashStringHelper mit einem speziellen Datentyp. Für print()/println() kann das deshalb die bessere Wahl sein, da man nichts per Hand umkopieren muss

Wenn man andere Dinge tun will braucht man aber PROGMEM/PSTR(). Von allen C String Funktionen gibt es _P Versionen die mit Strings im PROGMEM umgehen können:
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html (https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html)
Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: GastAnfaenger0815 on Aug 04, 2019, 06:11 pm
Vielen Dank für die viele Hilfe bis jetzt.

Der hohe Speicher-verbrauch des dynamischen Speichers lag daran, dass ich in der Software Serial Lib den Buffer von 64 bytes  auf 1024 bytes  erhöht hatte. Das es daran liegen könnte ist mir aber erst aufgefallen, als ich auf einem anderen System die Arduino IDE installiert hatte und mein Code nicht mehr funktionierte, da beim Einlesen einer SMS nur 64 bytes gelesen wurden. Habe den Buffer jetzt erstmal auf 256 bytes  reduziert. Und jetzt noch 1258 bytes frei. Eure vorgeschlagenen Lösungsansätze werde ich mir später angucken. Da das Programmieren mir wohl doch mehr Spaß gemacht hatte als ich zuerst dachte, habe ich mir jetzt ein Programmierer Handbuch bestellt. Bis jetzt hatte ich mich immer nur mit Hardware Sachen herum geschlagen. Ich poste mal ein paar Bilder von meinem Aufbau für die, die es interessiert.

(https://forum.arduino.cc/index.php?action=dlattach;topic=626676.0;attach=319177)

(https://forum.arduino.cc/index.php?action=dlattach;topic=626676.0;attach=319179)

(https://forum.arduino.cc/index.php?action=dlattach;topic=626676.0;attach=319181)

Title: Re: Arduino Nano SIm800L Modul String setzen und vergleichen.
Post by: Serenifly on Aug 05, 2019, 12:06 am
Quote
Das es daran liegen könnte ist mir aber erst aufgefallen, als ich auf einem anderen System die Arduino IDE installiert hatte und mein Code nicht mehr funktionierte, da beim Einlesen einer SMS nur 64 bytes gelesen wurden.
Ich glaube da ist eher das Schuld was du programmiert hat. Die serielle Schnittstelle ist sehr, sehr viel langsamer als der Prozessor. Ein Byte braucht 1 * Baudrate * 10 Sekunden. Selbst bei hohen Baudraten kann man daher den Eingangspuffer schneller auslesen als Daten ankommen.
Du musst nur dein Programm vernünftig schreiben. Vor allem nicht-blockierend, so dass man ständig überprüfen kann ob neue Daten da sind

Also lass den Puffer auf einer normalen Größe. Dann lege dir im eigentlichen Programm einen Puffer an der groß genug für die größte Nachricht ist (muss das wirklich 1kB sein) und kopiere ständig die Daten um