TCP Verbindung Daten Anzeigen auf LCD

Hallo

Ich möchte über eine TCP verbindung CHAR Daten einer SPS an einen Arduino LCD anzeigen.
Habe folgendes Problem. Ich sende die Daten an das Arduino und der Char " Hallo" wird im LCd mehrfach angezeigt .
So etwar.


HALLO HAL
HALLO HAL


Hier mal mein Programm

 hat  Server
 
 A simple server that distributes any incoming messages to all
 connected clients.  To use telnet to  your device's IP address and type.
 You can see the client's input in the serial monitor as well.
 Using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Analog inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 */

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

    LiquidCrystal_I2C lcd(0x3F,16,2);

// 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,178, 50);
IPAddress gateway(192,168,178, 1);
IPAddress subnet(255, 255, 255, 0);


// telnet defaults to port 23
EthernetServer server(2500);
boolean alreadyConnected = false; // whether or not the client was connected previously

void setup() {
  
  lcd.init();                      // initialize the lcd 
     
  // Print a message to the LCD.
  
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Starten");
  lcd.setCursor(0,1);
  lcd.print("System");
  delay( 3000);
  lcd.clear();
  
  
  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);
  // start listening for clients
  server.begin();
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Chat server address:");
  Serial.println(Ethernet.localIP());
}

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

  // when the client sends the first byte, say hello:
  if (client) {
    if (!alreadyConnected) {
      // clead out the input buffer:
      client.flush();    
      Serial.println("We have a new client");
      client.println("Hello, client!"); 
      alreadyConnected = true;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("  Verbunden  ");
      delay( 2000);
      lcd.clear();
    } 
    
    if (client.available() > 0) {
      // read the bytes incoming from the client:
      char thisChar = client.read();
      // echo the bytes back to the client:
      server.write(thisChar);
      // echo the bytes to the server as well:
      Serial.write(thisChar);
      lcd.print(thisChar);
      delay( 0);
    }
  }
    if (client.available() < 1) {
      // wait a bit for the entire message to arrive
      delay(1000);
      // clear the screen
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("");
       delay(0);
      lcd.clear();
      
      // read all the available characters
    
    }
  
}

Was muss ich ändern damit der Text im LCD angezeigt wird bis eine neuer Text gesendet wird ? Der Text soll nur einmal angezeigt werden


  • Hallo *

Hat die andere Seite evtl. auch eine echo - Funktion, so wie der Code hier mit

      server.write(thisChar);

Wenn du es nicht genau wesst, entferne doch einfach mal diese Zeile ...

Ausserdem sind die Kommentare

      // wait a bit for the entire message to arrive

und
      // read all the available characters
am Ende für mich eher verwirrend...
Ich verstehe deinen Code so, dass nach 1 Sek. das LCD gelöscht wird, und dann einfach lange genug gewartet wird, bis vermutlich ein ganzer Text da ist, dann wird pro loop Durchlauf ein Zeichen verarbeitet.

Kommen die Sternchen auch vom Client? Oder sollen die nur das Display darstellen ?

Dein lcd(0x3f,16,2) schreibt nach clear() auch ohne lcd.setCursor(0,0) mehrere Zeilen ab (0,0) ???

Was muss ich ändern damit der Text im LCD angezeigt wird bis eine neuer Text gesendet wird

Etwa das was der "verwirrende" Kommentar andeutet ...

Hallo

Das Projekt habe ich von der Standart Lib. Und abgeändert, daher die Komentare.

Das mit dem echo weiß ich nicht so genau. Habe eine S7 an der anderen seite mit einem Baustein der Senden und empfangen kann. Wenn ich in die Empfangsvariablen schaue erhalte ich den selben Text zurück den ich sende.

Ich möchte mit der SPS einen Array senden und dieser Text soll im Arduino Display angezeigt werden.
Die Sterne sollen nur da Display darstellen.

