# Daten aus einer Seriellen Schnittstelle  empfangen



## Dana (4. Jul 2007)

Hallo Freunde,

ich versuche aus einer seriellen Schnittstelle Daten zu empfangen. 
Ich habe im Netz den unteren Code gefunden. 
Es funktioniert außer, dass am Enden des Codes einpaar komische Rechtecke stehen. Wieso ?
Und beim byte[] readBuffer = new byte[8]; warum gerade 8 ? 

Vielen Dank im Voraus



```
public void Test(MyFrame frame)
{
   
   try{portId = CommPortIdentifier.getPortIdentifier("COM2");
        serialPort = (SerialPort) portId.open("",1000);
    }
    catch(Exception exc){System.out.println("Fehler1 :"+exc);}
    
    try {
         is = serialPort.getInputStream();
         serialPort.addEventListener(new commListener());
       }
      catch (Exception e) { System.out.println("Fehler2: "+e);}
      
     serialPort.notifyOnDataAvailable(true);
      try {serialPort.setSerialPortParams(9600,
                                SerialPort.DATABITS_8,
                                SerialPort.STOPBITS_1 ,
                                SerialPort.PARITY_NONE);}
 catch (UnsupportedCommOperationException e) {}
 
   
}
      public class commListener implements SerialPortEventListener{
          public void serialEvent(SerialPortEvent event) {
            if(event.getEventType()==SerialPortEvent.DATA_AVAILABLE){
              byte[] readBuffer = new byte[8];
              try {
                while (is.available() > 0) 
                {
                  int numBytes = is.read(readBuffer);
                }
                String nachricht = new String(readBuffer);
                frame.TextCode.append(nachricht);
                 
              }
              catch (IOException e)
              {
                System.out.println("Fehler3: "+e);
              }
            }
          }
        }



}
```


----------



## tuxedo (4. Jul 2007)

Naja, 8... einfach so halt.. Es werden möglichst immer 8 Zeichen gelesen... Die "seltsamen" Rechtecke sind nicht darstellbare Sonderzeichen. Du kannst ja mal den Integer-Wert der rechtecke ausgeben lassen und in einer Ascii-Tabelle nachschlagen was das für Zeichen sind. Aber ich Tippe mal auf CR (Wagenrücklauf) und LF (Zeilenumbruch). 

BTW: Von was für einer Quelle liest du zeichen ein?


----------



## Dana (4. Jul 2007)

Aus einer Textdatei


----------



## tuxedo (4. Jul 2007)

?? Du liest doch von der seriellen Schnittstelle... 
Meine Frage war: Was ist da die Quelle der Daten? 

GPS-Empfänger, Heizungssteuerung XY, Receiver YZ, ...

Sowas in der Art hab ich erwartet.. Schließlich kann man keine Textdatei an eine serielle Schnittstelle anschließen...  Oder gibts jetzt Textdateien mit RS232-Schnittstelle *jokingly*

Nochmal zum Read-Buffer: Den kannst du nach belieben wählen. Machst du ihn größer wird mehr pro Durchgang gelesen. Machst du ihn kleiner wird weniger gelesen. Ist halt ein Puffer den du "frei" wählen kannst.

- Alex


----------



## Dana (4. Jul 2007)

in der Textdatei habe ich
1
2
3
A
B

geschrieben. Die Buchstaben und die Ziffern werden alle angezeigt, aber am Ende kommen sechs Rechtecke. Ich habe in der Textdatei geschaut da ist nix hinter der letzter Buchstabe


----------



## Dana (4. Jul 2007)

Sorry habe nicht verstanden. Es handelt sich um eine CNCmaschiene


----------



## tuxedo (4. Jul 2007)

Wenn du die Textdatei aufmachst: Siehst du dann den Zeilenumbruch als Zeichen? Nein. Du siehst nur dass ein neuer Buchstabe/Zahl in einer neuen Zeile steht. Der Texteditor hat "intern" quasi auch solche "Rechtecke". Nur weiß der Texteditor dass er daraus einen Zeilenumbruch etc. machen muss.

