Hallo,
für diejenigen, die lieber selber ein Wiegand-Interface basteln möchten, als sich ein fertiges zu kaufen, habe ich hier mal meinen ersten Arduino-Versuch reingestellt, da sich nach einem Gewitter die Tür nicht mehr öffnen ließ und ich nicht wusste, ob Fingerabdruckscanner oder Wiegand-Interface defekt sind. Um die Kosten im Rahmen zu halten, habe ich dann einfach mal für ein paar Euro ein Arduino Nano gekauft und mit folgendem Quellcode zum laufen gebracht:
long previousMillis = 0;
int interval = 200;
boolean opener = false;
boolean alarm = false;
volatile long bit_holder = 0;
volatile int bit_count = 0;
volatile long ausgabe = 0;
void DATA0(void) {
bit_count++;
bit_holder = bit_holder << 1;
previousMillis = millis();
}
void DATA1(void) {
bit_count++;
bit_holder = bit_holder << 1;
bit_holder |= 1;
previousMillis = millis();
}
void clearinterrupts () {
for(int i = 2; i<4; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH);
digitalWrite(i, LOW);
pinMode(i, INPUT);
digitalWrite(i, HIGH);
}
delay(10);
}
void setup()
{
Serial.begin(57600);
clearinterrupts();
pinMode(4, INPUT); // OPENER
pinMode(5, INPUT_PULLUP); // ALARM
attachInterrupt(0, DATA0, FALLING);
attachInterrupt(1, DATA1, FALLING);
delay(10);
Serial.println("Wiegand Interface V 0.01 by Olaf Jaster successfully initialized");
}
void loop() {
if (millis() - previousMillis > interval) {
bit_count = 0;
bit_holder = 0;
previousMillis = millis();
}
// 26 Bit Wiegand vollständig
if (bit_count >= 26) {
previousMillis = millis();
Serial.print("<");
Serial.print(bit_holder);
Serial.println(">");
bit_count = 0;
bit_holder = 0;
delay(100);
}
// Prüfen, ob neues Türöffnersignal - Wechsel von LOW auf HIGH = Türöffnersignal
if ((!opener) && (digitalRead(4) == HIGH)) {
opener = true;
Serial.println("<OPENER>");
}
if ((opener) && (digitalRead(4) == LOW)) {
opener = false;
}
// Prüfen, ob neues Alarmsignal
if ((!alarm) && (digitalRead(5) == LOW)) {
alarm = true;
Serial.println("<ALARM>");
}
if ((alarm) && (digitalRead(5) == HIGH)) {
alarm = false;
}
}
Auf die Überprüfung der Prüfziffern (1. und letztes Bit) habe ich verzichtet, diese werden einfach mit eingerechnet und somit an IPSymcon übergeben. Auch bei Übertragungsfehlern könnte ich die Daten sowieso nicht nochmal vom Scanner anfordern, somit lohnte sich für mich der Aufwand dafür nicht. Aber wenn das jemand machen möchte, könnt ihr natürlich die notwendigen Routinen hier gerne ergänzen 
Und hier das dazugehörige Skript für IP-Symcon:
<?
// Hier werden die einzelnen IDs hinterlegt, die vom Fingerabdruckscanner
// zurückgeliefert werden können
// Achtung! Auch die ID nicht freigeschalteter RFID-Token wird übermittelt
// Deswegen unbedingt den Wert prüfen, ansonsten könnte man durch Manipulation
// am Scanner ggfs. die Tür öffnen!
// Bei Wiegand 26 sind das erste und das letzte Bit jeweils Prüfbits,
// die übrigen 24 Bit enthalten die Nutzdaten.
// Die ersten 13 Bits müssen eine gerade Anzahlvon Einsen enthalten,
// die zweiten 13 Bits eine ungerade Anzahl von Einsen
// Wenn bspw. für einen Token vom Hersteller angegeben wird, dass er
// die ID 8354457 hat, wäre das binär 011111110111-101010011001
// Die ersten 12 Bits enthalten eine gerade Anzahl von Einsen, es wird
// also eine 0 vorangestellt.
// Die zweiten 12 Bits enthalten auch eine gerade Anzahl von Einsen, es
// wird eine 1 angehängt.
// Die über Wiegand-Interface übermittelte ID ist also 0-011111110111-101010011001-1
// umgerechnet in Dezimalschreibweise: 16708915
// Wer sich die Arbeit nicht machen möchte, kann auch einfach den Fingerabdruckscanner
// benutzen und den im Log angezeigten Wert übernehmen
$IDs = array("12345", // RFID-12345
23456"); // RFID-23456
// Hier werden die Namen der booleschen Variablen hinterlegt über die
// gesteuert wird, ob ein User / RFID-Token aktuell die Tür öffnen darf.
// Die Variablen können bspw. zeitgesteuert auf FALSE oder TRUE gesetzt
// werden, um nachts den Zugriff zu verbieten und morgens wieder zu erlauben o. Ä.
$Namen = array("RFID-Token-Olaf",
"Schliess-Token");
// Hier werden die dazugehörigen Aktionen hinterlegt
// z. B. kann mit dem Zeigefinger die Tür geöffnet werden, mit dem
// Mittelfinger verriegelt werden und mit dem Daumen die Alarmanlage
// scharfgeschaltet werden.
// Oder ein frei zugänglicher RFID-Token wird zum Verriegeln der Tür
// verwendet.
$Aktionen = array("OEFFNE",
"SCHLIESSE");
// RegVarID ermitteln - wird später zum Löschen des Buffers benötigt
$RegVarID = $IPS_INSTANCE;
echo "Neuer Wert von serieller Schnittstelle: <",$IPS_VALUE,">
";
// Die Daten kommen in zwei Schritten über die serielle Schnittstelle
// im ersten Datensatz wird die ID des Fingerabdrucks bzw. des RFID-Tokens
// übertragen. Im zweiten Datensatz kommt die Signalisierung vom Scanner,
// dass entweder eine gültiger Fingerabdruck oder RFID-Token erkannt wurde
// (Türöffnersignal) oder dass ein Manipulationsversuch erkannt wurde (Alarmsignal)
// oder auch keine Signalisierung (kein bekannter RFID-token)
// Die im ersten Schritt ermittelten Informationen zur Person, der gewünschten Aktion
// usw. werden aus den zentralen IPSymcon-Variablen zurückgelesen
$Person = GetValueString(41802 /*[Haustuer\Person]*/);
$Aktion = GetValueString(42791 /*[Haustuer\Aktion]*/);
// Soll ein Alarm ausgelöst werden? Z. B. zu viele Scan-Fehlversuche
if ($IPS_VALUE == "ALARM") {
// Ausführen von Alarmaktionen - z. B. Sabotagekontakt einer Alarmanlage schließen
// Alarmanruf tätigen o. Ä.
} else {
// Kein Alarm, prüfen, ob geöffnet werden soll
if ($IPS_VALUE == "OPENER") {
// Bei Fingerabdrücken suchen, ob boolesche Variable dazu existiert und die ID merken
$VarID = @IPS_GetVariableIDByName($Person, 32386 /*[Haustuer\Details\Fingerabdrücke]*/);
// Falls kein Fingerabdruck -> weitersuchen bei RFID-Token
if ($VarID === false) {
$VarID = @IPS_GetVariableIDByName($Person, 13014 /*[Haustuer\Details\RFID Token]*/);
}
if ($VarID === false) {
// für diesen RFID-Token bzw. Fingerabdruck gibt es noch keine gültige boolesche Variable
// ggfs. könnte hier auch über IPS_CreateVariable automatisch eine Variable angelegt werden
// Diese sind dann aber evtl. an nicht gewünschter Stelle im Objektbaum. Habe mich daher
// gegen automatische Generierung entschieden.
echo "Person nicht gefunden!
";
} else {
echo "Die Variablen-ID lautet: ", $VarID, "
";
echo $Person," hat Befehl ",$Aktion," gesendet.
";
}
// Soll die Tür geöffnet werden?
if ($Aktion == "OEFFNE") {
// Darf der User / RFID-Token zur Zeit die Tür öffnen? Ist die dazugehörige Variable auf TRUE?
if (GetValueBoolean($VarID) == true) {
// Homematic Türschloss öffnen
// Bei schwierigen Empfangsverhältnissen bis zu 5 Übermittlungsversuche
$Tries = 5;
while ($Tries > 0)
{
$Tries--;
if (HM_WriteValueBoolean(14622 /*[Haustuer\Tuerschloss]*/, "OPEN" , true) == true) {
$Tries = 0;
} else {
IPS_Sleep(2000);
}
}
} else {
echo "Keine Berechtigung zum Öffnen der Tür.
";
}
}
// Soll die Tür verriegelt werden? Das ist jederzeit erlaubt.
// Bei schwierigen Empfangsverhältnissen bis zu 5 Übermittlungsversuche
if ($Aktion == "SCHLIESSE") {
echo "Tür wird verriegelt
";
$Tries = 5;
while ($Tries > 0)
{
$Tries--;
if (HM_WriteValueBoolean(14622 /*[Haustuer\Tuerschloss]*/, "STATE" , false) == true) {
$Tries = 0;
} else {
IPS_Sleep(2000);
}
}
}
// Variable Person und Aktion löschen, damit nicht durch Manipulation die letzten
// User/RFID-Daten verwendet werden können
SetValueString(41802 /*[Haustuer\Person]*/, "");
SetValueString(42791 /*[Haustuer\Aktion]*/, "");
// Buffer löschen
RegVar_SetBuffer($RegVarID, "");
} else {
// Die ID des Fingerabdrucks bzw. des RFID-Tokens ermitteln
// und zwischenspeichern
$PersonID = $IPS_VALUE;
SetValueString(41802 /*[Haustuer\Person]*/, $PersonID);
SetValueString(42791 /*[Haustuer\Aktion]*/, "");
// Den dazugehörigen Namen und die gewünschte Aktion ermitteln und zwischenspeichern
for ($i=1; $i<=count($IDs); $i++)
{
if ($PersonID == $IDs[$i-1]) {
SetValueString(41802 /*[Haustuer\Person]*/, $Namen[$i-1]);
SetValueString(42791 /*[Haustuer\Aktion]*/, $Aktionen[$i-1]);
}
}
} // Ende von Kein Alarm
}
?>
Beim Cut&Paste hat leider die Übersichtlichkeit etwas gelitten, da die Tabs hier im Forum und im IPSymcon-Editor nicht identisch dargestellt werden - daher passen die Einrückungen nicht mehr…
Olaf.