Ports über Ethernet schalten

Hallo zusammen,
zuerst einmal danke für die vielen hilfreichen Beiträge. Ich lese das Forum schon seit ein paar Tagen und finde dort immer wieder nützliche Einträge.

Leider bin ich auf dem Gebiet des C-Programmierens ein totaler Anfänger.
Ich hoffe, dass ihr mein folgendes Problem versteht und mir helfen könnt:

Ich möchte gerne das Beispiel Chatserver dazu nutzen um über Ethernet einen Ausgang des Arduino Mega zu schalten.
Die Übertragung klappt. Allerdings schreibt der Code den ersten übermittelten Char auf Stelle 0 meines Arrays und danach alle weiteren Chars immer auf Stelle [1], statt das Array bis zum Schluss zu befüllen.

Hier mal der Code:

#include <SPI.h>
#include <Ethernet.h>
#include <String.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 200);
IPAddress myDns(192,168,1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);


// telnet defaults to port 23
EthernetServer server(23);
boolean alreadyConnected = false; // whether or not the client was connected previously
char nachricht[] ="";
int iterationsvariable = 0;
char thisChar;

void setup() {
  // initialize the ethernet device
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
  // start listening for clients
  server.begin();
  pinMode(3, OUTPUT);
  

}

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();

  // when the client sends the first byte, say hello:
  if (client) {
    if (!alreadyConnected) {
      // clear out the input buffer:
      client.flush();
      alreadyConnected = true;
     
    }
    iterationsvariable = 0;
    while (client.available() > 0) {
      
      thisChar = client.read();
      nachricht[iterationsvariable] = thisChar;
      iterationsvariable ++;
      //server.write((iterationsvariable +48));
      
    }
      server.write(nachricht[0]);
      server.write(nachricht[1]);
      server.write(nachricht[2]);
      server.write(nachricht[3]);
    if (strstr(nachricht,"AUS")!= 0) {
        digitalWrite(3, LOW);
        memset(nachricht, '\0', sizeof(nachricht));
        server.write("AUS");
        
      }
    if (strstr(nachricht,"EIN")!= 0) {
        digitalWrite(3, HIGH);
        memset(nachricht, '\0', sizeof(nachricht));
        server.write("EIN");
      }
  }
}

Der interessante Part ist der hier:

iterationsvariable = 0;
    while (client.available() > 0) {
      
      thisChar = client.read();
      nachricht[iterationsvariable] = thisChar;
      iterationsvariable ++;
      //server.write((iterationsvariable +48));
      
    }

Vielen Dank für eure Hilfe

angry:
Der interessante Part ist der hier: …

Ich habe das jetzt dreimal gelesen, ohne einen Fehler zu entdecken. Entweder habe ich Tomaten auf den Augen oder die Ursache des Fehlverhaltens versteckt sich anderswo.

Als ich mit C/C++ begonnen habe, habe ich einmal den Fehler in so einer Zeile gesucht:

for(float value=0.0; value < PI; value=value+0.01)

Die Zeile sieht perfekt aus und das ist sie auch. Der Fehler versteckte sich in der Definition von PI, die sah nämlich so aus:

#define PI 3.1415;

Das Semikolon ist dort vollkommen daneben.

Ich habe den anderen Teil Deines Codes nicht gelesen. Ich gehe davon aus, dass das Fehlverhalten Deines Programms eine vergleichbar dämliche Ursache hat. Merke: Ursache eines Fehlers und dessen Auftreten können beliebig weit auseinander liegen.

Gruß

Gregor

Erstaunlich, dass du in deinem Array der Länge eins mehrere Zeichen unterbringen willst.

char nachricht[] ="";

Wie wäre es mit einem längeren Array und einem Test um ein Überschreiten des Arrays zu verhindern?

Hallo zusammen,

danke für die Hilfe. Es lag wirklich an der Deklaration des Arrays...

Ich dachte, dass diese Zeile: char nachricht[] =""; ein leeres Array erstellt...

Grundlagen C sind was Tolles...

Array ordentlich initialisiert und schon läuft alles. char nachricht[5];

angry: Ich möchte gerne das Beispiel Chatserver dazu nutzen um über Ethernet einen Ausgang des Arduino Mega zu schalten.

Echt jetzt, Du möchtest zum Schalten der Ausgänge immer einen Textmode Telnet-Client starten und über das Senden von Textbefehlen schalten?

