Quick start
CASH.DLL v4.1.1.5

Schritt für Schritt Anleitung zur Implementierung des CASH-Interface in eigene Anwendungen.

QuickLinks: CASH-Interface   HOPPER-Interface   COUNTER-Board


CASH-Interface

Einbindung CASH.DLL

1. Fügen Sie die Funktion- und Procedure Deklarationen zu Iher USES Klausel hinzu.

Delphi:
implementation
{$R *.DFM}
uses cashdll;


Visual Basic 6:
Fügen Sie einfach die DLL-Import-Unit 'cashdll.bas' zu Ihrem Projekt hinzu:
=> Projekt, Datei hinzufügen, cashdll.bas

Visual Basic .NET:
Fügen Sie einfach die DLL-Import-Unit 'cashdll.vb' zu Ihrem Projekt hinzu:
=> Projekt, Vorhandenes Element hinzufügen, cashdll.vb

Alle Funktionen und Proceduren der CASH.DLL stehen Ihnen jetzt in Ihrem Projekt zur Verfügung.



COM Port zum CASH-Interface öffnen und schliessen

1. Öffen Sie den COM-Port zum CASH-Interface in der OnCreate Routine des Haupformulars

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  CASH_OPENCOM(1);         // COM1 öffnen
  CASH_TOTALBLOCKING_OFF;  // Geräte Freigabe
end;
Visual Basic 6:
Private Sub Form_Load()
  CASH_OPENCOM(1)          'COM1 öffnen
  CASH_TOTALBLOCKING_OFF   'Geräte Freigabe
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  CASH_OPENCOM(1)          'COM1 öffnen
  CASH_TOTALBLOCKING_OFF   'Geräte Freigabe
End Sub
Kann der COM-Port nicht geöffnet werden gibt die Funktion CASH_OPENCOM eine -1 als
Rückgabewert zurück. Dies kann z.B. so geprüft werden:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if CASH_OPENCOM(1) = -1 then 
    MessageDlg('Fehler beim Öffnen des COM-Ports!', mtError, [mbOK], 0) 
  else CASH_TOTALBLOCKING_OFF;
end;
Visual Basic 6:
Private Sub Form_Load()
  If CASH_OPENCOM(1) = -1 Then 
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  ELSE
    CASH_TOTALBLOCKING_OFF
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If CASH_OPENCOM(1) = -1 Then
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  Else
    CASH_TOTALBLOCKING_OFF
  End If
End Sub
Der COM-Port zum CASH-Interface ist nun geöffnet und es können Daten gelesen werden.

2. Schliessen Sie den COM-Port zum CASH-Interface in der OnClose Routine des Haupformulars

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  CASH_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  CASH_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  CASH_CLOSECOM()
End Sub



Daten vom CASH-Interface lesen

1. Definieren Sie globale Variablen die für das Arbeiten mit der CASH.DLL benötigt werden.

Delphi:
var
  Form1     : TForm1;
  iCredits  : Integer;                   // Credits total
  iRead     : Integer;                   // databyte
  iReadLast : Integer;                   // Last databyte
  iParallel : Integer;                   // PARALLEL mode channel no.
  aData     : Array[1..8] of Boolean;    // data flags
  aCoinPayed : Array[1..15] of Boolean;  // Coin payed backup
  aCoinValue : Array[1..15] of Integer;  // PARALLEL mode #1-#6 or 
                                         // BINARY mode coin values #1-#15
  aBillPayed : Array[1..15] of Boolean;  // BINARY bill payed backup
  aBillValue : Array[1..15] of Integer;  // BINARY mode bill values #1-#15
  LowNibble : Byte;                      // BINARY mode lower 4 bits of
                                         // the databyte
Visual Basic 6:
Dim iCredits As Long                     'Credits total
Dim iRead As Long                        'databyte
Dim iReadLast As Long                    'Last databyte
Dim iParallel As Long                    'Parallel value
Dim aData(1 To 8) As Boolean             'data flags
Dim aCoinPayed(1 To 15) As Boolean       'Coin payed backup
Dim aCoinValue(1 To 15) As Long          'PARALLEL mode #1-#6 or 
                                         'BINARY mode coin values #1-#15
