Compare commits

..

2 Commits

Author SHA1 Message Date
Stefan Ostermann 0f47f29c74 RFID 2023-06-28 23:47:52 +02:00
Stefan Ostermann cb3b817295 wiprfid 2023-06-27 23:29:44 +02:00
4 changed files with 182 additions and 187 deletions

View File

@ -27,6 +27,64 @@ CLK -> 18 (D5)
MISO -> 19 (D6) MISO -> 19 (D6)
``` ```
### RFID Reader
```
```
#### Registers
```
Writing 0x7F to the "ComIEnReg" means the following:
Bit 7: IRqInv=0 - Interrupts are active high
Bit 6: TxIEn=1 - Transmitter interrupt is enabled
Bit 5: RxIEn=1 - Receive interrupt is enabled
Bit 4: IdleIEn=1 - Idle interrupt is enabled
Bit 3: HiAlertIEn=1 - "High Alert" interrupt is enabled
Bit 2: LoAlertIEn=1 - "Low Alert" interrupt is enabled
Bit 1: ErrIEn=1 - Error interrupt is enabled
Bit 0: TimerIEn=1 - Timer interrupt is enabled
The bits in the register "ComIrqReg" have the following meaning:
Bit 7: Set1 - when written as 1, a bit value of 1 in bits 6-0 of the byte written set the corresponding register bit; when written as 0, bits 6-0 clear the corresponding register bit
Bit 6: TxIRq - Set when the last bit of Tx data has been sent
Bit 5: RxIRq - Set when the receiver detects the end of a valid data stream
Bit 4: IdleIRq - Set when the CommandReg changes the command field to the idle command
Bit 3: HiAlertIRq - Set when the Status1 register HiAlert bit is set
Bit 2: LoAlertIRq - Set when the Status1 register LoAlert bit is set
Bit 1: ErrIRq - Set when any bit in ErrorReg gets set
Bit 0: TimerIRq - Set when the TCounterValReg decrements to zero
Writing 0x14 to the "DivIEnReg" has the following meaning:
Bit 7: IRQPushPull=0 - IRQ is an open-drain output pin
Bit 6: reserved=0 - no known effect
Bit 5: reserved=0 - effect unknown
Bit 4: MfinActEn=1 - Allow the MFIN active interrupt request to trigger IRQ
Bit 3: reserved=0 - boundedly undefined
Bit 2: CRCIEn=1 - Permit the "DivIrqReg" bit CRCIRq to trigger IRQ
Bit 1: reserved=0 - do not set to 1 on pain of nothing
Bit 0: reserved=0 - has no purpose other than to confuse
The register "DivIrqReg" corresponds to "DivIrqEn", and has the following bit definitions:
Bit 7: Set2 - when written as 1, a bit value of 1 in bits 6-0 of the byte written set the corresponding register bit; when written as 0, bits 6-0 clear the corresponding register bit
Bit 6: reserved - don't ask
Bit 5: reserved - don't tell
Bit 4: MfinActIRq - MFIN is active
Bit 3: reserved - just leave it at zero and back away slowly
Bit 2: CRCIRq - when 1, the CalcCRC command is active and all data is processed
Bit 1: reserved - nothing to see here
Bit 0: reserved - are you feeling lucky, punk?
```
Interrupt method was not working because it seems reading a card does not trigger one.
See https://arduino.stackexchange.com/a/76285 and https://github.com/miguelbalboa/rfid/blob/master/examples/MinimalInterrupt/MinimalInterrupt.ino
## Buttons ## Buttons
``` ```

View File

