🔑 VB.NET RFID Scanner – Chips mit dem Arduino Mikrocontroller auslesen

VB.NET RFID Scanner - Chips mit dem Arduino Mikrocontroller auslesen
VB.NET RFID Scanner – Chips mit dem Arduino Mikrocontroller auslesen

RFID Chips mit Visual Basic .NET und dem Arduino Mikrocontroller auslesen

Wer in VB.NET Daten aus einem RFID-Chip auslesen möchte, trifft unter normalen Umständen vermutlich auf die handelsüblichen Geräte. Ruckzuck an den PC angeschlossen sind Sie auch schon startklar, uns die ausgelesenen Daten als Tastatur-Input bereitzustellen. Gleichzeitig liegt genau hier das Problem, jedoch gleich mehr dazu. Im heutigen Beitrag beschäftigen wir uns also mit einem RFID-Scanner der Marke Eigenbau und schauen uns die Verarbeitung mit VB.NET an.

Zu den bekannten Einsatzgebieten der kleinen RFID-Sensoren zählen unter anderem: Zugangs- und Zugriffskontrollen wie z. B. Ticketsysteme und Türen, aber ebenso bei unseren tierischen Freunden und sogar im Ausweis finden Sie Ihre Anwendung. Selbst beim Einkauf können wir mit der RFID-Technologie kontaktlose Bezahlvorgänge durchführen und somit unseren Alltag erleichtern.

💡 Achtung: In diesem Beitrag geht es in erster Linie um die Verarbeitung der RFID-Daten seitens VB.NET. Ich werde in einem zukünftigen Beitrag noch die Seite des Mikrocontrollers (Arduino Nano, Mega, whatever) erläutern. Hier beschäftigen wir uns ein wenig mit den Aspekten wie Handhabung und Sicherheit. Ich verwende in diesem Beitrag Affiliate-Links, womit Du mich vollkommen kostenlos bei einem Kauf über die Links unterstützen kannst.

VB.NET RFID Reader aus dem Handel = meist „Tastatur-a-like only“

Kommen wir nochmal genauer auf das Problem mit der angesprochenen Tastatur-Emulation (wenn das der exakt korrekte Ausdruck ist..) zurück. Wenn wir mit solchen Geräten, bzw. Sensoren wie einem RFID-Scanner arbeiten möchten, dann natürlich so flexibel wie möglich. Man stellt sich also vor, man startet seine Anwendung, lässt Sie in Ruhe laufen und wenn man loslegen will, kommt ein Kollege und möchte sich „eben“ im System anmelden.

Dies funktioniert mit den gängigen Geräten im Discount-Bereich häufig nicht, da Diese zwangsweise eine fokussierte Oberfläche (TextBox, etc.) benötigen. Das ist freilich nicht gerade cool, wenn wir eine Bestellung bearbeiten und zig Daten neu eingeben müssten, nachdem unser Kollege fertig ist. Schöner wäre es hingegen, wenn unser Kollege seinen Chip einscannt, eine kleine Maske kommt und er seine 2–3 Eingaben so erledigen könnte. Anschließend könnten wir dann mit unserer Arbeit fortfahren und wir wären durch.

Sicherlich gibt es vermutlich auch andere Varianten, Welche dann zig andere Funktionen unterstützen, aber hier bewegen wir uns dann auch zumeist im vergleichsweise teureren Preis-Segment. Leider bieten die handelsüblichen Geräte also häufig nur eine Art „nix Halbes und nix Ganzes“-Lösung. Das Gerät emuliert häufig einfach nur eine Art Tastatur, Welche dann die einzelnen Daten-Bestandteile runterschreibt und häufig mit einem „Enter“ bestätigt.

Was benötigen wir für den VB.NET RFID Reader

Bedenke den blauen Hinweis oben, dass wir in diesem Beitrag vorerst nur die VB.NET Seite der Medaille betrachten. Trotzdem möchte ich hier eben noch einmal die verwendeten Dinge auflisten, alles Weitere wird dann in einem zukünftigen Beitrag ergänzend erscheinen.

Wir benötigen also:

  • Einen Mikrocontroller wie z. B. den Arduino Nano in meinem Fall
  • Die Arduino IDE (am häufigsten verwendet)
  • Ein RFID Kit (häufig bestehend aus Sensor, Pins und Chipkarten/Anhänger)
  • Ausreichend Jumper-Kabel (je nach Setup – hier 7 male to female)
  • 1 Mini-USB Kabel zur Verbindung des Arduinos zum PC (eigentlich immer beim Arduino dabei..)

