mikrocontroller.net

Forum: PC-Programmierung Java Com lesen und schreiben


Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Nicht Gast (Gast)
Datum:

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

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: MB (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch mal die rxtx.org

Dort gibts libs für den com Port anzusprechen.

Autor: Pfeiffy (Gast)
Datum:

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

Gruß
Pfeiffy

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
outputStream.write("S".getBytes());

Gruß
Pfeiffy

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, das einlesen machst du am besten eventbasiert mit einem 
SerialPortEventListener.
Hier mal ein funktionsfähiges Quick&Dirty Beispiel:
public class SeriellTest implements SerialPortEventListener {

    private CommPortIdentifier portID;
    private SerialPort serport;
    private InputStream inputStream;
    private OutputStream outputStream;

    public SeriellTest() {
        try {
            portID = CommPortIdentifier.getPortIdentifier("COM1"); //oder /dev/ttyS0
            serport = (SerialPort) portID.open("foobar", 2000);
            serport.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            inputStream = serport.getInputStream();
            outputStream = serport.getOutputStream();
            serport.addEventListener(this);
            serport.notifyOnDataAvailable(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void serialEvent(SerialPortEvent evt) {
        if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                StringBuffer readBuffer = new StringBuffer();
                int c;
                //lies bis \r\n
                while ((c = inputStream.read()) != 10) {
                    if (c != 13) {
                        readBuffer.append((char) c);
                    }
                }
                inputStream.close();
                String eingelesen = readBuffer.toString();
                //mach was mit den eingelesenen Daten
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Autor: Pfeiffy (Gast)
Datum:

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

Gruß
Pfeiffy

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
private void schreibeAufSeriell(String foo) {
        try {
            outputStream.write(foo.getBytes());
            outputStream.flush();
            outputStream.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

Autor: Pfeiffy (Gast)
Datum:

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

Gruß und Dank
Pfeiffy

Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich kanns leider erst heute Abend direkt mit dem AVR testen, aber so 
stelle ich es mir vor:
import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; //import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

//import OeffnenUndSenden.serialPortEventListener;

public class SeriellTest implements SerialPortEventListener {

  private CommPortIdentifier portID;
  private SerialPort serport;
  private InputStream inputStream;
  private OutputStream outputStream;
  static String empfangen;
  
  
  public static void main(String[] args)
  {
    SeriellTest st = new SeriellTest();
    st.schreibeAufSeriell("s");
    System.out.println("empfangen: " + empfangen);
  
  }

  
  
  public SeriellTest() {
    try {
      portID = CommPortIdentifier.getPortIdentifier("COM1"); // oder
                                  // /dev/ttyS0
      serport = (SerialPort) portID.open("foobar", 2000);
      serport.setSerialPortParams(4800, SerialPort.DATABITS_8,
          SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
      inputStream = serport.getInputStream();
      outputStream = serport.getOutputStream();
      serport.addEventListener(this);
      serport.notifyOnDataAvailable(true);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void serialEvent(SerialPortEvent evt) {
    if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
      try {
        StringBuffer readBuffer = new StringBuffer();
        int c;
        // lies bis \r\n
        while ((c = inputStream.read()) != 10) {
          if (c != 13) {
            System.out.println("empfange");
            readBuffer.append((char) c);
          }
        }
        inputStream.close();
        empfangen = readBuffer.toString();
        // mach was mit den eingelesenen Daten
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void schreibeAufSeriell(String foo) {
    try {
      outputStream.write(foo.getBytes());
      outputStream.flush();
      outputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  
}

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

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
// mach was mit den eingelesenen Daten

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
st.schreibeAufSeriell("s");
System.out.println("empfangen: " + empfangen);
ankommen.

Autor: Dirk P. (pfeiffy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann so?: nach dem empfangen abfragen, was ich gesendet habe?
import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; //import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

//import OeffnenUndSenden.serialPortEventListener;

public class SeriellTest implements SerialPortEventListener {

  private CommPortIdentifier portID;
  private SerialPort serport;
  private InputStream inputStream;
  private OutputStream outputStream;
  static String empfangen;
  static String gesendet; // was habe ich gesendet
  static String temp1;
  static String temp2;

  public static void main(String[] args) {
    SeriellTest st = new SeriellTest();
    gesendet = "s";
    st.schreibeAufSeriell(gesendet);
    System.out.println("empfangen: " + empfangen);

  }

  public SeriellTest() {
    try {
      portID = CommPortIdentifier.getPortIdentifier("COM1"); // oder
      // /dev/ttyS0
      serport = (SerialPort) portID.open("foobar", 2000);
      serport.setSerialPortParams(4800, SerialPort.DATABITS_8,
          SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
      inputStream = serport.getInputStream();
      outputStream = serport.getOutputStream();
      serport.addEventListener(this);
      serport.notifyOnDataAvailable(true);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void serialEvent(SerialPortEvent evt) {
    if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
      try {
        StringBuffer readBuffer = new StringBuffer();
        int c;
        // lies bis \r\n
        while ((c = inputStream.read()) != 10) {
          if (c != 13) {
            System.out.println("empfange");
            readBuffer.append((char) c);
          }
        }
        inputStream.close();
        empfangen = readBuffer.toString();

        // Verarbeite die Temperaturen.......
        verarbTemp(empfangen, gesendet);

        // mach was mit den eingelesenen Daten
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void schreibeAufSeriell(String foo) {
    try {
      outputStream.write(foo.getBytes());
      outputStream.flush();
      outputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  void verarbTemp(String empfangen, String gesendet) {

    // hier könnte ich abfragen, was ich gesendet habe
    if (gesendet == "s") {
      // der empfangene Wert ist die Temperatur an Punkt1
      temp1 = empfangen;
      // schreibe Temp1 weg

    }
    if (gesendet == "t") {
      // der empfangene Wert ist die Temperatur an Punkt2
      temp2 = empfangen;
      // schreibe Temp1 weg

    }

  }

}

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du jetzt noch endlich
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.

Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bernd Klier (bem) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Pfeiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.