Dim aBillPayed(1 To 15) As Boolean       'BINARY mode bill payed backup
Dim aBillValue(1 To 15) As Long          'BINARY mode bill values #1-#15
Dim LowNibble As Long                    'BINARY mode lower 4 bits 
                                         'of the databyte
Visual Basic .NET:
Dim iCredits As Integer                  'Credits total
Dim iRead As Integer                     'databyte
Dim iReadLast As Integer                 'Last databyte
Dim iParallel As Integer                 'Parallel value
Dim aData(8) As Boolean                  'data flags
Dim aCoinPayed(15) As Boolean            'Coin payed backup
Dim aCoinValue(15) As Integer            'PARALLEL mode #1-#6 or 
                                         'BINARY mode coin values #1-#15
Dim aBillPayed(15) As Boolean            'BINARY mode bill payed backup
Dim aBillValue(15) As Integer            'BINARY mode bill values #1-#15
Dim LowNibble As Long                    'BINARY mode lower 4 bits
                                         'of the databyte

2. Plazieren Sie eine Timer Komponente auf dem Hauptformular und setzten Sie den Interval auf 20 ms.

3. Plazieren Sie eine Label Komponente auf dem Hauptformular um die Daten anzuzeigen und bennenen es Label_CASH_READ.

4. Plazieren Sie eine Label Komponente auf dem Hauptformular um die Credite anzuzeigen und bennenen es Label_Credits.

5. Die Werte für Münzen und Geldscheine werden in der Create Methode in ein Array geschrieben.
Im PARRALEL Mode erfolgt die Zuweisung im Array aCoinValue 1-6
Im BINARY Mode erfolgt die Zuweisung im Array aCoinValue 1-15 und aBillValue 1-15

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  ...

  // Beispiel PARALLEL Mode
  aCoinValue[1] := 500;    // Geldscheinprüfer Kanal1 = 5 Euro Schein
  aCoinValue[2] := 1000;   // Geldscheinprüfer Kanal2 = 10 Euro Schein
  aCoinValue[3] := 2000;   // Geldscheinprüfer Kanal3 = 20 Euro Schein
  aCoinValue[4] := 5000;   // Geldscheinprüfer Kanal4 = 50 Euro Schein
  aCoinValue[5] := 100;    // Münzprüfer Kanal5 = 1 Euro Münze
  aCoinValue[6] := 200;    // Münzprüfer Kanal6 = 2 Euro Münze
end;
Visual Basic 6:
Private Sub Form_Load()
...
  'Beispiel PARALLEL Mode
  aCoinValue(1) = 500;     'Geldscheinprüfer Kanal1 = 5 Euro Schein
  aCoinValue(2) = 1000;    'Geldscheinprüfer Kanal2 = 10 Euro Schein
  aCoinValue(3) = 2000;    'Geldscheinprüfer Kanal3 = 20 Euro Schein
  aCoinValue(4) = 5000;    'Geldscheinprüfer Kanal4 = 50 Euro Schein
  aCoinValue(5) = 100;     'Münzprüfer Kanal5 = 1 Euro Münze
  aCoinValue(6) = 200;     'Münzprüfer Kanal6 = 2 Euro Münze
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
...

  'Beispiel PARALLEL Mode
  aCoinValue(1) = 500;     'Geldscheinprüfer Kanal1 = 5 Euro Schein
  aCoinValue(2) = 1000;    'Geldscheinprüfer Kanal2 = 10 Euro Schein
  aCoinValue(3) = 2000;    'Geldscheinprüfer Kanal3 = 20 Euro Schein
  aCoinValue(4) = 5000;    'Geldscheinprüfer Kanal4 = 50 Euro Schein
  aCoinValue(5) = 100;     'Münzprüfer Kanal5 = 1 Euro Münze
  aCoinValue(6) = 200;     'Münzprüfer Kanal6 = 2 Euro Münze
End Sub

In der OnTimer Procedure erfolgt nun das Lesen der Daten vom CASH-Interface.

Delphi:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  Label_CASH_READ.Caption := IntToStr(iRead);
end;
Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  if iRead = iReadLast then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ = iRead
End Sub
Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)
End Sub
Starten Sie nun Ihre Anwendung und beobachten Sie den Datenwert bei Geldeinwurf.



Daten vom CASH-Interface auswerten