Du kannst jetzt folgendes machen:

1) Du lässt dir den Integer-Wert der Rechtecke ausgeben und schlägst in einer ASCII-Tabelle nach was das für zeichen sind.

2) Du schreibst (write(byte[] byte) das, was dein Programm von der seriellen Schnittstelle ließt per Java in eine Datei und öffnest diese nachher mit einem Texteditor. Die Datei sollte, wenn du alles richtig gemacht hast, wieder so aussehen wie am Anfang.


- Alex


----------



## Dana (4. Jul 2007)

Erst mal danke für deine mühe. (Ah ja.. D.h. du hast ein Programm das auf der seriellen Schnittstelle sendet (Hyperterminal, ein Java-Tool oder was in der Art), und auf einem anderen PC ein zweites Programm das empfängt. Und dazwischen hängt ein Null-Modem-Kabel, oder?) 
Richtig es ist genau so.

Die Rechtecke können mit der Textdatei nicht zu tun habe, denn wenn ich die 
byte[] readBuffer = new byte[8]; von acht auf z.B. 10 oder 13 Umstelle dann werden die Rechtecke viel mehr


----------



## Dana (4. Jul 2007)

Ich habe in der Textdatei nur
1 
geschrieben, trotzdem kommt ein Rechteck


----------



## tuxedo (4. Jul 2007)

Tu uns beiden den gefallen und lass die Integer-Werte der Rechtecke ausgeben und dann poste die hier bitte.

Wie gesagt: In einem Texteditor wird nicht alles als Zeichen angezeigt was da auch wirklich drin ist. 
Wenn du vorher bei 5 Zeilen 6 Rechtecke hattest heißt das für mich: Pro Zeile eine Rechteck für Zeilenumbruch und abschließend eins für's Ende der Datei, oder sowas in der Art.

Wir können aber noch lange rumrätseln was das für Zeichen sind, solange du nicht den Integer-Wert der Zeichen auswertest.

- Alex


----------



## Dana (4. Jul 2007)

ohh wie geht das(Wert als Integer ausgeben), sorrrrry ich bin neu


----------



## tuxedo (4. Jul 2007)

Hier ein wenig Beispielcode.


```
// Pufferinhalt zeilenweise als Integer ausgeben
        for (int i=0; i<readBuffer.length;i++){
            System.out.println((int)buffer[i]);
        }
```

Solltest du in deinem Beispielcode nach Zeile 33 einbauen. Also nachdem der readBuffer befüllt wurde...


----------



## Guest (4. Jul 2007)

Das Kästchen ist ein Zeilenumbruch... Ziemlich sicher...


----------



## tuxedo (4. Jul 2007)

Anonymous hat gesagt.:
			
		

> Das Kästchen ist ein Zeilenumbruch... Ziemlich sicher...



Muss nicht unbedingt ein Zeilenumbruch sein. Wenn in der Textfile nur eine Zeile existiert kanns tatsächlich auch was anderes sein. Ein EOF-Zeichen oder sowas...


----------



## Dana (11. Jul 2007)

Ich habe in der Textdatei Hallo geschrieben
das Programm gibt die Zahlen aus
Die Zahlen  104

97
108
108
111
0
0
0
d.h. die Drei Null sind zuviel. Woran liegt es bitte ?


----------



## Dana (11. Jul 2007)

Hallo hat 5 Buchstaben und das Programm gibt 8 Zahlen raus, weil in der Zeile 28 
byte[] readBuffer = new byte[8]; steht, oder ?? wenn ja, wie kann ich diese Array die richtige Länger der Zeile übergeben??


----------



## Dana (11. Jul 2007)

Hallo hat 5 Buchstaben und das Programm gibt 8 Zahlen raus, weil in der Zeile 28 
byte[] readBuffer = new byte[8]; steht, oder ?? wenn ja, wie kann ich diese Array die richtige Länger der Zeile übergeben??


----------



## tuxedo (11. Jul 2007)

Der Ascii-Wert "0" ist kein Zeichen aus dem herkömmlichen Alphabet. 

Tauchen _immer_ drei Nullen auf? Sprich: Tauchen die bei jeder Antwort der CNC-Maschine am Ende auf? 

Wenn ja dann ist das eine eigenart der Maschine. Normalerweise sind solche Sachen auch in einem Handbuch spezifiziert. 

Vielleicht hilft es auch weiter wenn du "erklärst" was du genau machen willst. Macht ja an sich wenig Sinn an der CNC-Maschine eine Textdatei mit Inhalt "Hallo" via serieller Schnittstelle an einen PC zu senden. Geht's vielleicht drum ein CNC-Programm von der Maschine zum PC zu übertragen und vllt. auch wieder zurück?

Würde definitv mal das Handbuch nach Infos und Angaben zur seriellen Schnittstelle durchsuchen. Weil ein Java-Seitiger "Fehler" ist das mit 99,9999998%iger Wahrscheinlichkeit nicht. 

- Alex

P.S. Hier mal ne Ascii-Tabelle. Da kannst du die Zahlencodes auch selbst nachschlagen:


----------



## tuxedo (11. Jul 2007)

Okay, du warst schneller als ich ....

jo, du kannst den Puffer auch verkleiner. Stell ihn mal stat 8 auf 1 ein ...

Hab da noch ne Idee.. momentchen ...

[update]

So... jetzt...


```
byte[] readBuffer = new byte[8]; 
              try { 
                while (is.available() > 0) 
                { 
                  int numBytes = is.read(readBuffer); 
                } 
                String nachricht = new String(readBuffer); 
                frame.TextCode.append(nachricht); 
                  
              }
```

Du hast also den Puffer auf 8... ABER beim lesen merkst du dir die anzahl der gelesenen Zeichen in "numBytes"...

Dieser Wert sollte, wenn nur "Hallo" übertragen wird, eigentlich 5 betragen. Damit kannst du den Puffer im nachinein entsprechend "kürzen". Vorher geht das nicht. Du weißt ja nicht wieviele Zeichen du empfängst... Und den Puffer auf 1 runterschrauben ist keine gute Idee.

Prüf das mal mit dem "numBytes"...

- Alex


----------



## Dana (12. Jul 2007)

Erstmal vielen Dank für eure Mühe, besonders du Alex.


> Geht's vielleicht drum ein CNC-Programm von der Maschine zum PC zu übertragen und vllt. auch wieder zurück?


Genau so ist es.

Es ist was „für mich unerklärliches “ passiert. An der Zeile 35 meine Codes steht 
frame.TextCode.append(nachricht);
TextCode ist eine JTextArea gewesen und habe sie in TextArea  umgewandelt. Die Rechtecke werden nicht mehr angezeigt, bzw. der Text wird genauso übertragen wie er geschrieben ist. Könntet ihr das verstehen?? Macht es einen Unterschied??
MfG


----------



## tuxedo (12. Jul 2007)

Argh. Du solltest Swing (Die J-Klassen, z.b. "JTextArea"), nicht mit AWT-Klassen (ohne J am Anfang, z.B. "TextArea") nicht mischen. Das führt früher oder später unweigerlich zu Problemen.

Das was du da "versuchst" ist keine Lösung des Problem. Das ist nur ein "dirty Work-Around". Du bekämpfst die Symptome, nicht aber die Ursache.

Ich vermute die Sonderzeichen werden deshlab im "TextArea" nicht mehr angezeigt weil da drin einfach keine Sonderzeichen angezeigt werden können.. Wie gesagt, habs nicht probiert, ich vermute es.

Du wandelst ja irgendwann deinen byte[]-Puffer in einen String um... 


```
String nachricht = new String(readBuffer);
```

Du solltest hier jedoch prüfen ob du den Puffer beim lesen vollmachen konntest, oder ob noch leere Stellen drin sind. Das kannst du wie gesagt über "numBytes", welches du hier bekommst:


```
while (is.available() > 0) { 
   int numBytes = is.read(readBuffer); 
}
/* erst hier wird der Puffer weiter verarbeitet */
```

Du liest bisher solange Daten wie welche anliegen, und füllst damit den Puffer. Was machst du wenn der Puffer voll ist?

Ein Beispiel:
Gehen wir wieder von einer Puffergröße von 8 aus. Und die Maschine sendet 10 Zeichen...
Nehmen wir mal an das wäre folgender String:

"abcdefghij"

Beim ersten lesen wird der Puffer mit "abcdefgh" gefüllt und ist voll. Die Bedingung der While-Schleife ist aber noch "true". Es liegen ja noch 2 Zeichen an, nämlich i und j.  Der Puffer wird also erneut benutzt. Der bisherige Inhalt von readBuffer wird weggeworfen und durch "ij" ersetzt. Die letzten 6 Zeichen, die im Puffer dann noch übrig sind, dürften wieder diese Sonderzeichen sein. 

Du solltest also sowas hier machen:


```
while (is.available() > 0) { 
   int numBytes = is.read(readBuffer); 
   String nachricht = new String(readBuffer,0,numBytes);
   /* mache hier was mit "nachricht" */
}
```

Zum einen nimmst du nur soviel aus dem Puffer raus wie auch drin steht, und zum anderen werden Teile der ankommenden Information, die nicht auf einmal in den Puffer passe nicht weggeworfen, sondern gleich verarbeitet, bevor sie weggeworfen werden.

- Alex

P.S.



			
				Dana hat gesagt.:
			
		

> Die Rechtecke werden nicht mehr angezeigt, bzw. der Text wird genauso übertragen wie er geschrieben ist.



Du hast da was falsch verstanden: Die Rechtecke sind nicht Teil der Übertragung. Die Rechtecke sind leere Plätze im Puffer. Wenn der Puffer 8 groß ist und du nur 5 zeichen reinschreibst, hast du 3 leere Stellen. Und das sind deine Rechtecke.
Die Übertragung ist also nach wie vor die gleiche. Nur zeigt TextArea scheinbar keine Sonderzeichen an...


----------



## Dana (12. Jul 2007)

Suuuuuper es hat mit der Ergänzung


```
while (is.available() > 0) 
       {
         int numBytes = is.read(readBuffer);
          String nachricht = new String(readBuffer,0,numBytes); 
           frame.PCode.append(nachricht);
       }
```

Funktioniert. Es spielt jetzt keine Rolle mehr, wie lang mein  Buffer ist, oder ?

Vielen Dank  Alex


----------



## tuxedo (12. Jul 2007)

Naja, die Puffergröße ist eine Frage der Datenmenge. 
Funktionieren tuts jetzt immer. Ob du jetzt 1 oder 1024 einstellst. 
Aber wenn du Megabyteweise Daten durchschaufelst, ist es sinnvoller keine allzukleinen blöcke (z.B. puffergröße 1) zu lesen. 

Denn dann wird für jedes einzelne Byte das hier aufgerufen:


```
int numBytes = is.read(readBuffer);
```

Ist der Puffer also 1 groß und du willst 1 Megabyte übertragen, wird etwa 1 Million mal is.read() aufgerufen.
Ist der Puffer größer als 1, z.B. 512, dann wird die Methode nur knapp etwa 2000 mal aufgerufen.

Du merkst: 500 mal mehr die is.read() Methode aufrufen dauert dann auch länger... 

Musst dir also überlgen wieviele Daten du senden und Empfangen willst, und dann den Puffer einstellen. 

- Alex


----------

