Powershell und Kommunikation (lesen und schreiben) mit RS-232, COM1, serielle Schnittstelle
Hallo,
über die Powershell soll ein externes Gerät mit serieller Schnittstelle(RS232/COM1) angesprochen und gesteuert werden. Das Senden der Daten an das Gerät stellt kein Problem dar.
Allerdings habe ich große Probleme die seriellen Daten korrekt zu empfangen, da Daten verloren gehen bzw. die Übertragung nicht stabil läuft!
Mein erster Ansatz für die Lösung dieser Aufgabe war folgender Beitrag auf der Microsoft-Webseite mit folgenden Quellcode:
Die Steuerung des Gerätes erfolgt nach folgenden Schema:
Erster Beispielquellcode
Das angesprochene Gerät sendet nach dem Empfangen des Befehls sofort eine Antwort, je nach Abfragegeschwindigkeit werden nicht alle Daten übertragen bzw. gehen verloren!
Deshalb möchte ich das Empfangsregister (Puffer/Buffer) über eine Ereignisabfrage (Interrupt/Flag) abfragen. Nur wenn neue Daten anliegen erfolgt eine Abfrage der Daten und eine Auswertung auf das Abschlusszeichen. Allerdings ist hierzu die Dokumentation von Microsoft und im Internet bezogen auf die Powershell dürftig.
Für die Abfrage soll die Methode DataReiceved() genutzt werden, allerdings komme ich hier nicht weiter, da der Code von Microsoft nicht für die Powershell ist?! Wie kann ich diese Methode und das Abfragen der Events korrekt in die Powershell einbinden?
In folgenden Artikel wird auf diese Thematik eingegangen:
1. SerialPort and DataReceived Event
2. Top 5 SerialPort Tips
über die Powershell soll ein externes Gerät mit serieller Schnittstelle(RS232/COM1) angesprochen und gesteuert werden. Das Senden der Daten an das Gerät stellt kein Problem dar.
Allerdings habe ich große Probleme die seriellen Daten korrekt zu empfangen, da Daten verloren gehen bzw. die Übertragung nicht stabil läuft!
Mein erster Ansatz für die Lösung dieser Aufgabe war folgender Beitrag auf der Microsoft-Webseite mit folgenden Quellcode:
#Daten schreiben
$port= new-Object System.IO.Ports.SerialPort COM1,9600,None,8,one
$port.open()
$port.WriteLine("Hello world")
$port.Close()
#Daten lesen
$port= new-Object System.IO.Ports.SerialPort COM1,9600,None,8,one
$port.Open()
$port.ReadLine()
Die Steuerung des Gerätes erfolgt nach folgenden Schema:
- Befehl senden
- Daten lesen/empfangen
- Befehl senden
- Daten lesen/empfangen
- usw.
Erster Beispielquellcode
#INIT => Allgemein
[string]$buffer = " ";
# Befehlsyntax für RS-232-Gerät
[string]$rs232_event_check = "/event/log/entries ?`r";
[string]$rs232_event_transfer = "/event/log/read ?`r";
# INIT => Eigenschaften der seriellen schnittstelle
$port = New-Object System.IO.Ports.SerialPort;
[string]$port.PortName = "COM1";
[int]$port.BaudRate = 19200;
[int]$port.DataBits = 8;
[string]$port.Parity = "None";
[string]$port.StopBits = "One";
[string]$port.Handshake = "XOnXOff";
# START => Kommunikation
# RS-232-Kommunikation => START
$port.Open();
# RS-232-Kommunikation => Gerät ansprechen
$port.WriteLine($rs232_event_check);
# RS-232-Kommunikation => Gerätdaten abfragen
$buffer = $port.ReadLine();
# Testausgabe auf Konsole
echo $buffer;
$port.WriteLine($rs232_event_check);
$buffer = $port.ReadLine();
echo $buffer;
# RS-232-Kommunikation => ENDE
$port.Close()
Das angesprochene Gerät sendet nach dem Empfangen des Befehls sofort eine Antwort, je nach Abfragegeschwindigkeit werden nicht alle Daten übertragen bzw. gehen verloren!
Deshalb möchte ich das Empfangsregister (Puffer/Buffer) über eine Ereignisabfrage (Interrupt/Flag) abfragen. Nur wenn neue Daten anliegen erfolgt eine Abfrage der Daten und eine Auswertung auf das Abschlusszeichen. Allerdings ist hierzu die Dokumentation von Microsoft und im Internet bezogen auf die Powershell dürftig.
Für die Abfrage soll die Methode DataReiceved() genutzt werden, allerdings komme ich hier nicht weiter, da der Code von Microsoft nicht für die Powershell ist?! Wie kann ich diese Methode und das Abfragen der Events korrekt in die Powershell einbinden?
In folgenden Artikel wird auf diese Thematik eingegangen:
1. SerialPort and DataReceived Event
2. Top 5 SerialPort Tips
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 203134
Url: https://administrator.de/contentid/203134
Ausgedruckt am: 23.11.2024 um 00:11 Uhr
3 Kommentare
Neuester Kommentar
Hallo DonniDuck,
schau mal hier und hier nach. Dort sind zwar nur Beispiele für Timer-Events, das sollte sich allerdings auf Deinen Fall übertragen lassen.
Evtl. so (ungetestet):
Gruß
Friemler
schau mal hier und hier nach. Dort sind zwar nur Beispiele für Timer-Events, das sollte sich allerdings auf Deinen Fall übertragen lassen.
Evtl. so (ungetestet):
$rs232_event_check = "/event/log/entries ?`r";
$rs232_event_transfer = "/event/log/read ?`r";
$port = new-Object System.IO.Ports.SerialPort
$port.PortName = "COM1"
$port.BaudRate = 19200
$port.DataBits = 8
$port.Parity = "None"
$port.StopBits = "One"
$port.Handshake = "XOnXOff"
$null = Register-ObjectEvent $port DataReceived -SourceIdentifier "SerialPort.DataReceived" -Action {OnDataReceived}
$port.Open()
$port.WriteLine($rs232_event_check)
Start-Sleep -Seconds 2
$port.Close()
Unregister-Event -SourceIdentifier "SerialPort.DataReceived"
function OnDataReceived {
$response = $port.ReadLine()
echo $response
}
Gruß
Friemler
Hi DonniDuck,
ein etwas später Kommentar, aber vielleicht hilft er noch, ich hatte mir hier auch ewig den Kopf zerbrochen. Der Event wird schon getriggert, das sieht man, wenn man in der Action einfach etwas auf den Host schreibt. Nur habe ich nie Daten vom seriellen Port gesehen, bis ich nach einigem Probieren auf den MessageData-Parameter gekommen bin:
$event = Register-ObjectEvent -InputObject $port -EventName DataReceived -MessageData $port -SourceIdentifier "SerialPort.DataReceived" -Action { $event.messagedata.readexisting() | Out-Host }
Und vor dem Schließen des Ports sollte dann noch ein Start-Sleep stattfinden, sonst ist der Kanal zu bevor das Gerät fertig geantwortet hat.
Viele Grüße vom Bitschubser
ein etwas später Kommentar, aber vielleicht hilft er noch, ich hatte mir hier auch ewig den Kopf zerbrochen. Der Event wird schon getriggert, das sieht man, wenn man in der Action einfach etwas auf den Host schreibt. Nur habe ich nie Daten vom seriellen Port gesehen, bis ich nach einigem Probieren auf den MessageData-Parameter gekommen bin:
$event = Register-ObjectEvent -InputObject $port -EventName DataReceived -MessageData $port -SourceIdentifier "SerialPort.DataReceived" -Action { $event.messagedata.readexisting() | Out-Host }
Und vor dem Schließen des Ports sollte dann noch ein Start-Sleep stattfinden, sonst ist der Kanal zu bevor das Gerät fertig geantwortet hat.
Viele Grüße vom Bitschubser