TonUINO Set erweitern - Teil 1 - AZ-Delivery

Der folgende Beitrag wurde uns von dem Gastautoren Bastian Brumbi zur Verfügung gestellt:

Ziel dieser Reihe ist es, das bestehende TonUINO Set um einige Features zu erweitern. Dazu fangen wir erst einmal mit dem Grundkonzept dieses Projekts an. Das Ziel des ersten Teils ist, dass bei Vorhalten einer Karte die entsprechende mp3 Datei abgespielt wird und über die drei zusätzlichen Taster die Lautstärke eingestellt werden kann, die Wiedergabe pausiert und die Karten programmiert werden können.

Um die Sounddateien abzuspielen, benötigen wir den DFplayer aus dem tonUINO Set und eine micro-SD Karte (max. 32GB, FAT32) mit den Dateien. Hier ist es wichtig, dass die Dateien mit Nummern benannt sind („001.mp3“ oder „001name.mp3“), damit der DFPlayer diese lesen kann.

Hardware

Als Erstes die Hardware. Für den Aufbau werden benötigt:

Die Bauteile werden wie folgt verdrahtet:

Mikrocontroller

Modul

Anmerkung

 

D 10

RC522 - SDA

 

 

D 13

RC522 - SCK

D 11

RC522 - MOSI

D 12

RC522 - MISO

-

RC522 - IRQ

Optionaler Interrupt-Pin

 

GND

RC522 - GND

 

D 9

RC522 - RST

3V3

RC522 - 3.3V

5V

DFPlayer - VCC

GND

DFPlayer - GND

D 3

DFPlayer - RX

1kOhm Widerstand

D 2

DFPlayer - TX

 

D 7

Button UP

D 6

Button OK

D 5

Button DWN

Software

Als nächstes das Programm, dafür müssen folgende Libraries zusätzlich installiert werden:

DFRobot DFPlayerMini

MFRC522

Diese können einfach als .zip Datei heruntergeladen und in der Arduino IDE hinzugefügt werden. Die Libraries können auch über den integrierten Bibliotheksverwalter installiert werden.

Kopieren oder laden Sie folgendes Programm in die Arduino IDE, wählen Sie den Nano und den richtigen Port aus und laden Sie das Programm hoch.

Falls sie das erste Mal mit dem Nano Mikrocontroller arbeiten, müssen Sie zuerst noch den CH340 Treiber installieren

Im oberen Teil des Programms werden die Libraries eingebunden und Makros für die Pins des Mikrocontrollers definiert.

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include "DFRobotDFPlayerMini.h"
#include <SoftwareSerial.h>
 
#define RST_PIN 9
#define SS_PIN 10
#define UP 7
#define OK 6
#define DWN 5

Nun kommt die Initialisierung der Objekte und Variablen.

SoftwareSerial softSerial(2, 3);
 
DFRobotDFPlayerMini myDFPlayer;
 
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
MFRC522::StatusCode status;
 
byte sector         = 1; //Position im Speicher
byte blockAddr      = 4; 
byte dataBlock[]    = { //Buffer zum beschreiben
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00
};
byte buffer[18]; //Buffer zum lesen
byte trailerBlock = 7;
bool State = true;
int FileCount = 4; //!!!Anzahl an Dateien, bitte anpassen!!!

Die folgende Funktion ist für das Lesen der Daten von der Karte zuständig. Falls die Seriennummer der Karte nicht gelesen werden kann, kann daraus geschlossen werden, dass ein Fehler bei der Kommunikation mit der Karte aufgetreten ist und die Funktion wird durch ein earlyreturn vorzeitig beendet. Danach wird der Schlüssel angewendet und der Inhalt des Speichers in das Array Buffer geschrieben.

void readCard() { //Lesen des RFID Stacks -> Buffer
  if ( ! mfrc522.PICC_ReadCardSerial())
    return; //Karte kann nicht gelesen werden -> Abbruch
 
  byte size = sizeof(buffer);
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &amp;amp;amp;key, &amp;amp;amp;(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &amp;amp;amp;size);
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Read() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
  }
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

In der Methode writeCard() wird genauso wie zuvor die Methode bei einem Lesefehler frühzeitig beendet. Danach wird die Karte authentifiziert und das Array dataBlock in den Speicher geschrieben.