Wie müsste das Programm aussehen damit immer dieser Text angezeigt wird der in meiner SPS Arry steht. sommt würde ich über die SPS entscheiden wann der Text gelöscht oder angezeigt wird ?

Bin in sachen Arduino nicht so fitt.

Hallo
habe es hin bekommen. Jetzt habe ich nur noch folgendes Problem. Ich bekomme die gesendete Nachricht nicht in der richtigen Reihenfolge zurück siehe Bild

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,178, 50);
IPAddress gateway(192,168,178, 1);
IPAddress subnet(255, 255, 255, 0);

EthernetServer server(2500);
boolean alreadyConnected = false;

char thisChar[10];
int i;

void setup() {

lcd.init();

lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Starten");
lcd.setCursor(0,1);
lcd.print("System");
delay( 3000);
lcd.clear();

// initialize the ethernet device
Ethernet.begin(mac, ip, gateway, subnet);
// start listening for clients
server.begin();
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

Serial.print("Chat server address:");
Serial.println(Ethernet.localIP());
}

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

// when the client sends the first byte, say hello:
if (client) {
if (!alreadyConnected) {
// clead out the input buffer:
client.flush();
Serial.println("We have a new client");
client.println("Verbunden");
alreadyConnected = true;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Verbunden ");
delay( 5000);
lcd.clear();

}

if (client.available() > 0) {
for (i = 0; i < 11; i++) {
// read the bytes incoming from the client:
thisChar = client.read();

  • }*
  • // echo the bytes back to the client:*
  • server.write(thisChar);*
  • // echo the bytes to the server as well:*
  • Serial.write(thisChar);*
  • lcd.clear();*
  • lcd.print(thisChar);*
  • delay( 100);*
  • }*
  • }*

}
SPS DB
Hallo Welt.JPG

Die Sterne sollen nur da Display darstellen.

OK, also ein 20*2 Display:

************************
*HALLO            HAL*
*HALLO            HAL*
************************

Oder doch eher 16*2 ?

LiquidCrystal_I2C lcd(0x3F,16,2);

Habe eine S7 an der anderen seite mit einem Baustein der Senden und empfangen kann

Wie oft sendet der ?
Und woran soll der Arduino erkennen, dass ein neuer Text kommt ?

Am einfachsten, und wenn du die SPS auch im Griff hast, definiere doch Sonderzeichen für Text-Anfang (und/oder Text-Ende).
Dann brauchst du gar keine delay() in deiner loop() Funktion:

z.B. Text-Anfang = '>' :
Wenn kein Zeichen kommt, ist loop schon fertig, sonst:
Wenn ein '>' kommt, wird das lcd gelöscht und auf (0,0) gesetzt.
Jedes andere Zeichen wird wie bisher: ausgegeben, zurückgesendet und auf Serial protokolliert.

Jetzt du, dieses Programm in C. :wink:

Das Drumherum scheint ja zu funktionieren, auch wenn ich nicht sehe, wann alreadyConnected jemals wieder zurücksesetzt wird. Das soll wohl erlauben, dass erst der Arduino startet, und irgendwann später die TCP-Verbindung kommt...
aber nach einer Unterbrechung das ganze wieder zu verbinden ohne Reset, geht eher (noch) nicht.

und

 Serial.begin(9600);
   while (!Serial) { }

verstehe ich auch nicht ganz. Hat da jemand für das Serial Objekt den ! Operator umdefiniert oder ist das nur ein NOP - Befehl ???
Entschuldigung, emilio, lass dich da nicht verwirren. Wenn's geht, lass es halt wie es ist.

Deine neue Version hat den kleinen Nachteil, dass du auf jeden Fall 11 Zeichen liest, egal wie viele da sind, ( mehr oder weniger ?),
und alle Zeichen an die gleiche Stelle schreibst, noch dazu in ein char[] statt ein char ( kein Syntaxfehler ?! , schreib das ganze mal in

 Tags )

