Serielle Schnittstelle auslesen...
-
- Beiträge: 4
- Registriert: 03.09.2014 11:01
Serielle Schnittstelle auslesen...
Hallo
Ich habe einen Atmel Mikrocontrollerboard via Serieller Schnittstelle mit dem PC verbunden um Meßdaten auszulesen.
Kommunikation Hardwaremäßig funktioniert einwandfrei.
Blos beim Auslesen der Daten habe ich Probleme.
Der Controller schickt die Meßwerte binär zu PC.
ReadSerialPortData(0, @Puffer, 1)
Wert.s = chr (Puffer)
Was muß ich ändern damit mir immer nicht nur das erste Zeichen angezeigt wird. Wenn ich in dem Read Befehl die Länge von 1 ändere wird das Zeichen nicht mehr korrekt angezeigt.
Gruß...Gerhard
Ich habe einen Atmel Mikrocontrollerboard via Serieller Schnittstelle mit dem PC verbunden um Meßdaten auszulesen.
Kommunikation Hardwaremäßig funktioniert einwandfrei.
Blos beim Auslesen der Daten habe ich Probleme.
Der Controller schickt die Meßwerte binär zu PC.
ReadSerialPortData(0, @Puffer, 1)
Wert.s = chr (Puffer)
Was muß ich ändern damit mir immer nicht nur das erste Zeichen angezeigt wird. Wenn ich in dem Read Befehl die Länge von 1 ändere wird das Zeichen nicht mehr korrekt angezeigt.
Gruß...Gerhard
- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
Re: Serielle Schnittstelle auslesen...
Hab zwar keine serielle Schnittstelle
, aber so in etwa sollte es Funktionieren:
Gruß
Thomas

Code: Alles auswählen
EnableExplicit
; ...
; ...
Define *Puffer, anzahl, Wert.s
*Puffer = AllocateMemory(1000)
anzahl = ReadSerialPortData(0, *Puffer, 1000)
Wert = PeekS(*Puffer, anzahl, #PB_Ascii)
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Re: Serielle Schnittstelle auslesen...
ich sende oft Daten von meinem Arduino an meine PureBasic-Anwendungen. Daher bin ich mit dem seriellen Datenaustausch (COM-Anschluss) in Purebasic vertraut. So wie ich es interpretiere, willst du einen String empfangen und zusammensetzten. Ist das Richtig? Was hast du denn genau vor?
viele Grüße,
SBond
viele Grüße,
SBond
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e


- NicTheQuick
- Ein Admin
- Beiträge: 8809
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Re: Serielle Schnittstelle auslesen...
Ich habe für meine Mikrocontroller-Projekte dafür ein Interface gebaut für die serielle Kommunikation. Das sieht so aus:
Wenn ich mal mehr Zeit finde, kommentiere ich es noch ausführlicher und stelle es in "Codes, Tipps & Tricks" ein. Außerdem wäre wohl eine Kapselung in ein Modul auch noch etwas schöner. 
Code: Alles auswählen
Interface Serial
open.i(device.s, baudrate.i, parity.i = #PB_SerialPort_NoParity, dataBits.i = 8, stopBit.i = 1, handShake.i = #PB_SerialPort_NoHandshake)
close.i()
sendData(*buffer, length.i)
sendChar(char.a)
sendFloat(float.f)
receiveData(*buffer, length.i)
receiveChar.a()
receiveLong.l()
sendUnicode(unicode.u)
receiveUnicode.u()
receiveFloat.f()
sendString(string.s) ; Sendet den String ohne Nullbyte am Schluss
receiveString.s(length.i = -1, eol.c = 0)
availableData.i()
waitFor.i(*buffer, length.i)
isOpen.i()
lock()
unlock()
tryLock.i()
free()
bps.f()
availableOutput.i()
EndInterface
Structure SerialS
vTable.i
device.s
baudrate.i
handle.i
hMutex.i
lastTime.i
bytesSent.i
EndStructure
Procedure.i Serial_new()
Protected *this.SerialS
*this = AllocateMemory(SizeOf(SerialS))
If Not *this : ProcedureReturn #False : EndIf
*this\vTable = ?vTable_Serial
*this\hMutex = CreateMutex()
*this\bytesSent = 0
ProcedureReturn *this
EndProcedure
Procedure.i Serial_open(*this.SerialS, device.s, baudrate.i, parity.i = #PB_SerialPort_NoParity, dataBits.i = 8, stopBit.i = 1, handShake.i = #PB_SerialPort_NoHandshake)
If IsSerialPort(*this\handle)
CloseSerialPort(*this\handle)
EndIf
*this\handle = OpenSerialPort(#PB_Any, device, baudrate, parity, dataBits, stopBit, handShake, 4096, 4096)
If Not *this\handle : ProcedureReturn #False : EndIf
*this\device = device
*this\baudrate = baudrate
ProcedureReturn #True
EndProcedure
OpenSerialPort(#PB_Any, "/dev/rfcomm0", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 4096, 4096)
Procedure Serial_close(*this.SerialS)
If IsSerialPort(*this\handle)
CloseSerialPort(*this\handle)
EndIf
EndProcedure
Procedure Serial_sendData(*this.SerialS, *buffer, length.i)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < length
pos + WriteSerialPortData(*this\handle, *buffer + pos, length - pos)
Wend
*this\bytesSent + length
EndIf
EndProcedure
Procedure Serial_sendChar(*this.SerialS, char.a)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < 1
pos + WriteSerialPortData(*this\handle, @char, 1)
Wend
*this\bytesSent + 1
EndIf
EndProcedure
Procedure Serial_sendFloat(*this.Serial, float.f)
*this\sendData(@float, SizeOf(Float))
EndProcedure
Procedure Serial_receiveData(*this.SerialS, *buffer, length.i)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < length
pos + ReadSerialPortData(*this\handle, *buffer + pos, length - pos)
Wend
ProcedureReturn length
EndIf
ProcedureReturn #False
EndProcedure
Macro Serial_receiveTYPE(__name, __t, __s, __return)
Procedure.__s Serial_receive#__name(*this.Serial)
Protected result.__s
If (*this\receiveData(@result, SizeOf(__t)))
ProcedureReturn result
EndIf
ProcedureReturn __return
EndProcedure
EndMacro
Serial_receiveTYPE(Char, Character, c, 0)
Serial_receiveTYPE(Long, Long, l, 0)
Serial_receiveTYPE(Unicode, Unicode, u, 0)
Serial_receiveTYPE(Float, Float, f, 0.0)
Procedure Serial_sendUnicode(*this.SerialS, unicode.u)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < 2
pos + WriteSerialPortData(*this\handle, @unicode + 1 - pos, 2 - pos)
Wend
*this\bytesSent + 2
EndIf
EndProcedure
Procedure Serial_sendString(*this.SerialS, string.s)
Protected pos.i, length.i = Len(string)
If IsSerialPort(*this\handle)
While pos < length
pos + WriteSerialPortData(*this\handle, @string + pos, length - pos)
Wend
*this\bytesSent + length
EndIf
EndProcedure
Procedure.s Serial_receiveString(*this.SerialS, length.i = -1, eol.c = 0)
Protected pos.i = 0, *mem, result.s = "", c.a
If IsSerialPort(*this\handle)
If length = 0 : ProcedureReturn "" : EndIf
While length
While Not ReadSerialPortData(*this\handle, @c, 1) : Wend
If (Not c) Or (c = eol) : Break : EndIf
result + Chr(c)
length - 1
Wend
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Serial_availableData(*this.SerialS)
If IsSerialPort(*this\handle)
ProcedureReturn AvailableSerialPortInput(*this\handle)
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i Serial_waitFor(*this.SerialS, *buffer.Ascii, length.i)
Protected try.i = 0
If IsSerialPort(*this\handle)
Protected i.i = 0, Dim copyBuffer.a(length - 1), j.i = 0, full.i = 1
Repeat
While Not ReadSerialPortData(*this\handle, @copyBuffer(j), 1) : Wend
j = (j + 1) % length
If (full < length)
full + 1
Else
For i = 0 To length - 1
If (*buffer\a <> copyBuffer((j + i) % length))
*buffer - i
try + 1
Break
EndIf
*buffer + 1
Next
If (i = length)
Break
EndIf
EndIf
ForEver
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i Serial_isOpen(*this.SerialS)
ProcedureReturn IsSerialPort(*this\handle)
EndProcedure
Procedure Serial_lock(*this.SerialS)
LockMutex(*this\hMutex)
EndProcedure
Procedure Serial_unlock(*this.SerialS)
UnlockMutex(*this\hMutex)
EndProcedure
Procedure.i Serial_tryLock(*this.SerialS)
ProcedureReturn TryLockMutex(*this\hMutex)
EndProcedure
Procedure Serial_free(*this.SerialS)
FreeMutex(*this\hMutex)
FreeMemory(*this)
EndProcedure
Procedure.f Serial_bps(*this.SerialS)
Protected newTime.i = ElapsedMilliseconds()
Protected bps.f = *this\bytesSent / ((newTime - *this\lastTime) / 1000.0)
*this\lastTime = newTime
*this\bytesSent = 0
ProcedureReturn bps
EndProcedure
Procedure.i Serial_availableOutput(*this.SerialS)
If IsSerialPort(*this\handle)
ProcedureReturn AvailableSerialPortOutput(*this\handle)
EndIf
ProcedureReturn -1
EndProcedure
DataSection
vTable_Serial:
Data.i @Serial_open(), @Serial_close(), @Serial_sendData(), @Serial_sendChar(), @Serial_sendFloat()
Data.i @Serial_receiveData(), @Serial_receiveChar(), @Serial_receiveLong()
Data.i @Serial_sendUnicode(), @Serial_receiveUniCode()
Data.i @Serial_receiveFloat()
Data.i @Serial_sendString(), @Serial_receiveString(), @Serial_availableData(), @Serial_waitFor()
Data.i @Serial_isOpen(), @Serial_lock(), @Serial_unlock(), @Serial_tryLock(), @Serial_free()
Data.i @Serial_bps(), @Serial_availableOutput()
EndDataSection

- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
Re: Serielle Schnittstelle auslesen...
@NicTheQuick
Ich denke mal, damit ist Cabriolöwe etwas überfordert
Ich denke mal, damit ist Cabriolöwe etwas überfordert

PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

-
- Beiträge: 4
- Registriert: 03.09.2014 11:01
Re: Serielle Schnittstelle auslesen...
Hallo..
Etwas überfordert ist gelinde gesagt maßlos untertrieben
Ich Programmiere die Microcontroller mit Bascom.
Bascom sendet die Werte mit dem Print Befehl binär über die Serielle Schnittstelle.
Ich habe jetzt eine Lösung gefunden wie es funktioniert, ob es die Beste ist, kann ich nicht beurteilen.
Ich lese die Werte Zahl für Zahl binär mit Purebasic wandle sie dann mit chr und füge sie zu einem String zusammen.
readserialportdata(0, @puffer, 1)
readserialportdata(0, @puffer1, 1)
Wert.s = Chr (puffer) + Chr (puffer1)
Wie ich mehrere Zeichen auf einmal auslesen kann das habe ich noch nicht hinbekommen.
Sobald ich die Länge 1 ändere auf 2 oder 3 kann ich nicht nachvollziehen was in den Puffer geschrieben wird.
Aber ich bin was Purebasic betriffe ein absoluter Anfänger.
Gruß..Gerhard
Etwas überfordert ist gelinde gesagt maßlos untertrieben

Ich Programmiere die Microcontroller mit Bascom.
Bascom sendet die Werte mit dem Print Befehl binär über die Serielle Schnittstelle.
Ich habe jetzt eine Lösung gefunden wie es funktioniert, ob es die Beste ist, kann ich nicht beurteilen.
Ich lese die Werte Zahl für Zahl binär mit Purebasic wandle sie dann mit chr und füge sie zu einem String zusammen.
readserialportdata(0, @puffer, 1)
readserialportdata(0, @puffer1, 1)
Wert.s = Chr (puffer) + Chr (puffer1)
Wie ich mehrere Zeichen auf einmal auslesen kann das habe ich noch nicht hinbekommen.
Sobald ich die Länge 1 ändere auf 2 oder 3 kann ich nicht nachvollziehen was in den Puffer geschrieben wird.
Aber ich bin was Purebasic betriffe ein absoluter Anfänger.
Gruß..Gerhard
Re: Serielle Schnittstelle auslesen...
hallo Cabriolöwe,
Zeichen für Zeichen zusammensetzten würde ich es nicht. Da du den Print-Befehl verwendest kommt das ganze in Text-Format an, was das ganze sogar noch vereinfacht.
Am besten liest man die ganzen vorhandenen Daten aus dem COM-Puffer und parst die Daten. Dann vermeidest du auch mögliche Pufferüberläufe (bei Windows passiert es bei ca. 12,5 KB Daten)
Ich könnte dir heute abend dazu etwas geben. Ich müsste nur wissen, auf welchem System das ganze laufen soll (Windows?) und wie so ein Datenstrom aussieht. Sind die Messwerte gleich lang oder durch ein Zeichen getrennt? Bei einen Print-Befehl wird ja oft ein CRLF mitgesendet....
sehen deine Daten in etwa so aus?:
123
532
334
552
632
oder so 412;1345;452;742;... ?
viele Grüße,
SBond
Zeichen für Zeichen zusammensetzten würde ich es nicht. Da du den Print-Befehl verwendest kommt das ganze in Text-Format an, was das ganze sogar noch vereinfacht.

Am besten liest man die ganzen vorhandenen Daten aus dem COM-Puffer und parst die Daten. Dann vermeidest du auch mögliche Pufferüberläufe (bei Windows passiert es bei ca. 12,5 KB Daten)
Ich könnte dir heute abend dazu etwas geben. Ich müsste nur wissen, auf welchem System das ganze laufen soll (Windows?) und wie so ein Datenstrom aussieht. Sind die Messwerte gleich lang oder durch ein Zeichen getrennt? Bei einen Print-Befehl wird ja oft ein CRLF mitgesendet....
sehen deine Daten in etwa so aus?:
123
532
334
552
632
oder so 412;1345;452;742;... ?
viele Grüße,
SBond
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e


-
- Beiträge: 4
- Registriert: 03.09.2014 11:01
Re: Serielle Schnittstelle auslesen...
Hallo SBond
Nein, ich schicke ausschließlich die Messwerte rüber...ohne Zeilenumbruch etc.
readserialportdata(0, @puffer, 1)
welches Datenformat müßte ich den verwenden um @Puffer und die Datenlänge korrekt verwenden kann.
Mit Ascii funktioniert es auch nicht, das habe ich schon ausprobiert.
Danke schon mal....Gruß....Gerhard
Nein, ich schicke ausschließlich die Messwerte rüber...ohne Zeilenumbruch etc.
readserialportdata(0, @puffer, 1)
welches Datenformat müßte ich den verwenden um @Puffer und die Datenlänge korrekt verwenden kann.
Mit Ascii funktioniert es auch nicht, das habe ich schon ausprobiert.
Danke schon mal....Gruß....Gerhard
Re: Serielle Schnittstelle auslesen...
Sind deine Messwerte immer ein Byte groß?
bzw. wie erkenne ich, dass ein Messwert komplett ist?
z.B. erhalte ich die Daten:26826773. Dann könnten die Werte folgende sein: 26, 82, 67, 73 oder 2682, 6773. Natürlich unter der Bedingung, dass die Zahlen als ASCII-Text interpretiert werden.
Hast du mal ein Beispiel, wie die Ausgabe von deinem Mikrocontroller aussieht?
viele Grüße,
SBond
bzw. wie erkenne ich, dass ein Messwert komplett ist?
z.B. erhalte ich die Daten:26826773. Dann könnten die Werte folgende sein: 26, 82, 67, 73 oder 2682, 6773. Natürlich unter der Bedingung, dass die Zahlen als ASCII-Text interpretiert werden.
Hast du mal ein Beispiel, wie die Ausgabe von deinem Mikrocontroller aussieht?
viele Grüße,
SBond
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e


-
- Beiträge: 4
- Registriert: 03.09.2014 11:01
Re: Serielle Schnittstelle auslesen...
Hallo S.Bond
Ich schicke mit dem Print Befehl z..b 12.00 rüber für 12.00V
mit
VorhandeneByte = availableserialportinput(0)
will ich diese anzahl überprüfen und sie dann auslesen. Wenn diese Daten ausgelesen sind will ich
dann mit writeserialportdata neue Daten anfordern.
mein "Problem" ist eigentlich nur wie ich die 5 Byte auf einmal aus dem Puffer auslesen kann und darstellen.
Gruß...Gerhard
Ich schicke mit dem Print Befehl z..b 12.00 rüber für 12.00V
mit
VorhandeneByte = availableserialportinput(0)
will ich diese anzahl überprüfen und sie dann auslesen. Wenn diese Daten ausgelesen sind will ich
dann mit writeserialportdata neue Daten anfordern.
mein "Problem" ist eigentlich nur wie ich die 5 Byte auf einmal aus dem Puffer auslesen kann und darstellen.
Gruß...Gerhard