Tips & Tricks ALT

ftComputing : Programme für die fischertechnik-Interfaces und -konstruktionskästen
  
ftComputing.de
Home
Back
Drehzahlst.
Sitemap
Index
Links
Impressum
Mail
 

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

Vorbemerkungen

  • 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.

Programmrahmen

  • 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.

Techniken

  1. Statusanzeige
    Do
    lblStatus = ft.GetInputs() & " Status"
    Loop Until ft.GetInput(6)
    '
  2. Analoganzeige
    Do
    lblStatus = ft.GetAnalog(0) & " Wert EX"
    Loop Until ft.GetInput(6)
    '
  3. 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.
    '
  4. 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.
    '
  5. 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
    '
  6. 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
    '
  7. Überfahren eines Tasters
    ft.SetMotor 1, ftiLinks ' Motor einschalten
    ft.WaitForLow 6 ' Eingang E1 wurde überfahren (0/1-Durchgang)
    ' der Motor läuft weiter
    '
  8. 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
    '
  9. 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

  1. Ereignisrahmen - Timer
    Timer Control auf Form : tmrFish
    nach OpenInterface tmrFish.Interval = 300 ' z.B.
    vor CloseInterface tmrFish.Enabled = False
  2. Ereignisrahmen - FishFace-Ereignisroutine
    Private WithEvents ft As clsFishFace
    anstelle der einfachen Deklaration
  3. Status (über Timer)
    If ft.GetInputs() = ftiFehler Then
    lblStatus = "Fehler"
    lblStatus.BackColor= cRot
    ft.NotHalt = True
    End If
    '
  4. 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) :

  1. 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
  2. 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)
  3. 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
  4. 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
  5. 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.