Nachdem wir nun von den Hardware-Komponenten erstmal startklar sind, widmen wir uns nach der Verbindung endlich dem Visual Basic NET Code.

Den RFID Scanner mit unserem PC verbinden

Ebenso einfach wie der oben beschriebene Weg mit den handelsüblichen RFID Scanner-Geräten, verfahren wir auch mit unserem Eigenbau. Verbinde den Arduino mithilfe eines Mini-USB Kabel mit einem USB-Port Deiner Wahl. Es sollte dann ein normales „Pling-Plong“-Geräusch kommen, Welches wie üblich das Anschließen eines neuen Gerätes signalisiert.

Verbindungsprobleme

Natürlich kann auch hier das ein oder andere Problem auf Dich zukommen, so traf es auch mich – Thema Treiber.. Um den typischen CH340 Chip erkennbar und zum Laufen zu bringen, installierst Du den für Dein System passenden Treiber. Danach wirst Du vermutlich zu einem Neustart Deines PCs aufgefordert, Welchen Du auch – um weitere Fehlerquellen zu vermeiden – durchführen solltest.

💡 Achtung: Bei der Treiber-Seite handelt es sich um einen chinesischen Anbieter. Achte auf das für dich passende Paket und verwende ggf. die z. B. in Chrome vorhandene Übersetzungs-Funktion. Grundsätzlich ist das dicke blaue Download-Icon aber nicht zu übersehen. Der „341SER.zip“-Treiber sollte auch für die 340er Variante funktionieren. Gerne würde ich Dir den Treiber ebenfalls zum Download anbieten, aber ich möchte vermeiden, dass Du nachher mit einem veralteten Treiber arbeitest.

Öffne dann einfach die „SETUP.exe“ im „CH341SER“-Ordner und klicke auf „install“:

Arduino USB Treiber Installation CH341SER – VB.NET RFID Scanner

Starte anschließend Deinen PC wie gesagt am besten neu, damit Du keine eventuellen Installations-, bzw. Erkennungsprobleme hast. Danach sollte der CH340 Chip ganz normal als COM-Port im Gerätemanager auftauchen (natürlich nur wenn tatsächlich physisch verbunden – Captain Obvious..):

USB Verbindung vom Arduino CH340 Chip erkannt – VB.NET RFID Scanner

Code – RFID-Daten über VB.NET auslesen

Kommen wir nun zum vermutlich heißt ersehnten VB.NET Code zum Auslesen der jeweiligen RFID-Daten. Im Mittelpunkt aller Dinge steht hier die SerialPort-Klasse, Welche Du ggf. noch via NuGet-Paket installieren musst. Suche dazu am besten im NuGet-Paketmanager nach „System.IO.Ports“, oder verwende diesen Link, dort drin befindet sich die Klasse. Nachdem wir jetzt über die erforderlichen Mittel für die Kommunikation via COM-Ports besitzen, können wir starten.

Lege z. B. eine .NET 6 Windows Forms App an und gehe wie gewohnt mit F7 in den Code hinter der Form. Zuerst legen wir (je nach Belieben/gewünschten Einschränkungen) eine Eigenschaft namens „Connection“ an, Welche unsere SerialPort-Verbindung widerspiegeln wird.

Public Property Connection As SerialPort

Als nächstes fügen wir noch ein „Dictionary“ für eine Zuweisung von Uids (Strings – die Ids der gescannten Chips) zu Nutzern (User-Klasse) hinzu. Beachte hierbei, dass ich mit einer generischen Variante, also einem Interface arbeite, alternativ kannst Du das große „i“ auch weglassen. Die User-Klasse erstellen wir gleich und dient nur zur Veranschaulichung.

Public Property UidsToUser As IDictionary(Of String, User)

Vorbereiten der Verbindung

Erstelle als Nächstes einen Konstruktor für die Form, indem Du „Sub New“ innerhalb der „Form1“-Klasse tippst und mit „Enter“ bestätigst. Dann sollte Visual Studio Dir ein grobes Skelett für den Konstruktor generieren, diesen passen wir wie folgt an:

    Sub New()
        InitializeComponent()
        Connection = New SerialPort("COM3", 9600, Parity.None, 8, StopBits.One)
        AddHandler Connection.DataReceived, AddressOf Connection_DataReceived
    End Sub

