🔑 VB.NET RFID Scanner – Chips mit dem Arduino Mikrocontroller auslesen
Inhaltsverzeichnis
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.
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.
Öffne dann einfach die „SETUP.exe“ im „CH341SER“-Ordner und klicke auf „install“:
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..):
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
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.
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.