[code]int i=0;
while (client.available() && i < 11) { thisChar[ i++ ] = client.read() ; }

[/code]

Hallo

ich Sende mit der SPS einen Array of Cahr[11] jede sec. Ob das so richtig ist weiß ich nicht.

Aktuell wird immer der Inhalt der Variable zum Arduino gesendet. Wenn sich in der SPS der CHAR ändert wird er auch am Arduino angezeigt.

Wenn ich nur Senden soll wenn sich was ändert muss ich auch men SPS Programm anpassen ?.

Ich schreibe doch den inhalt der gesendeten Variable in ein Char und gebe diesen auf dem Display wieder

Aktuell funktioniert es ob es. Wie macht man es richtig ? Sendet mann nur wenn sich was ändert ?

Kannst du mal die Zeihle erklären ? Die verstehe ich garnicht
while (client.available() && i < 11) { thisChar[ i++ ] = client.read() ; }

Wie macht man es richtig ? Sendet mann nur wenn sich was ändert ?

Das kann man schon machen wie man will, 10 Buchstaben / sec ist nichts was man optimieren müsste.

Kannst du mal die Zeihle erklären ? Die verstehe ich garnicht
while (client.available() && i < 11) { thisChar[ i++ ] = client.read() ; }

Tschuldigung, besser so ? :

char thisChar[11]; // Platz für 10 Buchstaben + Endekennung
int i = 0; // akt. Position in thisChar

while (client.available()    // solange ein Zeichen vorhanden ist
              &&   ( i < 11)     )  // aber max. 10
{ 
    thisChar[ i] = client.read() ;  // schreibe das Zeichen in den string thisChar
    i++; 
}
// jetzt sind alle Zeichen gelesen
thisChar[i] = 0; // C - EndeKennung für char thisChar[], 
Serial.println(thisChar); // gibt den ganzen Text aus

Hallo

Ich habe ja von der SPS einen data[0...11]Array of CHAR gesendent. Hat auch soweit funktioniert.

Jetzt versuche ich einen kompletten String[11] zu schicken. Habe deine änderung mit einfließen lasse. Es funktioniert aber noch nicht richtig. Kann mann überhaubt einen String schicken ?

Hallo
Ich bin dank deiner Hilfe schon ein ganzes Stück weiter gekommen.
Habe jetzt folgendes gemacht. Ich schicken mit der SPS eine kompletten String Text[16] an das Arduino. Auf dem Display wird ein lehrzeichen eine komisches Symbol und der Text Hallo.
Lasse ich die ersten 2 Byte beim Senden weg, wird nur der Text angezeigt.

Ich habe irgent wo gelesen das die ersten Bytes die länge des Strings angeben. Wenn ich diese Zahl nutzen könnte , könnte ich sie gegen die Variable austausche die die Göße meines Strings im Arduino angibt. Somit könnte ich einen Text jeder länge senden. Weiterhin müsste ich die ersten 2 bayt im display ausschneiden. Wie würde sowas gehen ?

Ich habe irgent wo gelesen das die ersten Bytes die länge des Strings angeben. Wenn ich diese Zahl nutzen könnte , könnte ich sie gegen die Variable austausche die die Göße meines Strings im Arduino angibt. Somit könnte ich einen Text jeder länge senden. Weiterhin müsste ich die ersten 2 bayt im display ausschneiden. Wie würde sowas gehen ?

Da ist wohl ein S7 String was anderes als in C.

char text[10] = "hallo"; // belegt 10 Byte, hat an Position 0 ein 'h' und an Position 5 eine 0. 
// text[6] ist vom Inhalt her undefiniert, kann aber genutzt werden.
Serial.print(text);  // gibt den text bis zur 0 aus, also 5 Buchstaben

Und was über die Leitung geht, müsste man genau anschauen.
Das "komische Symbol" kann natürlich ein Teil der Längen-Information sein.