@ -5,11 +5,31 @@ void stop();
void start(); void start();
void loop2(void* parameter);
boolean buttonPressed(const uint8_t pin); boolean buttonPressed(const uint8_t pin);
/**
* Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize)
{
for (byte i = 0; i < bufferSize; i++)
{
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
String getRFIDString(byte uidByte[10])
{
String uidString = String(uidByte[0]) + " " + String(uidByte[1]) + " " +
String(uidByte[2]) + " " + String(uidByte[3]);
return uidString;
}
unsigned long lastStart = 0; unsigned long lastStart = 0;
const int startDelay = 250; const int startDelay = 250;
#endif #endif

View File

@ -1,95 +0,0 @@
#ifndef HELPER_H_
#define HELPER_H_
#include <SD.h>
#include "globals.h"
struct DirectoryNode {
String name;
std::vector<DirectoryNode*> subdirectories;
std::vector<String> mp3Files;
String* currentPlaying;
};
void buildDirectoryTree(DirectoryNode* currentNode, const char* currentPath) {
File root = SD.open(currentPath);
while (true) {
File entry = root.openNextFile();
if (!entry) {
break;
}
if (entry.isDirectory()) {
DirectoryNode* newNode = new DirectoryNode;
newNode->name = String(currentPath) + entry.name();
currentNode->subdirectories.push_back(newNode);
buildDirectoryTree(newNode, (String(currentPath) + entry.name()).c_str());
} else if (String(entry.name()).endsWith(".mp3")) {
currentNode->mp3Files.push_back(entry.name());
}
entry.close();
}
root.close();
}
void printDirectoryTree(DirectoryNode* currentNode, int level = 0) {
for (int i = 0; i < level; i++) {
Serial.print(" ");
}
Serial.println(currentNode->name);
for (const String& mp3File : currentNode->mp3Files) {
for (int i = 0; i <= level; i++) {
Serial.print(" ");
}
Serial.println(mp3File);
}
for (DirectoryNode* childNode : currentNode->subdirectories) {
printDirectoryTree(childNode, level + 1);
}
}
void advanceToNextMP3(DirectoryNode* currentNode) {
if (currentNode->currentPlaying != nullptr) {
for (size_t i = 0; i < currentNode->mp3Files.size(); i++) {
if (*currentNode->currentPlaying == currentNode->mp3Files[i]) {
// Found the current playing MP3 file
if (i < currentNode->mp3Files.size() - 1) {
// Advance to the next MP3 file in the same directory
currentNode->currentPlaying = &currentNode->mp3Files[i + 1];
return;
}
// Reached the end of the MP3 files in the directory
break;
}
}
}
// If not playing or reached the end, set the first MP3 file as the current playing
if (!currentNode->mp3Files.empty()) {
currentNode->currentPlaying = &currentNode->mp3Files[0];
}
}
DirectoryNode* findFirstMP3Node(DirectoryNode* currentNode) {
if (!currentNode->mp3Files.empty()) {
return currentNode;
}
for (DirectoryNode* subdirectory : currentNode->subdirectories) {
DirectoryNode* tempNode = findFirstMP3Node(subdirectory);
if (!tempNode->mp3Files.empty()) {
return tempNode;
}
}
return NULL;
}
#endif /* HELPER_H_ */

View File