Zuerst lassen wir die von Haus aus kommende „InitializeComponent“-Methode unangetastet, da unsere eventuellen Form-Steuerelemente sonst nicht funktionieren würden. Danach instanziieren wir eine neue Instanz der Klasse „SerialPort“ mit einigen Werten.

  • COM3 – steht für den für die Kommunikation zu wählenden COM-Port. In meinem Fall steckt mein Arduino am COM-Port Nr. 3.
  • 9600 – ist die sogenannte Baudrate und regelt die „Kommunikationsgeschwindigkeit“ zwischen Arduino und PC. Achte hier darauf, dass Du den gleichen Wert wie in Deinem Arduino Sketch unter „Serial.Begin(<der Wert>)“ wählst.

Dann stellen wir noch gewisse andere Dinge wie die Parität, die Daten-Bits und die Stop-Bits ein. (Ich erspare Dir jede einzelne Erklärung hier..).

Im letzten Konstruktor-Schritt bezüglich der SerialPort-Verbindung fügen wir auch noch einen Ereignishandler für das „DataReceived“-Ereignis hinzu.

Verbindung starten

Danach können wir einen weiteren Handler generieren, hierbei handelt es sich um den Ereignishandler für das „Form Load“-Ereignis. Darin werden wir dann die Verbindung zum Arduino (über den SerialPort) öffnen, ansonsten können wir natürlich nicht kommunizieren 😉.

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Connection.Open()
    End Sub

Auf Daten reagieren/lauschen

Nun müssen wir den oben zugewiesenen (aber bisher nicht existenten) Ereignishandler für das „DataReceived“-Ereignis erstellen. Das geht erstmal ganz einfach wie folgt:

    Private Sub Connection_DataReceived(sender As Object, e As SerialDataReceivedEventArgs)
        Dim text = Connection.ReadLine().TrimStart().TrimEnd()
        If text.StartsWith("RFID:") Then
            Dim uid = text.Split(":")(1)
            Invoke(Sub() OnUidScanned(uid))
        End If
    End Sub

💡 Achtung: Ich habe seitens des Arduino-Codes sichergestellt, dass wir mit einem Zeilenumbruch arbeiten/kommunizieren. Daher kann ich hier mit dem „ReadLine“-Befehl arbeiten. Beachte allerdings bei Deinen geplanten Projekten, dass das „DataReceived“-Ereignis (wie der Name schon sagt) lediglich sagt: „Ey, hier sind Daten“ – das heißt aber nicht, dass ALLE Daten da sind, die Du Dir vorstellst. Da wir hier aber mit einer kleinen Datenmenge a la „RFID:DieUid“ arbeiten, werden wir hier aller Voraussicht nach kein Problem bekommen. Wenn Du allerdings ellenlange Texte hin und her schiebst, könnte es zu einem Problem werden – aber auch dazu in einem anderen Beitrag mehr..

Nun lesen wir mit „ReadLine“ die Daten ein und „säubern“ Diese anschließend durch Verkettung von „TrimStart“ und „TrimEnd“. Das verhindert unnötige und unerwartete Leerzeichen, kann aber natürlich auch durch saubere Programmierung am Arduino verhindert werden..

Nun vor-verarbeiten

Grundsätzlich haben wir den Text, Welcher vom Arduino kommt endlich vorliegen und können Ihn verarbeiten. Beachte, dass ich hier ein kleines „Protokoll“ einhalte, auch wenn es nur praktisch gesehen aus einem Teil besteht. Ich halte mich an meine Regel, dass ich beim erfolgreichen Einlesen eines RFID-Chips den String „RFID:“ gefolgt von der Uid-Zeichenfolge und einem Zeilenumbruch durch den SerialPort jage.

Ergo muss ich mich natürlich an der Gegenstelle (VB.NET) daran halten und die Daten dementsprechend auslesen und verarbeiten. Das mache ich dann im nächsten Schritt, indem ich prüfe, ob die eingelesenen Daten mit einem „RFID:“ beginnen. Ich splitte also den String anhand des Doppelpunktes und nehme mir den zweiten Teil des Strings als Uid.

Daten an die UI delegieren