void loop()
{
    if (!alreadyConnected) {
      // connect etc. ..., aber noch kein client.read()
      // ...
    }

    if ( client.available() ) 
    {
       int c = client.read();
       Serial.print(c); // als Dezimalzahl
       Serial.print( " = ' " );
       Serial.write( (char) c ); // als Zeichen wie gelesen
       Serial.println(" ' "); 
    }
}

Das sollte dir genau anzeigen, was ankommt.

"Beliebig lange Texte" verarbeitest du am besten gleich, Zeichen für Zeichen, ohne erst alle zwischenzuspeichern.

Hallo
Ist genau wie erwartet . erster.Byte Länge des String 16, zweiter.Byte Anzahl der Zeichen 5.

Wie kann ich dies jetzt nutzen ?

Ich möchte im LCD nur den Text Anzeigen. Benötige ich die anzahl der Zeichen 5 für einen Array ? oder kann ich einen x belibig großen String verwenden?
Ich woll eigentlich nur die 2 Zeilen des Display nutzen. Habe gedacht ich schicke einen String mit 32 Zeichen , die ersten 16 werden im oberen teil des LCD angezeigt und die weitern 16 im unteren Teil. Oder wäre es besser 2 Strings mit je 16 Zeichen zu senden? Die frage ist nur wie ordne ich das zu ? woher weiß ich was was ist ?

woher weiß ich was was ist ?

Genau :wink:

2+32 Zeichen je Sekunde sind nicht die Welt, mach's dir einfach...

erster.Byte Länge des String 16, zweiter.Byte Anzahl der Zeichen 5

verstehe ich nicht... Was ist der Unterschied zwischen der Länge eines String und der Anzahl der Zeichen ?
Werden immer 16 Zeichen gesendet, aber nur 5 sind "gültig" ???
also: "hallo\0\0\0\0\0\0\0\0\0\0\0" oder gar irgend was undefiniertes nach den 5 Zeichen ???

Das wird gedenden

Ist bei einer S7 so Das erst die Läng desStrings und dan die benutztn Zeichen angegeben werden . Siehe Bild.

Hallo
Ist genau wie erwartet . erster.Byte Länge des String 16, zweiter.Byte Anzahl der Zeichen 5.

Wie kann ich dies jetzt nutzen ?

Ich möchte im LCD nur den Text Anzeigen. Benötige ich die anzahl der Zeichen 5 für einen Array ? oder kann ich einen x belibig großen String verwenden?
Ich woll eigentlich nur die 2 Zeilen des Display nutzen. Habe gedacht ich schicke einen String mit 32 Zeichen , die ersten 16 werden im oberen teil des LCD angezeigt und die weitern 16 im unteren Teil. Oder wäre es besser 2 Strings mit je 16 Zeichen zu senden? Die frage ist nur wie ordne ich das zu ? woher weiß ich was was ist ?

Wie kann ich dies jetzt nutzen ?

2+32 Zeichen je Sekunde sind nicht die Welt, mach's dir einfach, sende doch einfach jedes Mal 32 Zeichen von der S7.

Die ersten 2 Byte müssten dann jeweils eine 32 = ' ' sein, die du einfach ignorierst.
Oder machst du den Arduino so "schlau", dass er auch kürzere Texte kann: Der Rest des Displays wird mit Leerzeichen aufgefüllt

    if ( client.available() ) 
    {
       byte len = client.read(); // Gesamt-Länge: Ignorieren
       delay(1); // evtl. Warten, bis alles gesendet ist ???
       len = client.read(); // Netto - Länge im 2. byte
       lcd.setCursor(0,0);
        byte pos = 0;
       while ( client.available() ) 
        { 
             char c = client.read();
             if (pos < len) lcd.write(c);
             else lcd.write(' '); // mit Leerzeichen auffüllen
             pos++;
        }
        while (pos++ < 32) 
        { 
             lcd.write(' ');  // Rest löschen, wenn Gesamt-Länge < 32
        } 
    }   // Ende von if ( available() )