Die meisten wollen wohl lieber einen Webbrowser zur Bedienung verwenden und programmieren sich einen HTTP-Webserver auf dem Arduino.

Aber Du nicht?

Du stehst auf Telnet über Port-23 und Textmode statt HTTP über Port-80 und Webbrowser?

Du stehst auf Telnet über Port-23 und Textmode statt HTTP über Port-80 und Webbrowser?

Naja... Es gibt schon einige Gründe, etwas schlankeres, als das HTTP zu verwenden.

Man sollte vor dem Schreiben immer prüfen ob man noch auf gültigen Speicher zugreift. Es kann auch auch mal vorkommen dass mehr gesendet wird.

Mein üblicher Serial Code um C Strings bis zu einem Linefeed einzulesen sollte auch mit Ethernet funktionieren: https://forum.arduino.cc/index.php?topic=406574.msg2796932#msg2796932

Ich habe den neuen Code nicht mehr gepostet. Ich überprüfe in der Whileschleife VOR dem schreiben ins Arrayfeld, dass das Array noch nicht voll ist.

Danke trotzdem für den Hinweis.

Ich will später mit verschiedenen Geräten auf den Arduino zugreifen. unter anderem auch mit einer SPS. Die Geräte sollen einfach nur ein paar neoPixel über den Arduino ansteuern. Deshalb ohne Webserver...

Ich bin einfach eine Niete mit den Chararrays...

Hier noch eine Frage:

Ich möchte gerne einen mit Trennzeichen versehenen String übertragen (klappt schon) und die Teile zwischen den Trennzeichen auswerten. Ich habe es nun so versucht, aber ich stehe auf dem Schlauch, wie ich die Teilstrings und nicht nur das erste Char bekomme.

 ptr = strtok(nachricht,"-");
// Erstes Zeichen zeichen[0]
    zeichen[0] = ptr;
       
    iterationsvariable = 1;
    while(ptr != NULL) {
        ptr = strtok(NULL, "-");
        zeichen[iterationsvariable] = ptr;
        iterationsvariable ++;
        
    }


    ledNummer = int(*zeichen[0]);
    ledFarbeR  = int(*zeichen[1]);
    ledFarbeG  = int(*zeichen[2]);
    ledFarbeB  = int(*zeichen[3]);
    einOderAus = int(*zeichen[4]);

ich müsste es eigentlich in ein char-array speichern, aber ich komme nicht drauf wie ich es machen soll...

Ergebnis ist, ich übertrage "3-255-255-255-1" (3. LED in weiß einschalten) und in meinen Integern steht: ledNummer = 3 ledFarbeR = 2 ledFarbeG = 2 ledFarbeB = 2 einOderAus = 1 (eben immer nur das erste Char)

Danke für eure Hilfe

Deine Konvertierung ist völlig falsch und unsinnig. Ein einfacher Cast mit nur einem Zeichen reicht da nicht.

Wenn du immer die gleiche Anzahl an Teil-String überträgst kannst du sowas machen:

int value1 = atoi(strtok(nachricht, "-"));
int value2 = atoi(strtok(NULL, "-"));
int value3 = atoi(strtok(NULL, "-"));
int value4 = atoi(strtok(NULL "-"));

atoi = ascii to integer. Schau dir Standard C Konvertierungs-Funktionen an. Das ist auf dem Arduino auch nicht viel anders als auf dem PC. Oder die avr libc Doku (wobei die Funktionen auf anderen Seiten besser erklärt sind): http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html

strtok() in einer Schleife ist eher wenn man eine unbekannte Anzahl ein Teil-Strings hat. Geht aber so oder so. Das einfachste ist wenn man das Ergebnis dann auch in ein Array schreibt (statt einzelne Variablen). Dann geht es in einem Schritt.

angry:
Ich bin einfach eine Niete mit den Chararrays…

Mach’ Dir nichts draus. Als ich mit C/C++ anfing, bin ich ständig gegen Mauern gerannt. Gute Flüche helfen sehr :slight_smile: Eine Gummizelle ist auch nicht zu verachten :-))

Gruß

Gregor

PS: Vermutlich hilft Dir das hier.

Danke für die schnellen Antworten.

Ich werde es morgen früh mal in Ruhe ausprobieren. Melde mich dann :)

Danke

angry: Melde mich dann :)

Wenn es klappt, kannst Du einen ausgeben. Oder Karmapunkte verteilen :-)

Gruß

Gregor

Musste es ja doch noch testen...

Danke, klappt

(Karmapunkte sind raus ;) )