Forum: PC-Programmierung Java Com lesen und schreiben


von Pfeiffy (Gast)


Lesenswert?

Hallo,

ich habe ein Programm für meinen Atmega8 geschrieben, der gibt mit, wenn 
ich ein 's' sende den ADC-Wert zurück - soweit geht dies im 
Hyperterminal.
Jetzt möchte ich dies jedoch in Java implementieren, um hier eine 
Temperatursteuerung zu bauen, jedoch weiss ich nicht, wie ich in Java 
gleichzeitig senden und empfangen kann?, ich denke hintereinander kann 
ich dies nicht machen?

Gruß
Pfeiffy

von Nicht Gast (Gast)


Lesenswert?

Wenn Pfeiffy die Suche benutzt hätte, wäre ihm bestimmt ein Artikel dazu 
aufgefallen.

von U.R. Schmitt (Gast)


Lesenswert?

Wenn Du in Java etwas gleichzeitig machen willst ist die Klasse "Thread" 
dein Freund.
Alternativ kann man in einer Klasse das Interface "Runnable" 
implementieren.
Gute Onlinedoku über Java findet sich unter "Java ist auch eine Insel". 
Das ist ein Onlinebuch, das man sich auch runterladen kann.
Ausseredem solltest Du immer die Onlinereferenz der Java API offen 
haben.
Serielle Programmierung habe ich in Java noch nicht gemacht, da brauchts 
dann Rechner/Betriebssystemspezifische Module. Sollte aber kein 
hexenwerk sein, Google hilft da bestimmt weiter.
Bei Fragen : Hier rein posten

von Pfeiffy (Gast)


Lesenswert?

Hallo,

ja, suche - so einfach ist es auch nicht, habe ich gerade gemacht. Das 
problem ist, dass ich in Java praktisch gleichzeitig senden und 
Empfangen muss, das mache ich klar in einem Thread, aber der Comport ist 
eben beim senden dann durch das empfangen gesperrt - das ist die Frage.

Gruß
Pfeiffy

von MB (Gast)


Lesenswert?

Versuch mal die rxtx.org

Dort gibts libs für den com Port anzusprechen.

von Pfeiffy (Gast)


Lesenswert?

Hallo,
ich denke das mit der rxtx.org ist eine gute Idee, werds heute Abend 
zuhause gleich probieren.

Gruß
Pfeiffy

von U.R. Schmitt (Gast)


Lesenswert?

Pfeiffy schrieb:
> Das
> problem ist, dass ich in Java praktisch gleichzeitig senden und
> Empfangen muss,

Das sehe ich so noch nicht. Nur weil Du

Pfeiffy schrieb:
> der gibt mit, wenn
> ich ein 's' sende den ADC-Wert zurück

ein Zeichen schreibst und dann 2 Byte empfangen willst, brauchst du 
keine 2 Threads und gleichzeitiges schreiben und lesen.
Alleine die Hardware hat im PC schon 16 Byte Puffer, die Treiber werden 
das noch etwas vergrößern.
Wenn Dein Protokoll also nicht deutlich komplexer wird, würde ich mir 
das Multithreading an der Stelle sparen.

von Pfeiffy (Gast)


Lesenswert?

Hallo,
ok, com in Java war bis jetzt noch nicht so meine Welt, kannst du mir 
sagen, mit was für einem Befehl ich das mache?, das schreiben - worauf 
ich ja die 2 byte erwarte ist der Befehl:
1
outputStream.write("S".getBytes());

Gruß
Pfeiffy

von Bernd K. (bem) Benutzerseite


Lesenswert?

Also, das einlesen machst du am besten eventbasiert mit einem 
SerialPortEventListener.
Hier mal ein funktionsfähiges Quick&Dirty Beispiel:
1
public class SeriellTest implements SerialPortEventListener {
2
3
    private CommPortIdentifier portID;
4
    private SerialPort serport;
5
    private InputStream inputStream;
6
    private OutputStream outputStream;
7
8
    public SeriellTest() {
9
        try {
10
            portID = CommPortIdentifier.getPortIdentifier("COM1"); //oder /dev/ttyS0
11
            serport = (SerialPort) portID.open("foobar", 2000);
12
            serport.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
13
            inputStream = serport.getInputStream();
14
            outputStream = serport.getOutputStream();
15
            serport.addEventListener(this);
16
            serport.notifyOnDataAvailable(true);
17
        } catch (Exception e) {
18
            e.printStackTrace();
19
        }
20
    }
21
22
    public void serialEvent(SerialPortEvent evt) {
23
        if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
24
            try {
25
                StringBuffer readBuffer = new StringBuffer();
26
                int c;
27
                //lies bis \r\n
28
                while ((c = inputStream.read()) != 10) {
29
                    if (c != 13) {
30
                        readBuffer.append((char) c);
31
                    }
32
                }
33
                inputStream.close();
34
                String eingelesen = readBuffer.toString();
35
                //mach was mit den eingelesenen Daten
36
            } catch (IOException e) {
37
                e.printStackTrace();
38
            }
39
        }
40
    }