void writeCard() { //Schreiben des dataBlock -> RFID Stack
  if ( ! mfrc522.PICC_ReadCardSerial())
    return; //Karte kann nicht gelesen werden -> Abbruch
 
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &amp;amp;amp;key, &amp;amp;amp;(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Write() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
  }
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

Diese nächste Methode wird ausgeführt, wenn eine neue Karte gescannt wird. Im ersten Schritt wird überprüft, ob der Marker vorhanden ist. Der Marker besteht aus einer im Speicherblock an der Position 0 gespeicherten 1. Ist dieser nicht vorhanden, handelt es sich um eine neue Karte, worauf eine Dateinummer erst neu geschrieben werden muss. Dies ist durch das Drücken der Taster (auswählen und bestätigen) umgesetzt. Falls der Marker vorhanden ist, wird die entsprechende Datei abgespielt.

void startCard() {
  readCard();
  //neue Karte
  if(buffer[0] != 1) { //Marker nicht vorhanden
    myDFPlayer.play(1);
    int i = 1;
    while(true) {
      if(!digitalRead(UP)) {
        while(!digitalRead(UP)) delay(20);
        if(i < FileCount) {
          i+=1;
          myDFPlayer.next();
        }
        else {
          i = 1;
          myDFPlayer.play(1);
        }
      }
      if(!digitalRead(DWN)) {
        while(!digitalRead(DWN)) delay(20);
        if(i > 1) {
          i-=1;
          myDFPlayer.previous();
        }
        else {
          i = FileCount;
          myDFPlayer.play(FileCount);
        }
      }
      if(!digitalRead(OK)) { //bestätigen und beschreiben
        while(!digitalRead(OK)) delay(20);
        dataBlock[0] = 1;
        dataBlock[1] = i;
        while(!mfrc522.PICC_IsNewCardPresent()) delay(20);
        writeCard();
        return;
      }
    }
  }
  //registrierte Karte
  else {
    myDFPlayer.play(buffer[1]);
  }
}

Die Funktion setup() wird nach dem Start einmalig ausgeführt. Hier werden die Startfunktionen der Objekte ausgeführt und der Schlüssel für den Speicher der RFID-Karte ins zugehörige Array geschrieben.

void setup() {
    softSerial.begin(9600);
    Serial.begin(115200);
 
  while(!myDFPlayer.begin(softSerial, false, false)) {
    Serial.println(F("Unable to begin"));
    delay(1000);
  }
  
  SPI.begin();
  mfrc522.PCD_Init();
 
  for (byte i = 0; i < 6; i++) {
      key.keyByte[i] = 0xFF;
  }
  pinMode(UP, INPUT_PULLUP);
  pinMode(OK, INPUT_PULLUP);
  pinMode(DWN, INPUT_PULLUP);
 
  myDFPlayer.volume(5);
}

Die loop() ist die Funktion, welche nach dem setup() permanent wiederholt wird. Wenn eine neue Karte erkannt wird, wird die Methode startCard() aufgerufen. Wenn ein Taster gedrückt wurde, wird dementsprechend die Datei pausiert, beziehungsweise fortgesetzt, oder die Lautstärke verändert.

void loop() {
  if (mfrc522.PICC_IsNewCardPresent()) { //Karte erkannt
    startCard();
  }
  if(!digitalRead(UP)) {
    while(!digitalRead(UP)) delay(20); //warten bis Taster losgelassen wurde
    myDFPlayer.volumeUp();
  }
  if(!digitalRead(DWN)) {
    while(!digitalRead(DWN)) delay(20); //warten bis Taster losgelassen wurde
    myDFPlayer.volumeDown();
  }
  if(!digitalRead(OK)) {
    while(!digitalRead(OK)) delay(20); //warten bis Taster losgelassen wurde
    if(State) {
      myDFPlayer.pause();
      State = 0;
    }
    else {
      myDFPlayer.start();
      State = 1;
    }
  }
}

Bedienung

Halten Sie als Nächstes eine unbeschriebene RFID Karte an das MFRC522-Modul, danach können Sie über die äußeren Taster die zu spielende mp3-Datei auswählen. Die aktuell ausgewählte Datei wird daraufhin abgespielt. Haben Sie die richtige Datei ausgewählt, bestätigen Sie dies durch das Drücken des mittleren Buttons. Entfernen Sie die Karte und halten Sie diese noch einmal vor das Modul. Nun ist im 1kByte Speicher des Tags die Nummer der zu spielenden Datei gespeichert und wird beim erneuten Vorhalten der Karte abgespielt.

Falls Sie eine neue Datei auf die Karte schreiben wollen, können Sie den Speicher der Karte einfach über eine kostenlose App, wie zum Beispiel NFC Tools, formatieren (ANDERE -> Formatiere Speicher) und die vorherigen Schritte wiederholen.

In den folgenden Teilen werden wir unser bisheriges Projekt mit zusätzlichen Funktionen und Modulen erweitern. Unter anderem ein OLED-Display und einen LED-Ring, um damit den Fortschritt, Status und Namen anzuzeigen.

Viel Spass beim Nachbauen :)

