Höchsten Wert von 23 Leitungen ermitteln

Dieser Bereich ist für den Austausch FERTIGER Makros und allgemein nützlicher Schaltungen vorgesehen.
habe
Beiträge: 36
Registriert: Samstag 18. Oktober 2008, 18:51

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von habe » Dienstag 29. November 2011, 19:51

Hallo Thomas,

die DLL ist mit FreeBASIC programmiert worden.
Mit Euphoria, C oder Delphi kenn ich mich nicht aus.
Ich bin auch kein Programmierprofi, bin selber noch am lernen.

FreeBASIC ist ein Open-Source-Compiler. Für diesen Compiler gibt es
mehrere verschiedene IDE's. Ich benutze die IDE FBEdit 1.0.7.6c.
Sie verfügt über einen Editor, mit der man grafische Oberflächen erstellen
kann (bei Delphi ist das glaube ich ähnlich).
Da es bei FreeBasic keine objektorientierte Programmierung gibt, muss die
Handhabung der Controlls über WinAPI-Funktionen erfolgen.

Hier mal der Code der DLL (geht bestimmt effizenter, also nicht lachen!):

Code: Alles auswählen

#Include Once "windows.bi"

#Define IDD_DLG1 1000
#Define IDC_BTN1 1001
#Define IDC_BTN2 1002
#Define IDC_CBO1 1003
#Define IDC_CBO2 1004

Dim Shared hInstance As HMODULE

'----- Deklaration von Sub's und Functionen -----

' Diese Function wird nach öffnen des User-Dialogs 
' immer wieder aufgerufen um z.B:
' - Comboboxen mit Werten zu füllen
' - Überwacht ob ein Button angeklickt wurde
' - usw.
Declare Function DlgProc(ByVal hWin As HWND, _
								 ByVal uMsg As UINT, _
								 ByVal wParam As WPARAM, _
								 ByVal lParam As LPARAM) As Integer
								 
' Diese Function ermittelt die Instance des User-Dialogs.
' Sonst wird es nicht von Windows dargestelt. 
Declare Function GetModuleInstance() As Integer
'------------------------------------------------

Dim Shared Combobox1 As Short		' Anzahl Kanäle
Dim Shared Combobox2 As Short		' LED Ausgabe Ja/Nein

Dim Shared a As UByte				' wird zur Beschriftung der Ausgänge benötigt
Dim Shared b As UByte				' wird zur Beschriftung der Ausgänge benötigt

' Die ProfiLab Routinen müssen zwischen "Extern" und "End Extern" stehen
Extern "windows-ms"
' Beginn ProfiLab Routinen
Function CNumInputsEx (PUser As Double Ptr) As UByte Export 

	Return PUser[0] + 1				' Rückgabe der Bauteileingänge (+1 für Use-Pin)

End Function

Function CNumOutputsEx (PUser As Double Ptr) As UByte Export 
	
	If PUser[1] = 1 Then
		Return (2 * PUser[0]) + 3	' Rückgabe der Bauteilausgänge (+3 für Min/Max/Mittel)
	Else
		Return 3
	EndIf
			
End Function

Sub GetInputName (ByVal Channel As UByte, InputName As ZString) Export 
	
	If Channel = 0 Then
		InputName = "Use"
	Else
		InputName = "K" & LTrim(Str(Channel))
	EndIf
		
End Sub

Sub GetOutputName (ByVal Channel As UByte, OutputName AS ZString) Export 
	
	If Channel = 0 Then
		OutputName = "Max"
	ElseIf Channel = 1 Then
		OutputName = "Mittel"
	ElseIf Channel = 2 Then
		OutputName = "Min"
		a = 1
		b = 1
	Else 
		If a = 1 Then
			OutputName = "K" & Str(b) & "_Max"
			a = a + 1
		Else
			OutputName = "K" & Str(b) & "_Min"
			a = 1
			b = b + 1
		EndIf
	EndIf	
	
End Sub


Sub CSimStart (PInput AS Double Ptr, POutput AS Double Ptr, PUser AS Double Ptr) Export
	
	' nothing to be done

End Sub

Sub CSimStop (PInput As Double Ptr, POutput As Double Ptr, PUser As Double Ptr) Export

	' nothing to be done

End Sub