41
}

von Pfeiffy (Gast)


Lesenswert?

Hallo,
kannst du mir sagen, wie ich dann den String ("S") mitgeben kann?

Gruß
Pfeiffy

von Bernd K. (bem) Benutzerseite


Lesenswert?

Pfeiffy schrieb:
> kannst du mir sagen, wie ich dann den String ("S") mitgeben kann?

genauso, wie du es schon geschrieben hast, ich hab dir ja im Konstruktor 
schon einen OutputStream angelegt.

Jetzt fügst du z.B. noch eine Funktion ein:
1
private void schreibeAufSeriell(String foo) {
2
        try {
3
            outputStream.write(foo.getBytes());
4
            outputStream.flush();
5
            outputStream.close();
6
        } catch(IOException e) {
7
            e.printStackTrace();
8
        }
9
    }

von Pfeiffy (Gast)


Lesenswert?

Hallo,
ok, ich werde dies morgen, wenn ich zuhause bin ausgibig ausprobieren 
und mich dann evtl. nochmal melden

Gruß und Dank
Pfeiffy

von Pfeiffy (Gast)


Lesenswert?

Hallo,
ich kanns leider erst heute Abend direkt mit dem AVR testen, aber so 
stelle ich es mir vor:
1
import gnu.io.*;
2
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.io.OutputStream; //import java.io.OutputStream;
6
import java.util.Enumeration;
7
import java.util.TooManyListenersException;
8
9
//import OeffnenUndSenden.serialPortEventListener;
10
11
public class SeriellTest implements SerialPortEventListener {
12
13
  private CommPortIdentifier portID;
14
  private SerialPort serport;
15
  private InputStream inputStream;
16
  private OutputStream outputStream;
17
  static String empfangen;
18
  
19
  
20
  public static void main(String[] args)
21
  {
22
    SeriellTest st = new SeriellTest();
23
    st.schreibeAufSeriell("s");
24
    System.out.println("empfangen: " + empfangen);
25
  
26
  }
27
28
  
29
  
30
  public SeriellTest() {
31
    try {
32
      portID = CommPortIdentifier.getPortIdentifier("COM1"); // oder
33
                                  // /dev/ttyS0
34
      serport = (SerialPort) portID.open("foobar", 2000);
35
      serport.setSerialPortParams(4800, SerialPort.DATABITS_8,
36
          SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
37
      inputStream = serport.getInputStream();
38
      outputStream = serport.getOutputStream();
39
      serport.addEventListener(this);
40
      serport.notifyOnDataAvailable(true);
41
    } catch (Exception e) {
42
      e.printStackTrace();
43
    }
44
  }
45
46
  public void serialEvent(SerialPortEvent evt) {
47
    if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
48
      try {
49
        StringBuffer readBuffer = new StringBuffer();
50
        int c;
51
        // lies bis \r\n
52
        while ((c = inputStream.read()) != 10) {
53
          if (c != 13) {
54
            System.out.println("empfange");
55
            readBuffer.append((char) c);
56
          }
57
        }
58
        inputStream.close();
59
        empfangen = readBuffer.toString();
60
        // mach was mit den eingelesenen Daten
61
      } catch (IOException e) {
62
        e.printStackTrace();
63
      }
64
    }
65
  }
66
67
  private void schreibeAufSeriell(String foo) {
68
    try {
69
      outputStream.write(foo.getBytes());
70
      outputStream.flush();
71
      outputStream.close();
72
    } catch (IOException e) {
73
      e.printStackTrace();
74
    }
75
  }
76
  
77
}

das heisst: sofort nach meinem senden, sendet der AVR, welches sofort in 
den String "empfangen" übergeben wird und ich kann den empfangenen 
String  benutzen.

Gruß
Pfeiffy

von Bernd K. (bem) Benutzerseite


Lesenswert?

Äh, nein.
Wenn das funktioniert, dann nur durch Glück und Zufall.

Deine Ausgabe machst du in serialEvent(), ich hab dazu extra noch einen 
Kommentar hinterlassen:
1
// mach was mit den eingelesenen Daten

von Dirk P. (pfeiffy)


Lesenswert?

Hallo,
aber, um etwas zu empfangen muss ich ja zuerst senden, durch das senden 
löse ich somit ja erst den serial-event aus.

von Bernd K. (bem) Benutzerseite


Lesenswert?

Di Pfe schrieb:
> aber, um etwas zu empfangen muss ich ja zuerst senden, durch das senden
> löse ich somit ja erst den serial-event aus.

Ja.
Der Event kommt aber irgendwann, deshalb musst du in der Methode auf 
das Ereignis reagieren.
Du kannst nicht davon ausgehen, dass deine Daten sicher zwischen der 
Ausführung der beiden Zeilen
1
st.schreibeAufSeriell("s");
2
System.out.println("empfangen: " + empfangen);
ankommen.