1. Der gelesene Datenwert "iRead" muss nun in einzele Bits zerlegt werden.

Der gelesene Datenwert "iRead" setzt sich folgendermaßen zusammen:
Bit1 = Kanal 1
Bit2 = Kanal 2
Bit3 = Kanal 3
Bit4 = Kanal 4
Bit5 = Kanal 5
Bit6 = Kanal 6 (im BINARY Mode Münzprüfer "data valid" Leitung)
Bit7 = BUSY Signal NVx
Bit8 = Stromversorgung ok

Das Zerlegen in Bits wird in der OnTimer Procedure erledigt.

Delphi:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  Label_CASH_READ.Caption := IntToStr(iRead);

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;
end;
Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ = iRead
  
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
End Sub
Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)
		
  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
End Sub
Die einzelnen Bits stehen nach dem Zerlegen im Array aData zur Verfügung.

2. Auswerten der einzelnen Bits

Da alle 20ms mittels CASH_READ der Signalzustand vom CASH-Interface gelesen wird und z.B. ein Münzsignal 150ms dauert müssen wir darauf achten das solch ein Signal nicht 2x gezählt wird. Dies wird erreicht durch Speichern des lezten Zustandes. Wir benutzen auch Bit Nr.8 um die Spannungsversorgung zu erkennen. Da Münz- und Geldscheinprüfer mit ACTIVE LOW (d.h. ein Signal ist 0 Volt) arbeiten würde bei abgeschalteter Stromversorgung ein LOW Signal gemessen und Credite gezählt. Durch eine UND Verknüpfung mit Bit Nr.8 wird dies vermieden.

PARALLEL Modus:
Zuerst wird wird eine Integer Zahl (iParallel) mit dem aktiven Kanal erzeugt, diese Zahl wird gleichzeitig verwendet um den Münz bzw. Geldscheinwert aus dem entsprechenden Array mit den Wertangaben zu lesen.

BINARY Modus:
Zuerst wird wird eine Integer Zahl (LowNibble) mit dem aktiven Kanal erzeugt, diese Zahl wird gleichzeitig verwendet um den Münz bzw. Geldscheinwert aus dem entsprechenden Array mit den Wertangaben zu lesen.

Delphi PARALLEL Mode:
// create a integer value out of the 6 Channels
iParallel := 0;
if aData[1] then iParallel := 1;
if aData[2] then iParallel := 2;
if aData[3] then iParallel := 3;
if aData[4] then iParallel := 4;
if aData[5] then iParallel := 5;
if aData[6] then iParallel := 6;

// we store a backup flag in aCoinPayed to prevent doubble counts