Anders als gedacht sollte man hier normalerweise nun nicht mit einer Art „ich update mal jetzt direkt die UI a la Label1.Text = …“ arbeiten. Das liegt daran, dass das Ereignis vom SerialPort (und somit unser Handler) meines Wissens nach auf einem anderen Thread als die UI ausgeführt wird. Von dort aus also nun auf die grafische Oberfläche zuzugreifen sollte aller Wahrscheinlichkeit nach einen „Cross Thread bla blupp“-Fehler auslösen.

Um dies zu vermeiden, verwende ich die „Invoke“-Methode der Form in Kombination mit einem inline definierten Delegaten („Sub() <etc>..“). Dieser Delegat hat einen zugrunde liegenden Aufruf namens „OnUidScanned“ – mit dem passenden String-Parameter. Alternativ könntest Du hier auch mit einem „BeginInvoke“-Aufruf arbeiten, dies lässt den Aufrufer nicht auf den Abschluss des Codes warten.

Reine Erkennung von Uids fertig – und nun?

An dieser Stelle haben wir unser Grundgerüst, was das Auslesen und „parsen“ der Uids der Chips betrifft fertig. Nun wirst Du Dich hoffentlich fragen – ja cool, und was nun? Nur Geduld junger Padawan, es geht direkt weiter. Als Nächstes definieren wir (in .NET-Manier) eine typische Ereignis-Methode namens „On…“. Diese kann bei Bedarf in Sub-Klassen überschrieben werden und dient als Basis für unser eigenes Ereignis.

Erstelle nun am Ende der Datei (da lege ich die Ereignisse eigentlich immer ab) ein Ereignis wie das Folgende. Beachte dabei, dass man normalerweise eine eigene von EventArgs abgeleitete Klasse für die Ereignisinformationen verwenden sollte, darauf habe ich hier verzichtet. Unser Ereignis beinhaltet nur die Uid-Information, also einen simplen String.

Public Event UidScanned As EventHandler(Of String)

Die passende „On“-Methode würde also so aussehen:

    Protected Overridable Sub OnUidScanned(uid As String)
        RaiseEvent UidScanned(Me, uid)
    End Sub

Zu guter Letzt verknüpfen wir nun unser eigens erstelltes Ereignis via Handles-Klausel mit einer passenden Methode als Handler:

    Private Sub Me_UidScanned(sender As Object, uid As String) Handles Me.UidScanned
        Dim user As User = Nothing
        UidsToUser.TryGetValue(uid, user)
        If user Is Nothing Then
            MessageBox.Show("Login failed!")
            Return
        End If
        MessageBox.Show($"Hey {user.Name}!")
    End Sub

Hier initialisieren wir zuerst eine leere Variable namens „User“, Welche anschließend durch die „TryGetValue“-Funktion der generischen Dictionary Klasseninstanz befüllt werden sollte. Wenn kein zur Uid passender Nutzer ermittelt werden konnte, wird hier eine kleine „Login failed!“-Meldung ausgegeben. Ansonsten zeigen wir testweise den Namen des jeweils ermittelten Nutzers an.

💡 Achtung: Hier noch der Hinweis, dass es sich hierbei keinesfalls um einen „production ready“ Code handelt. Das Beispiel dient lediglich zur Veranschaulichung des Empfangs von seriellen Sensordaten via SerialPort. Jeder mit einigermaßen vorhandenen Disassembler-Kenntnissen würde in wenigen Sekunden an die jeweiligen Chip-Uids kommen. Normalerweise sollte das Programm nur als Schnittstelle dienen, also die Daten einlesen und an eine passende (Web-) Schnittstelle zur Verarbeitung weiterleiten. Wenn sicher über Https übertragen, könnte die Schnittstelle also anhand der Uid einen passenden Nutzer aus der Datenbank laden und einen Zugriff ermöglichen. Auch wenn ich diesen Satz hasse: „..aber das würde den Rahmen sprengen“ / „The princess is in another castle“ – wenn Du mich verstehst 😛..

Die User-Klasse

Bevor ich es vergesse, hier noch die verwendete, simple User-Klasse:

Public Class User

    Public Property Name As String

    Sub New(name As String)
        Me.Name = name
    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function

End Class

Weitere Links

Downloads

Wie immer findest Du hier am Schluss den vollständigen Download des (VB.NET) Codes. Ggf. ergänze ich der Vollständigkeit halber trotzdem noch den Arduino-Code, ansonsten wird Dieser später in dem getrennten Arduino-Teil kommen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.