2024-05-16 13:19:30 +00:00
|
|
|
#include <LiquidCrystal.h>
|
2024-05-17 16:08:34 +00:00
|
|
|
#include <Wire.h>
|
2024-05-15 12:19:07 +00:00
|
|
|
#include <SPI.h>
|
2024-05-17 16:08:34 +00:00
|
|
|
#include <Adafruit_PN532.h>
|
2024-05-21 11:23:58 +00:00
|
|
|
#include <SoftwareSerial.h>
|
|
|
|
#include <DFRobotDFPlayerMini.h>
|
2024-05-15 08:40:32 +00:00
|
|
|
|
2024-05-16 13:19:30 +00:00
|
|
|
#include "station.h"
|
2024-05-17 13:04:36 +00:00
|
|
|
#include "statemachine.h"
|
|
|
|
#include "state.h"
|
2024-05-17 13:37:03 +00:00
|
|
|
#include "states.h"
|
2024-05-17 14:20:45 +00:00
|
|
|
#include "timer.h"
|
2024-05-16 13:19:30 +00:00
|
|
|
|
2024-05-15 12:19:07 +00:00
|
|
|
#define PN532_CS 10
|
|
|
|
|
2024-05-17 16:13:40 +00:00
|
|
|
// Using this library to set a timeout on readPassiveTagID
|
|
|
|
// The library in use is slightly modified to fix this issue: https://github.com/adafruit/Adafruit-PN532/issues/117
|
2024-05-17 16:08:34 +00:00
|
|
|
Adafruit_PN532 nfc(PN532_CS);
|
2024-05-15 12:19:07 +00:00
|
|
|
|
2024-05-16 13:19:30 +00:00
|
|
|
const int rs = 9, en = 8, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
|
2024-05-15 12:19:07 +00:00
|
|
|
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
|
|
|
|
|
2024-05-21 11:23:58 +00:00
|
|
|
SoftwareSerial softSerial(6, 7); // RX, TX
|
|
|
|
DFRobotDFPlayerMini myDFPlayer;
|
|
|
|
|
2024-05-16 13:19:30 +00:00
|
|
|
Station stations[4] = { Station(1680767519, "Yellow"), Station(3346823711, "Green"), Station(3569318175, "Pink"), Station(2174777887, "Blue") };
|
2024-05-17 16:08:34 +00:00
|
|
|
Station* currentStation;
|
|
|
|
|
2024-05-17 16:13:40 +00:00
|
|
|
Timer stationDetectionTimer(500, true);
|
2024-05-16 13:19:30 +00:00
|
|
|
|
2024-05-17 13:37:03 +00:00
|
|
|
StateMachine stateMachine(new Startup());
|
2024-05-17 13:04:36 +00:00
|
|
|
|
2024-05-17 14:20:45 +00:00
|
|
|
unsigned long lastLoopTime = 0;
|
|
|
|
unsigned long currentLoopTime = 0;
|
|
|
|
unsigned long deltaTime = 0;
|
|
|
|
|
2024-05-15 12:19:07 +00:00
|
|
|
void setup(void) {
|
2024-05-16 13:19:30 +00:00
|
|
|
setupNFC();
|
|
|
|
|
|
|
|
lcd.begin(16, 2);
|
2024-05-17 14:20:45 +00:00
|
|
|
stationDetectionTimer.start();
|
2024-05-21 11:23:58 +00:00
|
|
|
|
|
|
|
softSerial.begin(9600);
|
|
|
|
|
|
|
|
lcd.print("Initializing MP3");
|
|
|
|
lcd.clear();
|
|
|
|
if (!myDFPlayer.begin(softSerial, true, true)) {
|
|
|
|
lcd.print("Failed to init");
|
|
|
|
lcd.setCursor(0, 1);
|
|
|
|
lcd.print("DFPlayer!");
|
|
|
|
while (true) {
|
|
|
|
delay(100);
|
|
|
|
printMp3Detail(myDFPlayer.readType(), myDFPlayer.read());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
myDFPlayer.volume(5);
|
|
|
|
myDFPlayer.play(1);
|
2024-05-16 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void loop(void) {
|
2024-05-17 14:20:45 +00:00
|
|
|
currentLoopTime = millis();
|
|
|
|
deltaTime = currentLoopTime - lastLoopTime;
|
|
|
|
|
|
|
|
bool doCheck = stationDetectionTimer.update(deltaTime);
|
2024-05-17 16:08:34 +00:00
|
|
|
lcd.setCursor(0, 1);
|
|
|
|
lcd.print(" ");
|
2024-05-17 14:20:45 +00:00
|
|
|
if (doCheck) {
|
|
|
|
checkStations();
|
2024-05-17 16:08:34 +00:00
|
|
|
lcd.setCursor(7, 1);
|
|
|
|
lcd.print("check");
|
2024-05-17 14:20:45 +00:00
|
|
|
}
|
2024-05-17 16:08:34 +00:00
|
|
|
lcd.setCursor(0, 1);
|
|
|
|
lcd.print(String(deltaTime));
|
2024-05-17 14:20:45 +00:00
|
|
|
|
|
|
|
stateMachine.update(Context(stations, deltaTime));
|
|
|
|
|
|
|
|
lastLoopTime = currentLoopTime;
|
2024-05-17 16:13:40 +00:00
|
|
|
delay(10);
|
2024-05-16 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setupNFC() {
|
2024-05-15 12:19:07 +00:00
|
|
|
nfc.begin();
|
|
|
|
|
|
|
|
uint32_t versiondata = nfc.getFirmwareVersion();
|
2024-05-16 13:19:30 +00:00
|
|
|
if (!versiondata) {
|
|
|
|
while (1)
|
|
|
|
; // halt
|
2024-05-15 12:19:07 +00:00
|
|
|
}
|
|
|
|
// configure board to read RFID tags and cards
|
|
|
|
nfc.SAMConfig();
|
2024-05-15 08:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-05-16 13:19:30 +00:00
|
|
|
void checkStations() {
|
|
|
|
Station* station = detectStation();
|
2024-05-17 16:08:34 +00:00
|
|
|
|
2024-05-17 13:04:36 +00:00
|
|
|
if (station != 0) {
|
2024-05-17 16:08:34 +00:00
|
|
|
lcd.setCursor(0, 0);
|
|
|
|
lcd.print(" ");
|
|
|
|
lcd.setCursor(0, 0);
|
2024-05-17 14:20:45 +00:00
|
|
|
lcd.print("Station: " + station->getName());
|
2024-05-17 16:08:34 +00:00
|
|
|
if (currentStation == 0) {
|
|
|
|
currentStation = station;
|
|
|
|
stateMachine.putDown(currentStation);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lcd.setCursor(0, 0);
|
|
|
|
lcd.print(" ");
|
|
|
|
lcd.setCursor(0, 0);
|
|
|
|
lcd.print("not docked");
|
|
|
|
if (currentStation != 0) {
|
|
|
|
currentStation = 0;
|
|
|
|
stateMachine.pickedUp();
|
|
|
|
}
|
2024-05-17 13:04:36 +00:00
|
|
|
}
|
2024-05-16 13:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Station* detectStation() {
|
2024-05-17 16:08:34 +00:00
|
|
|
uint8_t uid[7];
|
|
|
|
uint8_t uidLength;
|
|
|
|
uint16_t timeout = 100;
|
|
|
|
bool success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, timeout);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t id = 0;
|
|
|
|
for (uint8_t i = 0; i < uidLength; i++) {
|
|
|
|
id <<= 8;
|
|
|
|
id |= uid[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-05-16 13:19:30 +00:00
|
|
|
Station* found = 0;
|
|
|
|
for (int i = 0; i < sizeof(stations); i++) {
|
|
|
|
Station* currentStation = &stations[i];
|
2024-05-17 13:04:36 +00:00
|
|
|
if (currentStation->check(id)) {
|
|
|
|
found = currentStation;
|
2024-05-15 12:19:07 +00:00
|
|
|
}
|
|
|
|
}
|
2024-05-16 13:19:30 +00:00
|
|
|
return found;
|
2024-05-15 08:40:32 +00:00
|
|
|
}
|
2024-05-21 11:23:58 +00:00
|
|
|
|
|
|
|
void printMp3Detail(uint8_t type, int value) {
|
|
|
|
lcd.clear();
|
|
|
|
switch (type) {
|
|
|
|
case TimeOut:
|
|
|
|
lcd.print("Time Out!");
|
|
|
|
break;
|
|
|
|
case WrongStack:
|
|
|
|
lcd.print("Stack Wrong!");
|
|
|
|
break;
|
|
|
|
case DFPlayerCardInserted:
|
|
|
|
lcd.print("Card Inserted!");
|
|
|
|
break;
|
|
|
|
case DFPlayerCardRemoved:
|
|
|
|
lcd.print("Card Removed!");
|
|
|
|
break;
|
|
|
|
case DFPlayerCardOnline:
|
|
|
|
lcd.print("Card Online!");
|
|
|
|
break;
|
|
|
|
case DFPlayerUSBInserted:
|
|
|
|
lcd.print("USB Inserted!");
|
|
|
|
break;
|
|
|
|
case DFPlayerUSBRemoved:
|
|
|
|
lcd.print("USB Removed!");
|
|
|
|
break;
|
|
|
|
case DFPlayerPlayFinished:
|
|
|
|
lcd.print("Num:");
|
|
|
|
lcd.print(value);
|
|
|
|
lcd.print(" Finished!");
|
|
|
|
break;
|
|
|
|
case DFPlayerError:
|
|
|
|
lcd.print("DFPlayerError:");
|
|
|
|
switch (value) {
|
|
|
|
case Busy:
|
|
|
|
lcd.print("Card not found");
|
|
|
|
break;
|
|
|
|
case Sleeping:
|
|
|
|
lcd.print("Sleeping");
|
|
|
|
break;
|
|
|
|
case SerialWrongStack:
|
|
|
|
lcd.print("Wrong Stack");
|
|
|
|
break;
|
|
|
|
case CheckSumNotMatch:
|
|
|
|
lcd.print("Checksum Error");
|
|
|
|
break;
|
|
|
|
case FileIndexOut:
|
|
|
|
lcd.print("File Index OOB");
|
|
|
|
break;
|
|
|
|
case FileMismatch:
|
|
|
|
lcd.print("File Mismatch");
|
|
|
|
break;
|
|
|
|
case Advertise:
|
|
|
|
lcd.print("In Advertise");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
lcd.print("Unknown Error");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
lcd.print("Unknown Type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delay(2000); // Display the message for 2 seconds
|
|
|
|
}
|