if (iParallel > 0) AND aData[8] then begin     
  if NOT aCoinPayed[iParallel] then begin
    aCoinPayed[iParallel] := true;
    inc(iCredits, aCoinValue[iParallel]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end;
Delphi BINARY Mode:
// We work with the LowNibble => channel1-4, 
// so we can detect 15 different bills and 15 different coins

LowNibble := iRead AND $0F;

// *****************************************************************
//  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
// *****************************************************************

// we store a backup flag in aBillPayed to prevent doubble counts

if (LowNibble > 0) AND aData[8] AND NOT aData[6] then begin
  if NOT aBillPayed[LowNibble] then begin
    aBillPayed[LowNibble] := true;
    inc(iCredits, aBillValue[LowNibble]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end else

// *****************************************************************
//  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
// *****************************************************************

// we store a backup flag in aCoinPayed to prevent doubble counts

if (LowNibble > 0) AND aData[8] AND aData[6] then begin
  if NOT aCoinPayed[LowNibble] then begin
    aCoinPayed[LowNibble] := true;
    inc(iCredits, aCoinValue[LowNibble]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end;

Visual Basic 6 PARALLEL Mode:
' create a integer value out of the 6 Channels
iParallel = 0
If aData(1) Then iParallel = 1
If aData(2) Then iParallel = 2
If aData(3) Then iParallel = 3
If aData(4) Then iParallel = 4
If aData(5) Then iParallel = 5
If aData(6) Then iParallel = 6

' we store a backup flag in aCoinPayed to prevent doubble counts

If (iParallel > 0) And aData(8) Then
  If Not aCoinPayed(iParallel) Then
    aCoinPayed(iParallel) = True
    iCredits = iCredits + aCoinValue(iParallel)
  End If
End If
Visual Basic 6 BINARY Mode:
' We work with the LowNibble => channel1-4, 
' so we can detect 15 different bills and 15 different coins
LowNibble = iRead And &HF
  
' *****************************************************************
'  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
' *****************************************************************

' we store a backup flag in aBillPayed to prevent doubble counts

If (LowNibble > 0) And aData(8) And Not aData(6) Then
  If Not aBillPayed(LowNibble) Then
    aBillPayed(LowNibble) = True
    iCredits = iCredits + aBillValue(LowNibble)
  End If

' *****************************************************************
'  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
' *****************************************************************

' we store a backup flag in aCoinPayed to prevent doubble counts

ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
  If Not aCoinPayed(LowNibble) Then
    aCoinPayed(LowNibble) = True
    iCredits = iCredits + aCoinValue(LowNibble)
  End If
End If

Visual Basic .NET PARALLEL Mode:
' create a integer value out of the 6 Channels
iParallel = 0
If aData(1) Then iParallel = 1
If aData(2) Then iParallel = 2
If aData(3) Then iParallel = 3
If aData(4) Then iParallel = 4
If aData(5) Then iParallel = 5
If aData(6) Then iParallel = 6

' we store a backup flag in aCoinPayed to prevent doubble counts

If (iParallel > 0) And aData(8) Then          
  If Not aCoinPayed(iParallel) Then
     aCoinPayed(iParallel) = True
     iCredits = iCredits + aCoinValue(iParallel)
   End If
End If
Visual Basic .NET BINARY Mode:
' We work with the LowNibble => channel1-4, 
' so we can detect 15 different bills and 15 different coins
LowNibble = iRead And &HF

' *****************************************************************
'  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
' *****************************************************************

' we store a backup flag in aBillPayed to prevent doubble counts

If (LowNibble > 0) And aData(8) And Not aData(6) Then
  If Not aBillPayed(LowNibble) Then
    aBillPayed(LowNibble) = True
    iCredits = iCredits + aBillValue(LowNibble)
  End If

' *****************************************************************
'  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
' *****************************************************************

' we store a backup flag in aCoinPayed to prevent doubble counts

ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
  If Not aCoinPayed(LowNibble) Then
    aCoinPayed(LowNibble) = True
    iCredits = iCredits + aCoinValue(LowNibble)
  End If
End If

Hier die komplette OnTimer Procedure für PARALLEL Modus in Delphi:
procedure TForm1.TimerPollTimer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ(comport)"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // stop the timer while working
  TimerPoll.Enabled := false;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  LabelRead.Caption := IntToStr(iRead);

  // clear the backup array if we have no more cash signals
  // 128 = no cash signals  OR  192 = NVx busy
  if ((iRead = 128) OR (iRead = 192)) then begin
    FillChar(aCoinPayed[1], Length(aCoinPayed)*sizeof(aCoinPayed[1]), 0);
  end;  

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;

  // Because we poll every 20 milliseconds and the signal is longer
  // we must prevent to count the same signal twice! The solution is
  // to store the last value. We also use flag no.8 to detect the power 
  // supply. Remember the acceptor works with active LOW, so no power
  // will detect a LOW and would count credits. Using a AND operation 
  // here, it will not count any credits while power failure.
 
  // bit 1 = channel 1
  // bit 2 = channel 2
  // bit 3 = channel 3
  // bit 4 = channel 4
  // bit 5 = channel 5
  // bit 6 = channel 6
  // bit 7 = NV busy
  // bit 8 = power supply ok

  // create a integer value out of the 6 Channels
  iParallel := 0;
  if aData[1] then iParallel := 1;
  if aData[2] then iParallel := 2;
  if aData[3] then iParallel := 3;
  if aData[4] then iParallel := 4;
  if aData[5] then iParallel := 5;
  if aData[6] then iParallel := 6;

  // we store a backup flag in aCoinPayed to prevent doubble counts
 
  if (iParallel > 0) AND aData[8] then begin       
    if NOT aCoinPayed[iParallel] then begin
      aCoinPayed[iParallel] := true;
      inc(iCredits, aCoinValue[iParallel]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end;

  // start the timer again
  TimerPoll.Enabled := true;
end;

Hier die komplette OnTimer Procedure für BINARY Modus in Delphi:
procedure TForm1.TimerPollTimer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ(comport)"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // stop the timer while working
  TimerPoll.Enabled := false;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  LabelRead.Caption := IntToStr(iRead);

  // clear the backup array if we have no more cash signals
  // 128 = no cash signals  OR  192 = NVx busy
  if ((iRead = 128) OR (iRead = 192)) then begin
    FillChar(aCoinPayed[1], Length(aCoinPayed)*sizeof(aCoinPayed[1]), 0);
    FillChar(aBillPayed[1], Length(aBillPayed)*sizeof(aBillPayed[1]), 0);
  end;  

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;

  // Because we poll every 20 milliseconds and the signal is longer
  // we must prevent to count the same signal twice! The solution is
  // to store the last value. We also use flag no.8 to detect the power 
  // supply. Remember the acceptor works with active LOW, so no power
  // will detect a LOW and would count credits. Using a AND operation 
  // here, it will not count any credits while power failure.

  // bit 1 = channel 1
  // bit 2 = channel 2
  // bit 3 = channel 3
  // bit 4 = channel 4
  // bit 5 = not used
  // bit 6 = coin validator binary line
  // bit 7 = NV busy
  // bit 8 = power supply ok

  // We work with the LowNibble => channel1-4, 
  // so we can detect 15 different bills and 15 different coins
  LowNibble := iRead AND $0F;

  // *****************************************************************
  //  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  // *****************************************************************

  // we store a backup flag in aBillPayed to prevent doubble counts

  if (LowNibble > 0) AND aData[8] AND NOT aData[6] then begin
    if NOT aBillPayed[LowNibble] then begin
      aBillPayed[LowNibble] := true;
      inc(iCredits, aBillValue[LowNibble]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end else

  // *****************************************************************
  //  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  // *****************************************************************

  // we store a backup flag in aCoinPayed to prevent doubble counts

  if (LowNibble > 0) AND aData[8] AND aData[6] then begin
    if NOT aCoinPayed[LowNibble] then begin
      aCoinPayed[LowNibble] := true;
      inc(iCredits, aCoinValue[LowNibble]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end;

  // start the timer again
  TimerPoll.Enabled := true;
end;

Hier die komplette Timer Routine für PARALLEL Modus in Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  
  'stop the timer while working
  TimerPoll.Enabled = False
  
  'store the current read byte
  iReadLast = iRead
  
  'show databyte in dezimal view
  Label_CASH_READ.Caption = iRead
  
  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
    Erase aCoinPayed
  End If
    
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
  
  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = channel 5
  'bit 6 = channel 6
  'bit 7 = NV busy
  'bit 8 = power supply ok

  'if this two flags are set to high we have the wrong com port
  If aData(1) And aData(2) Then
    TimerPoll.Enabled = True
    Exit Sub
  End If

  ' create a integer value out of the 6 Channels
  iParallel = 0
  If aData(1) Then iParallel = 1
  If aData(2) Then iParallel = 2
  If aData(3) Then iParallel = 3
  If aData(4) Then iParallel = 4
  If aData(5) Then iParallel = 5
  If aData(6) Then iParallel = 6

  'we store a backup flag in aCoinPayed to prevent doubble counts

  If iParallel > 0 And aData(8) Then 
    If Not aCoinPayed(iParallel) Then
      aCoinPayed(iParallel) = True
      iCredits = iCredits + aCoinValue(iParallel)
    End If
  End If
  
  'show the Credits
  Label_Credits.Caption = iCredits
  
  'start the timer again
  TimerPoll.Enabled = True
End Sub

Hier die komplette Timer Routine für BINARY Modus in Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  
  'stop the timer while working
  TimerPoll.Enabled = False
  
  'store the current read byte
  iReadLast = iRead
  
  'show databyte in dezimal view
  Label_CASH_READ.Caption = iRead
  
  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
    Erase aCoinPayed
    Erase aBillPayed
  End If
    
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
  
  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = not used
  'bit 6 = coin validator binary line
  'bit 7 = NV busy
  'bit 8 = power supply ok
  
  'We work with the LowNibble => channel1-4, 
  'so we can detect 15 different bills and 15 different coins
  LowNibble = iRead And &HF
  
  ' ***********************************************************************
  '  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  ' ***********************************************************************

  ' we store a backup flag in aBillPayed to prevent doubble counts

  If (LowNibble > 0) And aData(8) And Not aData(6) Then
    If Not aBillPayed(LowNibble) Then
      aBillPayed(LowNibble) = True
      iCredits = iCredits + aBillValue(LowNibble)
    End If

  ' ***********************************************************************
  '  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  ' ***********************************************************************

  ' we store a backup flag in aCoinPayed to prevent doubble counts

  ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
    If Not aCoinPayed(LowNibble) Then
      aCoinPayed(LowNibble) = True
      iCredits = iCredits + aCoinValue(LowNibble)
    End If
  End If
  
  'show the Credits
  Label_Credits.Caption = iCredits
  
  'start the timer again
  TimerPoll.Enabled = True
End Sub

Hier die komplette Timer Routine für PARALLEL Modus in Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ

  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub

  'stop the timer while working
  TimerPoll.Enabled = False

  'store the current read byte
  iReadLast = iRead

  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)

  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
      Array.Clear(aCoinPayed, 1, 15)
  End If

  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True

  ' bit 1 = channel 1
  ' bit 2 = channel 2
  ' bit 3 = channel 3
  ' bit 4 = channel 4
  ' bit 5 = channel 5
  ' bit 6 = channel 6
  ' bit 7 = NV busy
  ' bit 8 = power supply ok

  'if this two flags are set to high we have the wrong com port
  If aData(1) And aData(2) Then
    TimerPoll.Enabled = True
    Exit Sub
  End If

  ' create a integer value out of the 6 Channels
  iParallel = 0
  If aData(1) Then iParallel = 1
  If aData(2) Then iParallel = 2
  If aData(3) Then iParallel = 3
  If aData(4) Then iParallel = 4
  If aData(5) Then iParallel = 5
  If aData(6) Then iParallel = 6

  ' we store a backup flag in aCoinPayed to prevent doubble counts
  If (iParallel > 0) And aData(8) Then
    If Not aCoinPayed(iParallel) Then
      aCoinPayed(iParallel) = True
      iCredits = iCredits + aCoinValue(iParallel)
    End If
  End If

  'show the Credits
  Label_Credits.Text = CStr(iCredits)

  'start the timer again
  TimerPoll.Enabled = True
End Sub
Hier die komplette Timer Routine für BINARY Modus in Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ

  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub

  'stop the timer while working
  TimerPoll.Enabled = False

  'store the current read byte
  iReadLast = iRead

  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)

  'clear the backup array if we have no more cash signals
  '128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
      Array.Clear(aCoinPayed, 1, 15)
      Array.Clear(aBillPayed, 1, 15)
  End If

  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True

  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = not used
  'bit 6 = coin validator binary line
  'bit 7 = NV busy
  'bit 8 = power supply ok

  'We work with the LowNibble => channel1-4, 
  'so we can detect 15 different bills and 15 different coins
  LowNibble = iRead And &HF

  '***********************************************************************
  ' BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  '***********************************************************************

  'we store a backup flag in aBillPayed to prevent doubble counts

  If (LowNibble > 0) And aData(8) And Not aData(6) Then
    If Not aBillPayed(LowNibble) Then
      aBillPayed(LowNibble) = True
      iCredits = iCredits + aBillValue(LowNibble)
    End If

  '***********************************************************************
  ' COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  '***********************************************************************

  'we store a backup flag in aCoinPayed to prevent doubble counts

  ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
    If Not aCoinPayed(LowNibble) Then
      aCoinPayed(LowNibble) = True
      iCredits = iCredits + aCoinValue(LowNibble)
    End If
  End If

  'show the Credits
  Label_Credits.Text = CStr(iCredits)

  'start the timer again
  TimerPoll.Enabled = True
End Sub


HOPPER-Interface:

COM Port zum HOPPER-Interface öffnen und schliessen

1. Öffen Sie den COM-Port zum HOPPER-Interface in der OnCreate Routine des Haupformulars

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  HOPPER_OPENCOM(1);         // COM1 öffnen
end;
Visual Basic 6:
Private Sub Form_Load()
  HOPPER_OPENCOM(1)          'COM1 öffnen
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  HOPPER_OPENCOM(1)          'COM1 öffnen
End Sub
Kann der COM-Port nicht geöffnet werden gibt die Funktion HOPPER_OPENCOM eine -1 als
Rückgabewert zurück. Dies kann z.B. so geprüft werden:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if HOPPER_OPENCOM(1) = -1 then 
    MessageDlg('Fehler beim Öffnen des COM-Ports!', mtError, [mbOK], 0);
end;
Visual Basic 6:
Private Sub Form_Load()
  If HOPPER_OPENCOM(1) = -1 Then 
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If HOPPER_OPENCOM(1) = -1 Then
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  End If
End Sub
Der COM-Port zum HOPPER-Interface ist nun geöffnet.

2. Schliessen Sie den COM-Port zum HOPPER-Interface in der OnClose Routine des Haupformulars

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  HOPPER_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  HOPPER_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  HOPPER_CLOSECOM()
End Sub



Münzen auszahlen

Die einfachste Art Münzen auszuzahlen ist die Verwendung der Funktion HOPPER1_PAYOUT(n) für Hopper1 und HOPPER2_PAYOUT(n) für Hopper2.

Delphi:
  Label_HOPPER1_PAYOUT.Caption := IntToStr(HOPPER1_PAYOUT(1));
  Label_HOPPER2_PAYOUT.Caption := IntToStr(HOPPER2_PAYOUT(1));
Visual Basic 6:
  Label_HOPPER1_PAYOUT.Caption = HOPPER1_PAYOUT(1)
  Label_HOPPER2_PAYOUT.Caption = HOPPER2_PAYOUT(1)
Visual Basic .NET:
  Label_HOPPER1_PAYOUT.Text = CStr(HOPPER1_PAYOUT(1))
  Label_HOPPER2_PAYOUT.Text = CStr(HOPPER2_PAYOUT(1))

Weitere Möglichkeiten und Infos siehe Referenz CASH.DLL, Tipps zur Hopper Steuerung



COUNTER-Board:

COM Port zum COUNTER-Board öffnen und schliessen

1. Öffen Sie den COM-Port zum COUNTER-Board in der OnCreate Routine des Haupformulars

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  COUNTER_OPENCOM(1);         // COM1 öffnen
end;
Visual Basic 6:
Private Sub Form_Load()
  COUNTER_OPENCOM(1)          'COM1 öffnen
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  COUNTER_OPENCOM(1)          'COM1 öffnen
End Sub
Kann der COM-Port nicht geöffnet werden gibt die Funktion COUNTER_OPENCOM eine -1 als
Rückgabewert zurück. Dies kann z.B. so geprüft werden:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if COUNTER_OPENCOM(1) = -1 then 
    MessageDlg('Fehler beim Öffnen des COM-Ports!', mtError, [mbOK], 0);
end;
Visual Basic 6:
Private Sub Form_Load()
  If COUNTER_OPENCOM(1) = -1 Then 
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If COUNTER_OPENCOM(1) = -1 Then
    MsgBox "Fehler beim Öffnen des COM-Ports!"
  End If
End Sub
Der COM-Port zum COUNTER-Board ist nun geöffnet.

2. Schliessen Sie den COM-Port zum COUNTER-Board in der OnClose Routine des Haupformulars

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  COUNTER_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  COUNTER_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  COUNTER_CLOSECOM()
End Sub



Zählen

Zählvorgänge werden mit der Funktion COUNTER_COUNT1(COUNT, SPEED) für Zähler 1 und
COUNTER_COUNT2(COUNT, SPEED) für Zähler 2 ausgeführt.

Delphi:
  COUNTER_COUNT1(1, 50);
  COUNTER_COUNT2(1, 50);
Visual Basic 6:
  Call COUNTER_COUNT1(1, 50)
  Call COUNTER_COUNT2(1, 50)
Visual Basic .NET:
  COUNTER_COUNT1(1, 50)
  COUNTER_COUNT2(1, 50)



Hinweis: Beispielprojekte mit Quellcode für Delphi, Visual Basic 6 und Visual Basic .NET
finden Sie im entsprechendem Unterverzeichnis /example


Copyright © 2009 by bksoft