von Dirk P. (pfeiffy)


Lesenswert?

Dann so?: nach dem empfangen abfragen, was ich gesendet habe?
1
import gnu.io.*;
2
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.io.OutputStream; //import java.io.OutputStream;
6
import java.util.Enumeration;
7
import java.util.TooManyListenersException;
8
9
//import OeffnenUndSenden.serialPortEventListener;
10
11
public class SeriellTest implements SerialPortEventListener {
12
13
  private CommPortIdentifier portID;
14
  private SerialPort serport;
15
  private InputStream inputStream;
16
  private OutputStream outputStream;
17
  static String empfangen;
18
  static String gesendet; // was habe ich gesendet
19
  static String temp1;
20
  static String temp2;
21
22
  public static void main(String[] args) {
23
    SeriellTest st = new SeriellTest();
24
    gesendet = "s";
25
    st.schreibeAufSeriell(gesendet);
26
    System.out.println("empfangen: " + empfangen);
27
28
  }
29
30
  public SeriellTest() {
31
    try {
32
      portID = CommPortIdentifier.getPortIdentifier("COM1"); // oder
33
      // /dev/ttyS0
34
      serport = (SerialPort) portID.open("foobar", 2000);
35
      serport.setSerialPortParams(4800, SerialPort.DATABITS_8,
36
          SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
37
      inputStream = serport.getInputStream();
38
      outputStream = serport.getOutputStream();
39
      serport.addEventListener(this);
40
      serport.notifyOnDataAvailable(true);
41
    } catch (Exception e) {
42
      e.printStackTrace();
43
    }
44
  }
45
46
  public void serialEvent(SerialPortEvent evt) {
47
    if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
48
      try {
49
        StringBuffer readBuffer = new StringBuffer();
50
        int c;
51
        // lies bis \r\n
52
        while ((c = inputStream.read()) != 10) {
53
          if (c != 13) {
54
            System.out.println("empfange");
55
            readBuffer.append((char) c);
56
          }
57
        }
58
        inputStream.close();
59
        empfangen = readBuffer.toString();
60
61
        // Verarbeite die Temperaturen.......
62
        verarbTemp(empfangen, gesendet);
63
64
        // mach was mit den eingelesenen Daten
65
      } catch (IOException e) {
66
        e.printStackTrace();
67
      }
68
    }
69
  }
70
71
  private void schreibeAufSeriell(String foo) {
72
    try {
73
      outputStream.write(foo.getBytes());
74
      outputStream.flush();
75
      outputStream.close();
76
    } catch (IOException e) {
77
      e.printStackTrace();
78
    }
79
  }
80
81
  void verarbTemp(String empfangen, String gesendet) {
82
83
    // hier könnte ich abfragen, was ich gesendet habe
84
    if (gesendet == "s") {
85
      // der empfangene Wert ist die Temperatur an Punkt1
86
      temp1 = empfangen;
87
      // schreibe Temp1 weg
88
89
    }
90
    if (gesendet == "t") {
91
      // der empfangene Wert ist die Temperatur an Punkt2
92
      temp2 = empfangen;
93
      // schreibe Temp1 weg
94
95
    }
96
97
  }
98
99
}

von Bernd K. (bem) Benutzerseite


Lesenswert?

Wenn du jetzt noch endlich
1
System.out.println("empfangen: " + empfangen);

aus main() entfernen würdest, klappts wahrscheinlich sogar.
Ich würde an deiner Stelle gleich noch ganz auf die globale Variable 
"empfangen" verzichten, das verwirrt in der Konstellation nur.

Aber denk dran, dass dein AVR bei dem Code seine Strings mit \r\n 
abschliessen muss.

von Pfeiffy (Gast)


Lesenswert?

Hallo,
nun habe ich doch noch einen Fehler drinnen, ich kann das Programm 1 mal 
starten, aber beim nächsten mal ist der comport belegt, das ist ja blöd, 
da ich noch keine gui habe und beim stoppen keinen windows-event 
abfangen kann muss ich das Programm über die Kommandozeile stoppen, dann 
bleibt der comport wahrscheinlich offen - kann ich den irgendwie im PC 
wirder freigeben?

Gruß
Pfeiffy

von Bernd K. (bem) Benutzerseite


Lesenswert?

Ähm?
Wenn du das Programm beendest, ist der Comport auch wieder frei.
Ich weiss nicht, was du mit "stoppen" meinst oder was das ganze mit 
einer gui zu tun haben soll?

von Pfeiffy (Gast)


Lesenswert?

Hallo,
ja ich habe herausgefunden: ich habe das Programm in eclipse laufen 
lassen und hier nur den Prozess nach dem beenden nicht gestoppt, da ich 
ja nur 1 mal sende, aber immer auf Bereitschaft bin. Lösung: entweder 
den Prozess im Eclipse stoppen oder ein system.exit(0) einbauen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.