Daten von einen Serial Port empfangen und verarbeiten

Anfängerfragen zum Programmieren mit PureBasic.
HHYayo
Beiträge: 25
Registriert: 14.05.2015 23:15

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HHYayo »

HeX0R hat geschrieben:Es scheint doch aber so zu sein, dass das Paket, dass Du bekommst immer gleich lang ist, richtig?
Dann lässt sich das Ganze doch aber wirklich recht einfach umsetzen.

Je nachdem, ob da jetzt als Zeilenvorschub nur ein oder zwei Zeichen kommen, ist Dein Rückgabepaket immer 16 oder 19 Zeichen lang (ich denke mal die eckige Klammer gehört noch dazu).
Also musst Du einfach warten, bis Dir AvailableSerialPortInput(0) 16 oder 19 zurückgibt, dann liest Du alles in einem Rutsch in einen Memorypuffer und holst Dir die Bytes Nr. 12 + 13 bzw. 14 + 15.

Oder aber, falls die Pakete variabel in der Länge sind, ist evtl. die eckige Klammer das Abschlusszeichen, dann solange den Puffer füllen, bis die am Ende da steht.

[Edit]
Hier mal ein simples Beispiel (ungetestet)

Code: Alles auswählen

Enumeration
	#SEND_TIMER
	#RECEIVE_TIMER
EndEnumeration

Procedure main()
	Protected *Buffer, BufferPos, AvailableBytes, Value
	
	If OpenSerialPort(0, "COM5", 9600, #PB_SerialPort_EvenParity , 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024) = 0
		MessageRequester("Error", "Can't open RS232!")
		ProcedureReturn
	EndIf
	
	*Buffer = AllocateMemory(8192)
	If *Buffer = 0
		MessageRequester("Error", "No memory available!")
		ProcedureReturn 
	EndIf
	
	;create a stupid window
	OpenWindow(0, 0, 0, 215, 80, "RS232", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	TextGadget(0, 5, 15, 100, 24, "Value:")
	StringGadget(1, 110, 15, 100, 24, "", #PB_String_ReadOnly)
	CreateStatusBar(0, WindowID(0))
	AddStatusBarField(#PB_Ignore)
	
	;send any 200ms
	AddWindowTimer(0, #SEND_TIMER, 200)
	;receive any 5ms
	AddWindowTimer(0, #RECEIVE_TIMER, 5)
	
	
	Repeat
		
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
				Break
				
			Case #PB_Event_Timer
				Select EventTimer()
					Case #SEND_TIMER
						If WriteSerialPortString(0, "010D" + #CRLF$, #PB_Ascii) = 0
							MessageRequester("Error", "SendString Error!")
							Break
						EndIf
					Case #RECEIVE_TIMER
						AvailableBytes = AvailableSerialPortInput(0)
						If AvailableBytes > 0
							ReadSerialPortData(0, *Buffer + BufferPos, AvailableBytes)
							BufferPos + AvailableBytes
							StatusBarText(0, 0, "Received: " + Str(BufferPos) + "Bytes")
							;check for '>'
							If PeekB(*Buffer + BufferPos - 1) = 62
								;end of packet
								
								If BufferPos = 16
									;one linefeed char
									Value = Val("$" + PeekS(*Buffer + 12, 2, #PB_Ascii))
								Else
									;two linefeed chars
									Value = Val("$" + PeekS(*Buffer + 14, 2, #PB_Ascii))
								EndIf
								SetGadgetText(1, Str(Value))
								BufferPos = 0
							EndIf
						EndIf
				EndSelect
		EndSelect
		
	ForEver
	
	CloseSerialPort(0)
EndProcedure

main()
Musst nur aufpassen, dass bei Fehlfunktion der Puffer nicht überläuft.
Ich mache da üblicherweise eine dynamische Anpassung, war ich jetzt aber zu faul :mrgreen:
Wie du richtig erkannt hast empfange ich hier speziell immer dieselbe Paket-Größe. Im späteren Verlauf könnte es sein, dass ich Pakete in unterschiedlicher Größe empfangen und verarbeiten muss, welche jedoch nach dem gleichen Prinzip aufgebaut sind und sich lediglich wie auch in diesen Fall am Ende vom Aufbau und der Länge variabel sind. Von daher denke ich ist dein Example früher oder später einmal bedeutend für mich, danke!

Ich würde gerne mal noch eine Frage bezüglich der Kompatibilität der früheren und neueren Versionen von Purebasic stellen.

Mit einer älteren Version habe ich über den API's SetWindowLongPtr_ und SetLayeredWindowAttributes_ eine Procedur geschrieben, mit der ich ein Fenster randlos und ohne "Design" nach und nach von einen Transparenzwert 0-255 "aufgehen" lasse, in dem sich ein ImageGadget befindet (Welches ebenfalls langsam eingeblendet wurde). Seit der aktuellen Version funktioniert es jedoch nicht mehr, da sich lediglich das Fenster langsam einblendet, jedoch nur komplett schwarz und ohne den Image. Kommt Purebasic nicht mehr mit den genannten API's klar ? War eine hübsche Spielerei die ich gerne wieder verwenden würde :D

Mit freundlichen Grüßen
HHYayo
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
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: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von NicTheQuick »

Hast du vielleicht eher dein Windows gewechselt? Purebasic hat kein Problem mit API. Der wahrscheinlichere Fall ist, dass du sie falsch benutzt und sie deswegen nicht Versionsübergreifend korrekt funktioniert.
HHYayo
Beiträge: 25
Registriert: 14.05.2015 23:15

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HHYayo »

NicTheQuick hat geschrieben:Hast du vielleicht eher dein Windows gewechselt? Purebasic hat kein Problem mit API. Der wahrscheinlichere Fall ist, dass du sie falsch benutzt und sie deswegen nicht Versionsübergreifend korrekt funktioniert.
Ich verstehe das nicht. Ich habe zu Testzwecken den gleichen Code genutzt, die gleiche Bild-Datei und hab alles unter denselben Umständen laufen lassen wie ich es vor einen halben Jahr erfolgreich compiliert habe. Dies war zu der Zeit auf einem Laptop mit Windows 7 und 64bit, mittlererweile ist es zwar ein Rechner, jedoch ebenfalls mit Windows 7 und 64bit. Meinen Code habe ich ebenfalls bereits überprüft und mit anderen in Forum vergleichen können.

Was hat denn mein jetziges Windows nicht, welches mein Altes hatte ?

Mit freundlichen Grüßen
HHYayo

Nachtrag: Mir ist mal aufgefallen, dass nichtmal mehr die damals bereits erstellte und funktionierende Binary das Bild nicht mehr anzeigt. Denn muss es ja wirklich an meiner Hardware liegen... Kann sein das es mit der Grafikkarte oder ähnlichen zu tun hat ?
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HeX0R »

Kannst Du nicht mal nen 10 Zeiler machen, der das Problem zeigt?
HHYayo
Beiträge: 25
Registriert: 14.05.2015 23:15

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HHYayo »

HeX0R hat geschrieben:Kannst Du nicht mal nen 10 Zeiler machen, der das Problem zeigt?
Na klar:

Code: Alles auswählen

Enumeration
  #Image
EndEnumeration

Procedure.i SetWindowTransparency(Window.i, transparency.i)
 
  If IsWindow(Window)
    Protected WindowID = WindowID(Window)
    SetWindowLongPtr_(WindowID,#GWL_EXSTYLE,#WS_EX_LAYERED)
    SetLayeredWindowAttributes_(WindowID,0,transparency,#LWA_ALPHA)
  EndIf

EndProcedure

defaultF$ = ""
pattern$ = "Alle Dateien (*.*)|*.*"
pattern = 0
imagepath$ = OpenFileRequester("Test Bild auswählen!",defaultF$,pattern$,pattern)
image = LoadImage(#Image,imagepath$)

Window= OpenWindow(#PB_Any, x, y, 600, 250, "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
Image= ImageGadget(#PB_Any, 0, 0, 600, 250, image)

For transp=0 To 255
  SetWindowTransparency(Window,transp)
  Delay(5)
Next
Mit freundlichen Grüßen
Deis-Performance
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
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: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von NicTheQuick »

Es wäre besser du arbeitest noch die Events ab, die im Fenster auftreten können.

Code: Alles auswählen

For transp=0 To 255
	SetWindowTransparency(Window,transp)
	Delay(5)
	While WindowEvent() : Wend
Next

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Bei mir funktioniert es jedenfalls unter Windows 7 Pro 64 Bit.
HHYayo
Beiträge: 25
Registriert: 14.05.2015 23:15

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HHYayo »

NicTheQuick hat geschrieben:Es wäre besser du arbeitest noch die Events ab, die im Fenster auftreten können.

Code: Alles auswählen

For transp=0 To 255
	SetWindowTransparency(Window,transp)
	Delay(5)
	While WindowEvent() : Wend
Next

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Bei mir funktioniert es jedenfalls unter Windows 7 Pro 64 Bit.
Jep, gleiches Windows...

Mit meiner Funktion wird lediglich nach und nach ein schwarzes Fenster eingeblendet statt den Image. Mit dem Abarbeiten der Events des Fensters passiert genau das Gleiche, nur dass das Fenster denn nicht schwarz ist sondern eher Hellgrau/Weiß ist.

Kann doch nicht sein.

Mit freundlichen Grüßen
HHYayo
Benutzeravatar
mhs
Beiträge: 224
Registriert: 11.01.2009 16:30
Wohnort: Graben
Kontaktdaten:

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von mhs »

Zwei Dinge die mir aufgefallen sind:

1. image = LoadImage(#Image,imagepath$) ist nicht offiziell dokumentiert. Laut Beschreibung hat LoadImage nur "irgendeinen" Rückgabewert ungleich Null.

Sicherer wäre, wenn du die ID per ImageID() ermitteln würdest

Code: Alles auswählen

LoadImage(#image, imagepath$)
ImageGadget(#PB_Any, 0, 0, 600, 250, ImageID(#image))
2. Du verwendest keinen ImageDecoder wie UseJPEGImageDecoder(), dadurch kannst du nur *.bmp öffnen, evtl hast du hier ein falsches Bild ausgewählt?
Michael Hack

Michael Hack Software :: Softwareentwicklung | Webentwicklung | IT-Dienstleistungen
www.michaelhacksoftware.de :: www.mh-s.de :: www.michael-hack.de
HHYayo
Beiträge: 25
Registriert: 14.05.2015 23:15

Re: Daten von einen Serial Port empfangen und verarbeiten

Beitrag von HHYayo »

mhs hat geschrieben:Zwei Dinge die mir aufgefallen sind:

1. image = LoadImage(#Image,imagepath$) ist nicht offiziell dokumentiert. Laut Beschreibung hat LoadImage nur "irgendeinen" Rückgabewert ungleich Null.

Sicherer wäre, wenn du die ID per ImageID() ermitteln würdest

Code: Alles auswählen

LoadImage(#image, imagepath$)
ImageGadget(#PB_Any, 0, 0, 600, 250, ImageID(#image))
2. Du verwendest keinen ImageDecoder wie UseJPEGImageDecoder(), dadurch kannst du nur *.bmp öffnen, evtl hast du hier ein falsches Bild ausgewählt?
Unglaublich, sollte man natürlich auch dran denken. Jetzt habe nur den Testcode geschrieben und genutzt um zu schauen ob es geht und da wirklich UsePNGImageDecoder() vergessen.

Nun funktioniert es, vielen Dank!

Mit freundlichen Grüßen
HHYayo
Antworten