| |
Tips und Tricks für die Programmierung unter Nutzung von FishFace.DLL
Die Tips & Tricks beziehen sich auf die Version 3.1 der FishFace
DLLs FishF532.DLL und FishF632.DLL und die Programmierung in Visual Basic 5 bzw. 6,
können meist aber auch mit anderen Versionen und Sprachen genutzt werden. Ein Test mit
Visual Basic 6 und FishFa50.OCX ergab : geht auch, aber kleine Anpassungen erforderlich
(Control anstelle von ActiveX, keine Deklaration der Klasse clsFishFace mehr, WaitForTime
jetzt Pause, Dim res% jetzt Dim res& ... )
Vorbemerkungen
Programmrahmen
Techniken
Ereignisse
Lampen
Drehzahlsteuerung
- Refresh
Die fischertechnik Interfaces benötigen ca. alle 300 mSek ein Refresh des
Status der (Motor)Ausgänge, sonst werden die Ausgänge abgeschaltet. Das geschieht um das
Modell vor in die Irre gelaufenen Programmen zu schützen. Technisch läßt sich ein
Refresh am einfachsten durch die Methode GetInputs() realisieren, aber auch jede andere
Methode ist dazu geeignet. Meist wird man ohnehin eine Schleifenkonstruktion mit
Statusabfrage im Programm haben, die das dann nebenbei erledigt. Siehe auch die
Codebeispiele weiter unten. Bei den DLLs ab umFish20.DLL und darauf
aufbauendem FishFace wird das in der umFish.DLL erledigt. Im
Anwendungsprogramm sind dann also keine besonderen Maßnahmen
erforderlich.
- Interface Parameter
Das parallele Interface wird in Abhängigkeit von der Geschwindigkeit des
Rechners angesteuert. Wenn das Interface nicht wie gewünscht arbeitet sollten bei
schnellen Rechner die Eigenschaften OutputDelay und AnalogDelay gegenüber den
Defaultwerten erhöht werden.
- Unterbrechbarkeit
Enge Abfrageschleifen führen zu hoher Rechnerauslastung, die eine
Unterbrechbarkeit des Programms (z.B. durch Controls) nicht mehr zulassen. Deswegen sorgt
FishFace intern für eine Unterbrechbarkeit der Anwendung. Man kann diese Eigenschaft
durch einen OpenInterface Parameter oder die Eigenschaft InterruptEnabled (ab)schalten.
Bei umFish.DLL ist das von Haus aus nicht gegeben, hier müssen in das Programm an
geeigneter Stelle DoEvents (Visual Basic) bzw. Application.ProcessMessages (Delphi)
eingefügt werden. Man kann auch einzelne umFish-Funktionen redefinieren und mit
entsprechenden Unterbrechungen versehen (siehe Pneumatics).
- Abbrechbarkeit
Endlos-Abfrageschleifen oder auch langlaufende Methoden (Wait ..., MoveTo) können von
außen nicht einfach beendet werden, sie laufen ggf. sogar noch, wenn die Programm-Form
schon entladen wurde. Außerdem sollte für den Fall eines drohenden Crashes ein NotAus
vorhanden sein. FishFace.DLL kennt hier die Eigenschaft ft.NotHalt, die in allen
"Langläufern" ausgewertet wird. Auf der Form sollte ein Button vorhanden sein,
der die Eigenschaft ft.NotHalt = True setzt (daran denken vor jedem ProgrammStart
ft.NotHalt = False zu setzen). ft.NotHalt kann dann auch in Endlos-Abfrageschleifen
ausgewertet werden. In der Version ab Dez 99 ist außerdem eine Abfrage der Escape-Taste
mit gleicher Wirkung eingebaut. umFish.DLL enthält diese Funktion nicht (es gibt keine
Langläufer). Beispiele sind aber bei Pneumatics zu finden.
- Zeitverhalten
Das InterfacePanel beeinflußt das Zeitverhalten des gesamten Programmes. Wenn
zB. TasterStellungen des Digitaleingangs nicht mehr korrekt erkannt werden, könnte es
daran liegen (andere Fehlerquelle : LPTDelay, Wert erhöhen). Das Refresh-Intervall sollte
nicht unter 150 ms gesetzt werden. Wenn die Fehler weiter auftreten, InterfacePanel
abschalten. Das Problem tritt primär bei dem parallelen Interface auf.
- Drehsinn
Zur Bestimmung des Modellaufbaus müssen die Motoren eindeutig gepolt
werden. Hier wird von linksdrehend gesprochen, wenn der Motor bei Betätigung des
entsprechenden L-Buttons auf dem Interface-Panel in die
gewünschte Richtung dreht.Ggf. ist der Motor umzupolen.
- Deklarationen
In jedem Projekt muß FishFace im Menü : Projekt | Verweise aktiviert
werden.
Um FishFace ansprechen zu können muß außerdem eine entsprechende Objektvariable
angelegt und instanziert werden. Hier :
Private ft As clsFishFace
Set ft = New clsFishFace
und vor Programmende
Set ft = Nothing
- Open/Close
Bevor das Interface angesprochen werden kann, muß es geöffnet werden :
ft.OpenInterface
und zur Freigabe der Schnittstelle wieder geschlossen werden :
ft.CloseInterface
Programmiertechniken - sequentiell
Hinweis der Code der Beispiele ist als durchgehendes VB-Programm in tipstric.zip zu finden.
- Statusanzeige
Do
lblStatus = ft.GetInputs() & " Status"
Loop Until ft.GetInput(6)
'
- Analoganzeige
Do
lblStatus = ft.GetAnalog(0) & " Wert EX"
Loop Until ft.GetInput(6)
'
- NotHalt/Reset
ft.NotHalt = False ' Rücksetzen des NotHaltStatus
'
Private Sub cmdNotAus_Click()
ft.NotHalt = True ' Manuelles Setzen der NotHaltbedingung
End Sub
'
ft.EmergencyStop(8) ' Auswerten NotHalt und/oder Digitaleingang(8)
' Schließt Abschalten aller Motoren ein
Die Langlaufenden Methoden WaitForChange, WaitForLow, WaitForTime und MoveTo/MoveDelta
werten den Status von NotHalt aus und beenden ggf. die Methode. Also vor Aufruf dieser
Methoden sicherstellen, daß NotHalt = False ist.
'
- Fehlerrückmeldungen
Die Mehrzahl der Methoden liefern als Rückgabewert den InputStatus (dem
Zustand aller Digitaleingänge) oder einen Fehlercode (ftiFehler ...), er sollte in
kritischen Fällen, z.B. nach dem OpenInterface, abgefragt werden.
'
- Fahren zum Endtaster
ft.SetMotor 1, ftiLinks ' Motor 1 dreht links
Do
Loop Until ft.GetInput(6) ' bis Eingang 6 True
ft.SetMotor 1, ftiAus ' Motor 1 wieder ausschalten
'
- Fahren (auch Lampe an) für eine vorgegebene Zeit
ft.SetMotor 1,ftiRechts ' Motor/Lampe ein
ft.WaitForTime 3000 ' für 3 Sek
ft.SetMotor 1, ftiAus ' wieder ausschalten
'
- Überfahren eines Tasters
ft.SetMotor 1, ftiLinks ' Motor einschalten
ft.WaitForLow 6 ' Eingang E1 wurde überfahren (0/1-Durchgang)
' der Motor läuft weiter
'
- Fahren um eine vorgegebene Anzahl von Schritten
ft.SetMotor 1, ftiLinks
ft.WaitForChange 3, 5, 1 ' Warten auf 5 Impulse an E3 oder E1=True
ft.SetMotor 1, ftiAus
'
- Fahren auf eine vorgegebenen Position
Der Einsatz der Methode : MoveTo erfordert vorab die Erstellung einer
Motorliste (1-4 Motoren, Master/Slave 1-8). Der jeweilige Motor muß über ein
"Impulsnockenrad"(siehe Robots) einen Taster bedienen und in einer Richtung
einen Endtaster anfahren.
ft.MotCntl.Name(1) = "TestMotor"
ft.MotCntl.Nr(1) = 4 ' --- Motor an Ausgang M4
ft.MotCntl.Impuls(1) ' Nummer des Impulstasters
ft.MotCntl.Ende(1) = -6 ' Endtaster 6, Motor linksdrehend
' --- Home zum ersten Mal anfahren, Nutzung MoveTo,
' Vorgabe einer bewußt falschen Position in Gegenrichtung
' Ein Fahren zum Endtaster (Punkt 5) wäre auch möglich.
If ft.GetInput(6) Then ft.MotCntl.Position(1) = 0 _
Else ft.MotCntl.Position(1) = 9999
ft.MoveTo 0
' --- Position 72 anfahren, anschließend wieder Home
ft.MoveTo 72 ' --- bei mehreren Motoren z.B. ft.MoveTo 72, 0, 100
ft.MoveTo 0 ' --- nach MoveTo sind die Motoren ausgeschaltet
Programmiertechniken - ereignisgesteuert
alternativ über Timer oder Ereignisroutinen
- Ereignisrahmen - Timer
Timer Control auf Form : tmrFish
nach OpenInterface tmrFish.Interval = 300 ' z.B.
vor CloseInterface tmrFish.Enabled = False
- Ereignisrahmen - FishFace-Ereignisroutine
Private WithEvents ft As clsFishFace
anstelle der einfachen Deklaration
- Status (über Timer)
If ft.GetInputs() = ftiFehler Then
lblStatus = "Fehler"
lblStatus.BackColor= cRot
ft.NotHalt = True
End If
'
- Position (über FishFace Ereignisroutine)
ft_PositionChange(PositionListe as Variant)
lblStatus = PositionListe(1)
Das Ereignis wird durch MoveTo ausgelöst
Über den Umgang mit Lampen
Die 4 Digitalausgänge des
Interfaces sind primär zum Schalten von Motoren in zwei Laufrichtungen vorgesehen. Doch
bietet sich zusätzlich die Möglichkeit, Geräte, die nur ein- und ausgeschaltet werden
müssen wie z. B. Lampen an nur einen Pol eines Digitalausganges und die Erde
anzuschließen. Auf diese Weise ist es möglich 8 Lampen mit einem Interface zuschalten.
Hierfür gibt es die umFish.DLL-Funktion SetLamp.
Sollen Lampen gemeinsam (z. B. bei einer Verkehrsampel) geschaltet werden, können sie
auch über die Methode SetMotors geschaltet werden. Dazu sind die entsprechenden einzelnen
Lampenbits im MotorStatus zu setzen.
Es gibt hier Unterschiede zwischen den Interfaces :
Paralleles Interface : Im nicht geschalteten Zustand sind die Lampen aus. M1 vorderer
(gelber) Kontakt : Lampe 1, hinterer (orange) Kontakt Lampe 2 ...
Serielles Interface (30402) : im nicht geschalteten Zustand sind die Lampen an. M1
vorderer Kontakt : Lampe 2, M1 hinterer Kontakt Lampe 1 ...
Also genau hinsehen. Beim seriellen Interface ergibt sich der etwas irritierende
Effekt, daß alle Lampen im Ruhezustand eingeschaltet sind. Außerdem ist zu bedenken,
daß mit SetMotors stets alle M-Ausgänge geschaltet werden.
Hier ein paar Programmzeilen aus dem Beispielprogramm FishLamp
(Fußgängerüberweg mit Bedarfssteuerung, komplette Source in der Version für das
serielle Interface TipsTric.ZIP Basis FishN632.DLL Stand Dez 99, umFish.DLL
Stand Dez 99 vergleichbar) :
- Konstanten zum einfacheren Ansprechen der Funktionen
LampeGrün in M1 vorn, LampGelb in M1 hinten, LampeRot in M2 vorn, LampFuss in M2 hinten.
Version serielles Interface (30402) :
Const lampsAus = &HFFFF&, timeFak = 10
Const ctFuss = 1, ctAbbruch = 8
Const clGruen = 2, clGelb = 1, clRot = 4, clFuss = 3
Const csGrünE = 0, csGrünA = 2, csGelbE = 0, csGelbA = 1, csRotE = 0, csRotA = 8
Const csFussE = 0, csFussA = 4
Version paralleles Interface :
Const lampsAus = 0&, timeFak = 10
Const ctFuss = 1, ctAbbruch = 8
Const clGruen = 1, clGelb = 2, clRot = 3, clFuss = 4
Const csGrünE = 1, csGrünA = 0, csGelbE = 2, csGelbA = 0, csRotE = 4, csRotA = 0
Const csFussE = 8, csFussA = 0
- Nutzung SetMotors, allgemeine
Warteschleife
ft.SetLamp clGruen, ftiEin
Do
If ft.GetInput(ctFuss) And Not WunschFußSperre Then
comFussZyklus
End If
Loop Until ft.NotHalt Or ft.GetInput(ctAbbruch)
- comFussZyklus : Nutzung SetLamp
ft.SetLamp clGruen, ftiAus
ft.SetLamp clGelb, ftiEin
ft.WaitForTime 100 * timeFak
....
Vorteil : einfach zu schreiben, kein Einfluß auf andere M-Ausgänge. Nachteil :
Schreibaufwand
- comFussZyklus : Nutzung SetMotors
ft.SetMotors csGrünA + csGelbE + csRotA + csFussA
ft.WaitForTime 100 * timeFak
....
Vorteil : kompakter, Nachteil : schwerer zu durchschauen, beeinflußt immer alle
M-Ausgänge
- comFussZyklus : mit Sub AmpelTakt
AmpelTakt 100, csGrünA, csGelbE, csRotA, csFussA
....
Private Sub AmpelTakt(TaktZeit, ParamArray Lampen())
Dim i&, p&
p = 0
For i = LBound(Lampen) To UBound(Lampen)
p = p + Lampen(i)
Next i
ft.SetMotors p
ft.WaitForTime TaktZeit * timeFak
End Sub
Vorteil : besonders kompakter Code, von Vorteil, wenn Werte aus File
ausgelesen werden.. Nachteil : sep. Unterprogramm.
|