Sub CCalculate (PInput As Double Ptr, POutput AS Double Ptr, PUser AS Double Ptr) Export
	
	Dim Min_Wert As Double
	Dim Max_wert As Double
	Dim Mittelwert As Double
	Dim Summe As Double 
	Dim Use_Channel As UByte
	Dim n As UByte
	Dim x As UByte
		
	If PInput[0] < 2 Or PInput[0] > PUser[0] Then 
		Use_Channel = PUser[0]
	Else 
		Use_Channel = PInput[0]
	EndIf
		
	x 			= 0
	Min_wert   = 0
	Max_wert   = 0
	Mittelwert = 0

	Min_Wert   = PInput[1]
   Max_Wert   = PInput[1]
   Mittelwert = 0
	
	For n = 1 To Use_Channel
		If Min_Wert > PInput[n] Then Min_Wert = PInput[n]
		If Max_Wert < PInput[n] Then Max_Wert = PInput[n]	
		Summe = Summe + PInput[n]
	Next
	
	Mittelwert = Summe / Use_Channel
	
	POutput[0] = Max_Wert
  	POutput[1] = Mittelwert
  	POutput[2] = Min_Wert
  	
  	If PUser[1] = 1 Then
		If Min_Wert < Max_Wert Then
  			For n = 1 To Use_Channel
				If PInput[n] >= Max_wert Then
					x = (n * 2) + 1
					POutput[x] = 5
					x = x + 1
					POutput[x] = 0
				ElseIf PInput[n] <= Min_Wert Then
					x = (n * 2) + 1
					POutput[x] = 0
					x = x + 1
					POutput[x] = 5
				Else
					x = (n * 2) + 1
					POutput[x] = 0
					x = x + 1
					POutput[x] = 0
				EndIf
  			Next 			
		Else 
			' alle Kanäle haben den gleichen Wert (Min=Max)
  			For n = 1 To Use_Channel
  				x = (n * 2) + 1
  				POutput[x] = 5
  				x = x + 1
  				POutput[x] = 5
  			Next
		EndIf
		' LED's nicht benutzter Kanäle ausschalten
		For n = Use_Channel To PUser[0]
			x = (n * 2) + 3
			POutput[x] = 0
			x = x + 1
			POutput[x] = 0
		Next
  	End If
  	
	
End Sub 

Sub CConfigure (PUser As Double Ptr) Export
	
	'----- aktuelle Werte von PUser an Dialog übergeben -----
	' Kanäle
	If Puser[0] < 2 Then				' PUser[0] muss mind. 2 sein
		Combobox1 = 0					' 2 Kanäle
	Else 
		Combobox1 = PUser[0] - 2	' auf Index der Combobox setzen (0=2 Kanäle 1=3 Kanäle usw.)
	EndIf
	' LED Ausgabe
	Combobox2 = PUser[1]
	'--------------------------------------------------------
	
	'----- Aufruf des Dialog's -----
	DialogBoxParam(GetModuleInstance(), Cast(ZString Ptr,IDD_DLG1), NULL, @DlgProc, NULL)
	'-------------------------------
	 
	'----- neue Werte an PUser übergeben -----  	
  	PUser[0] = Combobox1 + 2	' Kanäle: +2 wegen Index von Combobox (0-46)
  	PUser[1] = Combobox2			' LED Ausgabe Ja=1/Nein=0
	'-----------------------------------------
	
End Sub

End Extern

Function DlgProc(ByVal hDlg As HWND, _
					  ByVal uMsg As UINT, _
					  ByVal wParam As WPARAM, _
					  ByVal lParam As LPARAM) As Integer
					  
	Dim id As Long 
	Dim Event As Long
	Dim n As UByte
	Dim Text As String

	Select Case uMsg
		Case WM_INITDIALOG
			' ------ Comboboxen mit Werten füllen -----
			' Combobox 1
			For n = 2 To 48
				Text = Str(n)
				SendMessage(GetDlgItem(hDlg, IDC_CBO1), CB_ADDSTRING, 0 , StrPtr(Text))
			Next
			' Index setzen
			SendMessage(GetDlgItem(hDlg, IDC_CBO1), CB_SETCURSEL, Combobox1, 0 )
			' Combobox 2
			SendMessage(GetDlgItem(hDlg, IDC_CBO2), CB_ADDSTRING, 0 , StrPtr("Nein"))
			SendMessage(GetDlgItem(hDlg, IDC_CBO2), CB_ADDSTRING, 0 , StrPtr("Ja"))
			' Index setzen
			SendMessage(GetDlgItem(hDlg, IDC_CBO2), CB_SETCURSEL, Combobox2, 0 )
			'	
		' [X] geklickt 
		Case WM_CLOSE
			EndDialog(hDlg, 0)	' Beendet das Dialogfenster
			'
		Case WM_COMMAND
			id = LoWord(wParam)
			Event = HiWord(wParam)
			Select Case id
				' OK Button gedrückt
				Case IDC_BTN1
					' Wert von Combobox an Variable übergeben
					Combobox1 = SendMessage(GetDlgItem(hDlg,IDC_CBO1), CB_GETCURSEL, 0, 0)
					Combobox2 = SendMessage(GetDlgItem(hDlg,IDC_CBO2), CB_GETCURSEL, 0, 0)
					EndDialog(hDlg, 0)	' Beendet das Dialogfenster				
				' Cancel Button gedrückt
				Case IDC_BTN2
					EndDialog(hDlg, 0)	' Beendet das Dialogfenster					
			End Select
		Case WM_SIZE
			'
		Case Else
			Return FALSE
			'
	End Select
	Return TRUE

End Function

	Function GetModuleInstance() As Integer
		
     	Dim mbi As MEMORY_BASIC_INFORMATION
     	
     	VirtualQuery( @DlgProc, @mbi, SizeOf(mbi) )
     	Return Cast(HANDLE ,mbi.AllocationBase)
     	
	End Function 


Hier noch ein Link der evtl. hilft
http://www.willemer.de/informatik/windo ... htm#simple

Ich hoffe ich konnte dir etwas weiterhelfen.
Gruß

Roberto
Beiträge: 116
Registriert: Mittwoch 15. September 2010, 20:34
Wohnort: Graz (Austria)
Kontaktdaten:

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von Roberto » Dienstag 29. November 2011, 21:33

Hallo haben

Herzlichen Dank!!!! :D :D
Ich habe gleich das File vom Compander modifiziert.
(er möge mir verzeihen ;) )

Soweit ich das kurz getestet habe, funktioniert alles!!
Super!

Nochmals herzlichen Dank für dein Mühe ! :)

l.G. Roberto
min_max_Beispiel.prj
(10.47 KiB) 942-mal heruntergeladen

compander
Beiträge: 657
Registriert: Dienstag 14. Oktober 2008, 17:06
Wohnort: Markt Schwaben

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von compander » Dienstag 29. November 2011, 23:03

Hallo Roberto.

Kann mir nicht vorstellen, daß deine .prj funktioniert.
Dafür gibt mehrere Gründe.
a) beim Aufruf des Projektes gibt es eine Fehlermeldung
b) leider hast Du nicht angegeben, mit welcher .DLL Du getestet hast.
Bzw. die .DLL nicht angefügt. Bei mir ist im BSB nur das allgemeine DLL-Symbol.
c) Du hast den Ausgang eines num. Eingabefeldes mit dem Ausgang eines Festwertes zusammengeschloßen.
Dies widerspricht sich. Was soll die nachfolgende Schaltung (z.B. ein Pin der .DLL) damit anfangen?

Bitte deine Schaltung downloaden, und erneut ausprobieren.

Gruß von C :shock: mpander.

tom_g
Beiträge: 215
Registriert: Freitag 31. Oktober 2008, 14:59

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von tom_g » Mittwoch 30. November 2011, 08:20

Hi habe,

lachen ??? Mitnichten, Anerkennung für Deine Ausführung und vielen Dank !
Ich habe das Konzept nun verstanden:

Mein Versuch, den Mechanismus in einfachen Worten zu beschreiben:

beim Click auf den Button "konfigurieren" wird die Routine Cconfigure aufgerufen.
Darin wird zuerst ein Dialogfenster definiert, dann erstellt
Der modifizierbare Inhalt des PL-Speicherbereichs pUser wird in die controls im Dialog hineingeschrieben.
Eine callback Funktion muss bereitgestellt werden, um gezielt auf (Eingabe)Ereignisse in diesem Dialogfenster zu reagieren (die Ereignisse werden von Windows verwaltet, die callbackfunktion muss Windows "bekanntgemacht" werden, es handelt sich bei der callback-Funktion um eine "Software-Interrupt-Routine", welche bei JEDEM von Windows erkanten Ereignis ausgeführt wird. Ereignisse sind MouseClick, drag...Eingaben, ButtonClicks, Timers und so weiter. In dieser Callback-Funktion werden nun die im Dialog eingetippten Daten nach Drücken von ENTER an die vorgesehene Speicherstelle von pUser gespeichert, oder nicht gepeichert, falls ABBRECHEN gedrückt wird.
Beide Ereignisse schliessen danach das Dialog-Fenster. Cconfigure() wird verlassen und PL ist nun im edit mode.
Erst nach START wird CsimStart() einmalig durchlaufen, danach synchron zur Zyklusabarbeitung Ccalculate(). Nach Stop wird einmalig CsimStop() durchlaufen.


En schööne Taag und viele Grüsse von Thomas
Curiousity makes us progress !

habe
Beiträge: 36
Registriert: Samstag 18. Oktober 2008, 18:51

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von habe » Mittwoch 30. November 2011, 11:52

Hallo Thomas,

das hast du sehr schön beschrieben!!

Bis dann
HB

Roberto
Beiträge: 116
Registriert: Mittwoch 15. September 2010, 20:34
Wohnort: Graz (Austria)
Kontaktdaten:

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von Roberto » Donnerstag 1. Dezember 2011, 00:05

Hallo compander
Kann mir nicht vorstellen, daß deine .prj funktioniert.
Bei mir tut sie es :roll:

Bei den Eigenschaften von der dll musst Du den Pfad der dll angeben.
dll ist die letzte von "haben".
Eingestellt auf 23 Kanäle bei den Eigenschaften und alle Pins von meinem Beispiel müssten passen. :roll:

l.G. Roberto

habe
Beiträge: 36
Registriert: Samstag 18. Oktober 2008, 18:51

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von habe » Freitag 2. Dezember 2011, 13:41

Hallo noch mal,

hab den Config - Dialog noch mal erweitert. Es läst sich nun der Use - Pin Ein/Ausschalten.

Dabei gab es aber ein kleines Problem bei der Beschriftung der Eingänge.
„NumInputsEx“ bekommt zwar die richtige Anzahl der Eingänge übergeben, aber „GetInputName“ weis nicht wie sie die Beschriften muss.
Beispiel:
Wird der Use - Pin benutzt, ist der Name des 1. Eingangs „Use“. Eingang 2 K1, Eingang 3 K2 uws. .
Wird der Use - Pin nicht benutzt, muss der Name des 1. Eingangs „K1“ lauten, Eingang 2 K2 usw. .

Da bei der „GetInputName“ die PUser - Variablen nicht übergeben werden, musste ich den Umweg über eine zusätzliche Datei(Buffer) gehen.
In der Datei wird der Wert der Puser - Variable die für das Ein/Ausschalten des Use - Pin zuständig ist gespeichert.
In „GetInputName“ wird der Wert dann wieder eingelesen und die Namen der Eingänge dementsprechend beschriftet.
Das hatt aber den Nachteil, dass man die DLL nur einmal im Projekt benutzen kann. Andere DLL-Bausteine würden auch auf ein und die selbe Datei zugreifen.
Ich hoffe das war einigermaßen verständlich?

Jetzt meine Frage kann man das irgendwie anders lösen, oder kann Abacom die Subroutine "GetInputName" mit der Puser-Variable erweitern.

MFG
HB

Roberto
Beiträge: 116
Registriert: Mittwoch 15. September 2010, 20:34
Wohnort: Graz (Austria)
Kontaktdaten:

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von Roberto » Freitag 2. Dezember 2011, 19:02

Hallo habe
hab den Config - Dialog noch mal erweitert. Es läst sich nun der Use - Pin Ein/Ausschalten.
Warum dieser Aufwand?
Macht ja nix, wenn der USE -Pin sichtbar ist ?
l.G. Roberto

habe
Beiträge: 36
Registriert: Samstag 18. Oktober 2008, 18:51

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von habe » Donnerstag 15. Dezember 2011, 20:38

Hallo Roberto,

in diesem Beispiel ist es vieleicht nicht so tragisch.
Es gibt aber bestimmt mal Sachen, wo man eine DLL benötigt, die flexible Einstellungen hat.
Dann ist es für die Übersichtlichkeit schon gut, dass man die Ein- und Ausgänge richtig bezeichnet.
Außerdem reizt es mich, sowas hinzubekommen und ich denke ich habs hinbekommen.
Soweit ich das testen konnte funktioniert das bei mir auch.
Ich häng die DLL mal an, vieleicht will das ja mal jemand testen.

Bis dann
habe
Dateianhänge
MinMaxMittel3.0.dll
(14.5 KiB) 741-mal heruntergeladen

compander
Beiträge: 657
Registriert: Dienstag 14. Oktober 2008, 17:06
Wohnort: Markt Schwaben

Re: höchsten Wert von 23 Leitungen ermitteln ?

Beitrag von compander » Donnerstag 15. Dezember 2011, 21:58

Hallo habe.

Ich habe in der Konfig 8 Schieber gewählt. Und habe desen Ausführungen "länger" gestalltet. Habe dann eine bessere Auflösung.

Bei mir funktionieren "min., max., mittel" genau so, wie es sein soll. Incl. der "Led-Arie".
Habe besten Dank! Kann ich gut (so) gebrauchen.

Gruß von C :shock: mpander.

Antworten

Zurück zu „Makros & Schaltungen“