@ -9,15 +9,12 @@
#include "Audio.h" #include "Audio.h"
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
#include <MFRC522.h>//RFID Reader #include <MFRC522.h> //RFID Reader
// define pins for RFID // define pins for RFID
#define CS_RFID 32// SIC, tried 4 and 32 but only this worked! #define CS_RFID 32 // SIC, tried 4 and 32 but only this worked!
#define RST_RFID 33 #define RST_RFID 33
#define IRQ_RFID 34 #define IRQ_RFID 34
@ -30,20 +27,20 @@
#define CS_SDCARD 22 #define CS_SDCARD 22
#define RFID_LOOP_INTERVAL 10
#include "globals.h" #include "globals.h"
#include "WebContent.h" #include "WebContent.h"
#include "DirectoryNode.h" #include "DirectoryNode.h"
File root; File root;
File mp3File; File mp3File;
Audio audio; Audio audio;
uint volume = 18; uint volume = 12;
uint rfid_loop = RFID_LOOP_INTERVAL;
AsyncWebServer server(80); AsyncWebServer server(80);
DNSServer dns; DNSServer dns;
@ -55,23 +52,27 @@ boolean blockState = false;
volatile bool newRfidInt = false; volatile bool newRfidInt = false;
MFRC522 rfid(CS_RFID, RST_RFID); // instatiate a MFRC522 reader object.
MFRC522 rfid(CS_RFID, RST_RFID); // instatiate a MFRC522 reader object. TaskHandle_t RfidTask;
void activateSD()
void activateSD() { {
digitalWrite(CS_SDCARD, LOW); digitalWrite(CS_SDCARD, LOW);
} }
void deactivateSD() { void deactivateSD()
{
digitalWrite(CS_SDCARD, HIGH); digitalWrite(CS_SDCARD, HIGH);
} }
void activateRFID() { void activateRFID()
{
digitalWrite(CS_RFID, LOW); digitalWrite(CS_RFID, LOW);
} }
void deactivateRFID() { void deactivateRFID()
{
digitalWrite(CS_RFID, HIGH); digitalWrite(CS_RFID, HIGH);
} }
@ -95,8 +96,10 @@ void playNextMp3()
String mp3File = currentNode->getCurrentPlayingFilePath(); String mp3File = currentNode->getCurrentPlayingFilePath();
Serial.println(mp3File.c_str()); Serial.println(mp3File.c_str());
deactivateRFID(); deactivateRFID();
activateSD();
audio.connecttoSD(mp3File.c_str()); audio.connecttoSD(mp3File.c_str());
activateRFID(); activateRFID();
deactivateSD();
blockState = false; blockState = false;
} }
@ -105,15 +108,18 @@ void audio_info(const char *info)
// Serial.print("info "); Serial.println(info); // Serial.print("info "); Serial.println(info);
} }
void mute() { void mute()
if (audio.getVolume()!=0) { {
if (audio.getVolume() != 0)
{
volume = audio.getVolume(); volume = audio.getVolume();
} }
audio.setVolume(0); audio.setVolume(0);
} }
void unmute() { void unmute()
{
audio.setVolume(volume); audio.setVolume(volume);
} }
@ -121,7 +127,8 @@ String getState()
{ {
String state = String(); String state = String();
if (blockState) { if (blockState)
{
return state; return state;
} }
blockState = true; blockState = true;
@ -133,7 +140,6 @@ String getState()
state += " / "; state += " / ";
state += audio.getAudioFileDuration(); state += audio.getAudioFileDuration();
state += " "; state += " ";
} }
else else
{ {
@ -172,40 +178,40 @@ void stop()
void start() void start()
{ {
if (currentNode!=NULL) { if (currentNode != NULL)
{
currentNode->setCurrentPlaying(NULL); currentNode->setCurrentPlaying(NULL);
currentNode = NULL; currentNode = NULL;
} }
playNextMp3(); playNextMp3();
} }
void next() void next()
{ {
playNextMp3(); playNextMp3();
} }
void audio_eof_mp3(const char *info) { void audio_eof_mp3(const char *info)
{
Serial.println("audio file ended."); Serial.println("audio file ended.");
playNextMp3(); playNextMp3();
} }
void readRFID() { /* not working, FIXME remove me! */
void IRAM_ATTR rfid_interrupt()
{
newRfidInt = true;
}
void readRFID()
{
rfid.PICC_ReadCardSerial(); rfid.PICC_ReadCardSerial();
Serial.print("Tag UID: "); Serial.print("Tag UID: ");
String uidString = String(rfid.uid.uidByte[0]) + " " + String(rfid.uid.uidByte[1]) + " " + String uidString = getRFIDString(rfid.uid.uidByte);
String(rfid.uid.uidByte[2]) + " " + String(rfid.uid.uidByte[3]);
Serial.println(uidString); Serial.println(uidString);
} }
void clearInt(MFRC522 mfrc522) {
mfrc522.PCD_WriteRegister(mfrc522.ComIrqReg, 0x7F);
}
void IRAM_ATTR rfid_interrupt() {
newRfidInt = true;
}
void setup() void setup()
{ {
// put your setup code here, to run once: // put your setup code here, to run once:
@ -213,24 +219,20 @@ void setup()
pinMode(BTN_START_STOP, INPUT_PULLUP); pinMode(BTN_START_STOP, INPUT_PULLUP);
/* setup the IRQ pin*/ /* setup the IRQ pin*/
pinMode(IRQ_RFID, INPUT_PULLUP); pinMode(IRQ_RFID, INPUT_PULLUP);
pinMode(CS_RFID,OUTPUT); pinMode(CS_RFID, OUTPUT);
pinMode(CS_SDCARD,OUTPUT); pinMode(CS_SDCARD, OUTPUT);
deactivateRFID(); deactivateRFID();
activateSD();
// first parameter is name of access point, second is the password // first parameter is name of access point, second is the password
AsyncWiFiManager wifiManager(&server, &dns); AsyncWiFiManager wifiManager(&server, &dns);
wifiManager.autoConnect("HannaBox"); wifiManager.autoConnect("HannaBox");
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
if (!SD.begin(CS_SDCARD)) if (!SD.begin(CS_SDCARD))
@ -244,30 +246,21 @@ void setup()
rootNode.buildDirectoryTree("/"); rootNode.buildDirectoryTree("/");
rootNode.printDirectoryTree(); rootNode.printDirectoryTree();
deactivateSD(); deactivateSD();
activateRFID(); activateRFID();
Serial.println("RFID"); Serial.println("RFID");
// Init MFRC522 // Init MFRC522
// Init SPI bus // Init SPI bus
SPI.begin(-1,-1,-1,CS_RFID); SPI.begin(-1, -1, -1, CS_RFID);
rfid.PCD_Init(CS_RFID, RST_RFID); rfid.PCD_Init(CS_RFID, RST_RFID);
if (rfid.PCD_PerformSelfTest()) {
Serial.println("RFID OK");
/*
* Allow the ... irq to be propagated to the IRQ pin
* For test purposes propagate the IdleIrq and loAlert
*/
//rfid.PCD_WriteRegister(rfid.ComIEnReg, 0xA0);
attachInterrupt(IRQ_RFID, rfid_interrupt, FALLING);
do { //clear a spourious interrupt at start if (rfid.PCD_PerformSelfTest())
; {
} while (!newRfidInt); Serial.println("RFID OK");
newRfidInt = false; //interrupt flag }
} else { else
{
Serial.println("RFID Self Test failed!"); Serial.println("RFID Self Test failed!");
} }
@ -276,7 +269,6 @@ void setup()
Serial.println("Audio initialized."); Serial.println("Audio initialized.");
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send_P(200, "text/html", index_html, processor); }); { request->send_P(200, "text/html", index_html, processor); });
@ -304,55 +296,75 @@ void setup()
next(); }); next(); });
server.begin(); server.begin();
xTaskCreatePinnedToCore(
loop2, /* Function to implement the task */
"RFIDTask", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&RfidTask, /* Task handle. */
0); /* Core where the task should run */
Serial.println("initialization done."); Serial.println("initialization done.");
} }
void loop() void loop()
{ {
if (audio.isRunning())
deactivateRFID(); {
audio.loop(); deactivateRFID();
activateRFID(); activateSD();
audio.loop();
if (newRfidInt) { deactivateSD();
Serial.println("Interrupt."); activateRFID();
if(rfid.PICC_IsNewCardPresent()) {
readRFID();
stop();
}
clearInt(rfid);
newRfidInt = false;
} }
rfid_loop--;
if (rfid_loop == 0)
if (buttonPressed(BTN_START_STOP)) { {
if (audio.isRunning()) { rfid_loop = RFID_LOOP_INTERVAL;
deactivateSD();
activateRFID();
if (rfid.PICC_IsNewCardPresent())
{
stop(); stop();
} else { readRFID();
start();
} }
} }
if (buttonPressed(BTN_START_STOP))
{
if (audio.isRunning())
{
stop();
}
else
{
start();
}
}
delay(5);
} }
boolean buttonPressed(const uint8_t pin) { void loop2(void *parameter)
{
for (;;)
{
}
}
boolean buttonPressed(const uint8_t pin)
{
if (digitalRead(pin) == LOW) if (digitalRead(pin) == LOW)
{ {
unsigned long now = millis(); unsigned long now = millis();
if (now - lastStart > startDelay) if (now - lastStart > startDelay)
{ {
lastStart = now; lastStart = now;
return true; return true;
} }
} }
return false; return false;
} }