Für arduinoProjekte für anfänger

4 commenti

Andreas Wolter

Andreas Wolter

@Michael: Danke für den Hinweis. Wir haben das in der Quelldatei korrigiert. Da haben sich Hilfszeichen zum Referenzierer hinzugesellt, die dort nicht hingehören.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Michael

Michael

Hallo,

vielen Dank für die tolle Arbeit an diesem Projekt.

Wenn jemand die einzelnen Teile Schrittweise nachbauen möchte, muss der Code aus Teil 1 ein wenig angepasst werden, ansonsten wird in der Arduino IDE das Kompilieren mit Fehlermeldung abgebrochen.
In den Zeilen 40, 46 und 59 hat sich ein Fehler eingeschlichen und es muss jeweils die Zeichenfolge “amp;amp;amp;” gelöscht werden:

Zeile 40 und 59:
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &amp;amp;key, &amp;amp;(mfrc522.uid));

Korrektur:
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));

Zeile 46:
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &amp;amp;size);

Korrektur:
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);

Viele Grüße
Michael

Andreas Wolter

Andreas Wolter

@Oliver: es gibt keine blöden Fragen. Für solch einen Fall ist sie tatsächlich berechtigt. Ja über den Empfänger wird im Transponder induktiv eine Spannung erzeugt. Dadurch fließt Strom und der Chip kann seine Daten übertragen (wenn es sich wie hier um ein passives System handelt).
Rein theoretisch ist die Feldstärke zu schwach, um den Inhalt eines Magnetbandes zu verändern. Dazu kommt die erzeugte Frequenz, die von der Frequenz abweicht, die den Inhalt des Magnetbandes verändern kann.
Es lässt sich natürlich nicht 100%ig ausschließen. Aus meiner Erfahrung konnten RFID-Karten zusammen mit Bankkarten in einer Geldbörse den Magnetstreifen auf den Bankkarten ebenfalls nicht verändern.
Um wirklich sicher zu gehen, müssten Sie Tests durchführen.

Hier finden Sie noch einmal Details zur RFID Technik:
https://www.rfid-basis.de/rfid-technik.html

Hier sind berechnungen zur Feldstärke von RFID enthalten:
https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/ElekAusweise/RFID/Mars_Teilbericht_1Therorie_pdf.pdf?__blob=publicationFile&v=1

Grüße,
Andreas Wolter
AZ-Delivery Blog

Oliver

Oliver

Ich habe mir das TonUINO Set bestellt und freue mich eigentlich schon sehr das Projekt nachzubauen und später mal für meinen Bedarf zu erweitern/umzubauen.

Leider habe ich bisher genau 0 Erfahrung mit der RFID Technik und daher eine (blöde?) Frage:
Soweit ich es verstehe, werden die RFID Tags durch das Lesegerät induktiv mit Strom versorgt, es entsteht also ein Magnetfeld. Ist dieses Magnetfeld geeignet um Magnetbänder (hier Audiokassetten) zu beschädigen? Konkret habe ich vor meine Hörspielsammlung zu digitalisieren und jeder Kassette einen RFID Tag zu verpassen. Der Tag würde dann (als Karte) zwischen Cover und Kassette liegen, das ganze dann in der entsprechenden Hülle, welche dann auf dem Lesegerät liegen würde. Geht das? Oder laufe ich Gefahr meine wertvollen Kassetten zu beschädigen?

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione