Datenlogger, Fehler bei Arrays

Hallo Forum,

bei einem Datenlogger-Projekt auf einem Arduino Nano habe ich ein seltsames Problem.

Ein Empfangsgerät bekommt von verschiedenen Sendern eine Namen (eine Adresse eines 18D20) und eine Temperatur übermittelt.
Nach der Übermittlung von einem Datensatz wird der Datensatz in ein CharArray "Empfangsstring" geschrieben. Anschließend wird geprüft, ob der Name schon in einem anderen CharArray "Wertespeicher" vorhanden ist.
Wenn er nicht vorhanden ist, soll er in den Wertespeicher kopiert werden.
Beim Durchlauf des ersten Datensatzes funktioniert das auch.
Kommt allerdings ein zweiter Datensatz mit einem anderen Namen, steht er von Anfang an (also schon beim Vergleich) sowohl im Empfangsstring als auch im Wertespeicher, ohne daß er kopiert wurde.
Ich hatte schon den Verdacht, daß beim Kopieren der Pointer auf den Wertespeicher die Adresse des Empfangsspeichers bekommt ( Wertespeicher[d][0] = Empfangsstring[a][0]; ) aber soweit ich das prüfen konnte, haben unterschiedliche Adressen.
Aktuell weiß ich nicht mehr weiter.
Woran kann das liegen?

char *Empfangsstring[4][17];
char *Wertespeicher[6][17];
unsigned int grArrEmpfangsstring=4;
unsigned int grArrWertespeicher = 6;

unsigned int b; // Zähvariable Wertespeicher
unsigned int d; // Zähvariable Wertespeicher



//In Loop steht folgender Ausschnitt

 int k; //Vergleichsergebnis

    
    for (unsigned int a = 0; a <= sizeof(grArrEmpfangsstring); a = a + 2)
    {
      bool MerkerA=false; // Merker, ob Zahl im Wertespeicher schon vorhanden

      for (b = 0; b <= sizeof(grArrWertespeicher); b = b + 2)
      {
        k = strcmp(Empfangsstring[a][0], Wertespeicher[b][0]);
        if ((k == 0) && (Empfangsstring[a][0] != "")) // Wenn Werte gleich und Empfangsspeicher nicht leer, dann Wert in Wertespeicher vorhanden --> MerkerA=true
			{
				MerkerA=true;// Element in Wertespeicher enthalten
      		}
      }// Ende For-Schleife b
        
       if ((MerkerA != true ) && (Empfangsstring[a][0]!=""))  //Wenn MerkerA = false und Empfangsstring[a] nicht leer, dann kopieren.
        {
          Wertespeicher[d][0] = Empfangsstring[a][0];
          d = d + 2;
          }
       MerkerA = false; // Merker zurücksetzen, nachdem Schleife b durchlaufen wurde;

        }  //Ende For-Schleife a
  

Vielen Dank
Klaus

Ausschnitte helfen keinem weiter. Gib uns bitte einen kompilierfähigen Sketch.

Gruß Tommy

Ist 2

Ist auch 2

Sebst sizeof(1) oder sizeof(4711) ist 2

wäre da nicht eine Datenstruktur besser angebracht?
Warum landet die Temperatur nicht in einer Zahl/Integer/Float?!?

struct Sensor{
  char name[4];
  float temp;
};
Sensor sensor[17];

dann schreib dir eine Funktion int find(char needle[4]) der du einen Suchbegriff/Namen/Needle übergibst und dir entweder die Indexposition aus dem Vergleich mit der Position aus dem Struktur Array zurück gibt oder -1 wenn der übergebene Name noch nicht im Array vorhanden ist.

Hallo zusammen,

vielen Dank für die Antworten bisher.

@combie : Interessant, das mit der Größe muß ich später prüfen. Das wirft gerade mein Weltbild etwas durcheinander, weil ich es bisher so gemacht habe. Aber mit Pointern ist halt manche anders.

@noiasca: Die Temperatur ist ein String, weil die Daten später an ein NAS weitergeschickt werden müssen, und ich dafür einen String brauche. Mit Strukturen kenne ich mich noch nicht aus.

Mit Daten aus nur einer Quelle funktioniert das ganze, auch mit fünf Sensoren.
Mein Ziel ist, daß die Daten von mehrern Quellen in einem String an das NAS geschickt werden können. Dafür müssen doppelte Werte vermieden werden.

Hier ist der komplette Quellcode:

#include <Arduino.h>

#include "printf.h"
#include <RF24.h>
#include <RF24Network.h>
#include <Ethernet2.h>


#define DEBUG 1

#if DEBUG == 1
#define debug(x) Serial.print(x)
#define debugln(x) Serial.println(x)
#else
#define debug(x)
#define debugln(x)
#endif



RF24 radio(7, 8); // nRF24L01(+) radio attached using Getting Started board

RF24Network network(radio);     // Network uses that radio
const uint16_t this_node = 00;  // Address of our node in Octal format ( 04,031, etc)
const uint16_t other_node = 01; // Address of the other node in Octal format

const unsigned long interval = 30000; // ms  Intervall wie oft Daten auf den Server geschickt werden
unsigned long last_sent;              // Zeit (millis), wann das letze Mal Daten auf den Server geschickt wurden.
uint32_t wait = 2000;
uint32_t lastWait = wait;

/**** Create a large array for data to be received ****
 * MAX_PAYLOAD_SIZE is defined in RF24Network_config.h
 * Payload sizes of ~1-2 KBytes or more are practical when radio conditions are good
 */

char dataBuffer[MAX_PAYLOAD_SIZE]; // MAX_PAYLOAD_SIZE is defined in RF24Network_config.h


char *Empfangsstring[4][17];
unsigned int grArrEmpfangsstring=4;

unsigned int grArrWertespeicher = 6;
char *Wertespeicher[6][17];

unsigned int b; // Zähvariable Wertespeicher
unsigned int d; // Zähvariable Wertespeicher

char *Teilstring; // Pointer auf char-Array zum Zerlegen der empfangenen Strings

// Angaben für Ethernet
byte mac[] = {0xDE, 0x01, 0x01, 0x01, 0x01, 0x01}; // MAC-ADRESSE eingeben!
byte ip[] = {192, 168, 181, 48};                   // IP-Adresse Arduino!
byte gateway[] = {192, 168, 181, 1};               // Gateway eingeben!
byte subnet[] = {255, 255, 255, 0};
byte server[] = {192, 168, 181, 8}; // IP des Servers eingeben
EthernetClient client;              // wurde geändert
char host[] = "192.168.181.8"; // = "localhost";  // DOMAIN eingeben!
char url[] = "/arduino_testdb.php"; // Pfad zur PHP-Datei eingeben
char c;

void setup(void)
{
  // debug_init();

  Serial.begin(115200);
  while (!Serial)
  {
    // some boards need this because of native USB capability
  }
  // debugln("Vor Ethernet begin");
  Ethernet.begin(mac, ip, gateway, subnet);
  delay(2000);
  debug("Verbinde Setup ");
  if (client.connect(server, 80))
  { // Verbindung zum Server aufbauen
    debugln("Verbunden");
  }
  else
  {
    debugln(" ***** VERBINDUNGSAUFBAU NICHT MÖGLICH *****");
  }
  client.stop();

  // debugln(F("Datenlogger4 Empfänger"));

  if (!radio.begin())
  {
    debugln(F("Radio hardware not responding!"));
    while (1)
    {
      // hold in infinite loop
    }
  }
  radio.setChannel(90);
  radio.setPALevel(RF24_PA_MAX);
  network.begin(/*node address*/ this_node);

  printf_begin(); // needed for RF24* libs' internal printf() calls
  radio.printDetails(); // requires printf support

  lastWait = millis();
}

// Variable for calculating how long between RX
uint32_t timeBetweenPackets = 0;

void Daten_senden() // per Ethernet an NAS
{
  Ethernet.begin(mac, ip, gateway, subnet);
  delay(200); // Vielleicht unnötig
  Serial.print("Verbinde DS1 ");
  if (client.connect(server, 80))
  { // Verbindung zum Server aufbauen
    debugln("Verbunden");
  }
  else
  {
    debugln(" ***** VERBINDUNGSAUFBAU NICHT MÖGLICH *****");
  }

  debugln("Daten senden an Ethernet");
  debug("Verbinde Ethernet ");
  client.connect(server, 80);
  if (client.connected()) // Prüfen, ob Verbindung zum Server steht
  {
    debug("Verbunden...sende Daten...");
    client.print("GET /arduino_testdb3.php");

    client.print("?Data=");

    client.print(dataBuffer);

    client.println(" HTTP/1.1");
    client.println("Host: 192.168.181.8");
    client.println();

    debug("Message: ");
    debugln(dataBuffer);
    debugln("fertig!");

    client.stop();
  }
  else
  {
    debugln(" ***** VERBINDUNGSAUFBAU NICHT MÖGLICH *****");
  }

  if (client.available())
  {
    // Serial.println("Client available");
    char c = client.read();
    debug(c);
  }
 

  strcpy(Empfangsstring[0][0], ""); // Nach Versenden an NAS löschen
  strcpy(Empfangsstring[2][0], "");
  strcpy(Wertespeicher[0][0], "");
  strcpy(Wertespeicher[2][0], "");
 b = 0; // Zählvariable für wertespeicher zurücksetzen
  d = 0;
}

void loop()
{

  network.update(); // Check the RF24 network regularly
  // delay(50);
  while (network.available()) // Während RF24 Netzwerk vorhanden ist
  {                           // Is there anything ready for us?
    Serial.println("Network available");
    RF24NetworkHeader header;                       // If so, grab it and print it out
    uint16_t payloadSize = network.peek(header);    // Use peek() to get the size of the payload
                                                    // network.read(header, &dataBuffer, payloadSize); // Get the data
    network.read(header, &dataBuffer, payloadSize); // Get the data
    debug("Received packet, size ");                // Print info about received data
    debugln(payloadSize);
    debug("dataBuffer ");
    debugln(dataBuffer);

    // String "Message" zerlegen
    Teilstring = strtok(dataBuffer, ";");
    int i = 0;                 // Zählvariable, um String in Array zu schreiben
    while (Teilstring != NULL) // Pointer darf nicht NULL sein
    {
      Empfangsstring[i][0] = Teilstring;
      printf("Abschnitt %s\n", Teilstring);
      Teilstring = strtok(NULL, ";"); // Nächster Abschnitt erstellen
      i = i + 1;
    }

    // Prüfen, ob Werte in Wertespeicher schon enthalten sind
    int k; //Stringvergleich
    
    for (unsigned int a = 0; a <= sizeof(grArrEmpfangsstring); a = a + 2)
    {
      bool MerkerA; // Merker, ob Zahl im Wertespeicher schon vorhanden
                    //  int posA;     // Position Empfangsspeicher zum kopieren
      for (b = 0; b <= sizeof(grArrWertespeicher); b = b + 2)
      {
        k = strcmp(Empfangsstring[a][0], Wertespeicher[b][0]);
        printf("Vergleich %d\n", k);
       
        if ((k == 0) && (Empfangsstring[a][0] != "")) // Warnung ist Compilerfehler  Wenn Werte gleich und Empfangsspeicher nicht 0, dann soll Wert vorhanden --> MerkerA=true
        {
          MerkerA = true; // Element in Wertespeicher enthalten
          
        }
      } // Ende For-Schleife b

      if ((MerkerA != true) && (Empfangsstring[a][0] != ""))
      {
        Wertespeicher[d][0] = Empfangsstring[a][0];
        
        d = d + 2;
  // For-Schleife für Suche in Wertespeicher verlassen damit Wert nicht mehrfach kopiert wird
      }
      MerkerA = false; // Merker zurücksetzen, nachdem Schleife b durchlaufen wurde;

    } // Endo For-Schleife a

    

    debug("(");
    debug(millis() - timeBetweenPackets);
    debugln("ms since last)");
    timeBetweenPackets = millis();

    // Daten_senden();


  } // Ende While network available

  // Daten regelmässig an Server schicken.
  if (lastWait < millis())
  { // Wenn  Zeit zu letztem Senden an lAN-Server zu lang, dann Daten senden

    Daten_senden(); // Per LAN an Datenbank/NAS schicken
    lastWait += interval;
  }

  // delay(5000);
  if (client.available()) // wenn Daten vom Server gesendet wurden
  {
    // Serial.println("Client available");
    char c = client.read();
    debug(c);
  }
}

das ist aber kein wirklicher Grund die Zwischenergebnisse bereits als string zu halten.

Das kannst du ändern.

erzähl mal:
Nach wie vielen eingelangten neuen Werten schickst du das an den Server weiter?

Schön!
Dann besteht ja Hoffnung, wenn erstmal der Schrott weg geräumt ist, dass was gutes nachwächst.

Das kannst du ändern.

Alles in allem, würde ich dir nahelegen, sich mal ein schönes modernes dickes C++ Grundlagenbuch zuzulegen.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.