Web improvements, NFC config

This commit is contained in:
Stefan Ostermann 2023-10-15 00:24:58 +02:00
parent a3be4cbb3c
commit 578281d9d1
5 changed files with 111 additions and 66 deletions

View File

@ -111,14 +111,23 @@ Place these sounds in the folder `system` on the SD card:
sleep.mp3 will be played just before the timed shutdown, start.mp3 will be played if the box started and initialized successfully.
## Battery Voltage
The battery voltage is measured by the ADC of pin 13. A voltage divider halves the voltage so that the pin can not be overloaded (max 3.3V).
The voltage divider consists of two 100kOHM resistors, the voltage is measured between them. One side is connected to the battery and the other to ground.
Pin 13s ADC (ADC2) can not be used while WIFI is on... damn.
## TODOs
* Card Reader with SPI. Configure hspi, second SPI channel? Or does SD Card + RFID run at the same channel?
![](images/wemos-d1-mini-esp32.png)
## Schematic without modules
### Charging circuit
https://ww1.microchip.com/downloads/en/AppNotes/01149c.pdf
MCP73837 ?

View File

@ -9,6 +9,8 @@ const char index_html[] PROGMEM = R"rawliteral(
<body>
<h1>HannaBox</h1>
<span id="state"></span><br/><br/>
<span id="voltage"></span><br/>
<span id="uid"></span><br/>
<div>
<button class="prev-button" onclick="simpleGetCall('prev');""></button>
@ -16,16 +18,17 @@ const char index_html[] PROGMEM = R"rawliteral(
<button class="next-button" onclick="simpleGetCall('next');"></button><br/><br/>
</div>
<div class="slidecontainer">
<label for="progress" id="progressLabel"></label>
<input name="progress" type="range" min="0" max="100" value="0" class="slider" id="progressSlider"
onmouseup="postValue('progress',document.getElementById('progressSlider').value);"
ontouchend="postValue('progress',document.getElementById('progressSlider').value);">
onchange="postValue('progress',document.getElementById('progressSlider').value);lastChange = Date.now()"
>
<label for="progress" id="progressLabel"></label>
</div>
<div class="slidecontainer">
<label for="volume">Vol</label>
<div class="slidecontainer">
<input name="volume" type="range" min="0" max="15" value="7" class="slider" id="volumeSlider"
onmouseup="postValue('volume',document.getElementById('volumeSlider').value);"
ontouchend="postValue('volume',document.getElementById('volumeSlider').value);">
onchange="postValue('volume',document.getElementById('volumeSlider').value);lastChange = Date.now()"
>
<label for="volume">Vol</label>
</div>
<!--
<button onmouseup="simpleGetCall('stop');" ontouchend="simpleGetCall('stop');">Stop</button>&nbsp;
@ -42,6 +45,8 @@ const char index_html[] PROGMEM = R"rawliteral(
// Get the <li> elements
var liElements = document.querySelectorAll('ul li');
var lastChange = 0;
// Add click event listener to each <li> element
liElements.forEach(function(li) {
li.addEventListener('click', function() {
@ -81,6 +86,8 @@ const char index_html[] PROGMEM = R"rawliteral(
function displayState(state) {
document.getElementById("state").innerHTML = state['title'];
document.getElementById("progressLabel").innerHTML = state['time'];
document.getElementById("voltage").innerHTML = state['voltage']+' mV';
document.getElementById("uid").innerHTML = 'Last NFC ID: '+state['uid'];
var elements = document.getElementsByClassName('play-button');
var btn = elements[0];
@ -89,12 +96,16 @@ const char index_html[] PROGMEM = R"rawliteral(
} else {
btn.classList.remove('paused');
}
var progress = document.getElementById('progressSlider');
progress.value = state['time'];
progress.max = state['length'];
if (Date.now()-lastChange>1200) {
var progress = document.getElementById('progressSlider');
progress.value = state['time'];
progress.max = state['length'];
var volume = document.getElementById('volumeSlider');
volume.value = state['volume'];
}
var volume = document.getElementById('volumeSlider');
volume.value = state['volume'];
}

View File

@ -65,4 +65,8 @@ li {
box-shadow: -10px 0 0 0 darkgrey;
}
.slider {
width: 80%;
}
)rawliteral";

View File

@ -52,6 +52,7 @@ void writeFile(fs::FS &fs, const char * path, const char * message){
file.close();
}
unsigned long lastStart = 0;
unsigned long lastInteraction = 0;
@ -64,12 +65,20 @@ boolean continuousMode = false;
uint8_t buttontoignore = 0;
uint32_t lastVoltage = 0;
const int startDelay = 250;
String lastUid = "";
const String sleep_sound = "sleep.mp3";
const String startup_sound = "start.mp3";
const String mapping_file = "/mapping.txt";
std::map<String, String> rfid_map;
/*
const long sleepMessageDelay = 28000;

View File

@ -31,6 +31,8 @@
#define CS_SDCARD 22
#define BAT_VOLTAGE_PIN 13
#define RFID_LOOP_INTERVAL 25
#include "globals.h"
@ -75,9 +77,12 @@ bool asyncNext = false;
bool asyncPrev = false;
/*
std::map<String, String> rfid_map{{"67 152 204 14", "01-The_Box_Tops-The_Letter.mp3"},
{"67 175 148 160", "068-Der_Schatz_im_Bergsee"}};
*/
void activateSD()
{
digitalWrite(CS_SDCARD, LOW);
@ -98,6 +103,12 @@ void deactivateRFID()
digitalWrite(CS_RFID, HIGH);
}
uint32_t getBatteryVoltageMv() {
uint32_t voltage = analogReadMilliVolts(BAT_VOLTAGE_PIN);
return voltage*2;//*2 because of the voltage divider.
}
void playSongByName(String song)
{
currentNode = rootNode.advanceToMP3(&song);
@ -117,10 +128,14 @@ void playSongByPath(String path)
void playSongByRFID(String id)
{
String song = rfid_map[id];
auto songit = rfid_map.find(id);
if (songit==rfid_map.end()) {
Serial.println("song for uid not found.");
return;
}
Serial.println("searching for ");
Serial.println(song);
playSongByName(song);
Serial.println(songit->second);
playSongByName(songit->second);
}
/**
@ -200,11 +215,41 @@ String getState()
jsonState["time"] = audio.getAudioCurrentTime();
jsonState["volume"] = audio.getVolume();
jsonState["length"] = audio.getAudioFileDuration();
jsonState["voltage"] = lastVoltage;
jsonState["uid"] = lastUid;
String output;
serializeJson(jsonState, output);
jsonState.clear();
jsonState.garbageCollect();
return output;
}
std::map<String, String> readDataFromFile(const char *filename) {
File file = SD.open(filename);
if (file) {
while (file.available()) {
// Read key and value from the file
String line = file.readStringUntil('\n');
int separatorIndex = line.indexOf('=');
if (separatorIndex != -1) {
// Extract key and value
String key = line.substring(0, separatorIndex).c_str();
String value = line.substring(separatorIndex + 1).c_str();
// Add key-value pair to the map
rfid_map[key] = value;
}
}
file.close();
} else {
Serial.print("Error opening file ");
Serial.println(filename);
}
return rfid_map;
}
String processor(const String &var)
{
if (var == "DIRECTORY")
@ -273,56 +318,13 @@ void IRAM_ATTR rfid_interrupt()
void readRFID()
{
rfid.PICC_ReadCardSerial();
Serial.print("Tag UID: ");
String uidString = getRFIDString(rfid.uid.uidByte);
Serial.println(uidString);
Serial.print("Card UID: ");
lastUid = getRFIDString(rfid.uid.uidByte);
Serial.println(lastUid);
//rfid.PICC_DumpDetailsToSerial(&(rfid.uid));
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//some variables we need
byte buffer[42]; //data transfer buffer (16+2 bytes data+CRC)
byte size = sizeof(buffer);
uint8_t pageAddr = 0x05; //In this example we will write/read 16 bytes (page 6,7,8 and 9).
//Ultraligth mem = 16 pages. 4 bytes per page.
//Pages 0 to 4 are for special functions.
MFRC522::StatusCode status;
rfid.PICC_DumpDetailsToSerial(&(rfid.uid));
//------------------------------------------- GET FIRST NAME
/*
status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid)); //line 834 of MFRC522.cpp file
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(rfid.GetStatusCodeName(status));
return;
}
Serial.println("Auth");
*/
// works only with mifare ultralight:
status = rfid.MIFARE_Read(pageAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(rfid.GetStatusCodeName(status));
return;
}
//Dump a byte array to Serial
for (byte i = 0; i < size; i++) {
Serial.write(buffer[i]);
}
Serial.println();
// ------------------------------
rfid.PICC_HaltA();
playSongByRFID(uidString);
playSongByRFID(lastUid);
lastInteraction = millis();
}
@ -361,6 +363,8 @@ void setup()
rootNode.buildDirectoryTree("/");
rootNode.printDirectoryTree();
readDataFromFile(mapping_file.c_str());
deactivateSD();
activateRFID();
Serial.println("RFID");
@ -384,11 +388,19 @@ void setup()
Serial.println("Audio initialized.");
lastVoltage = getBatteryVoltageMv();
Serial.print("Battery Voltage in mV: ");
Serial.println(lastVoltage);
// first parameter is name of access point, second is the password
AsyncWiFiManager wifiManager(&server, &dns);
wifiManager.setTimeout(180);
Serial.println("Deactivating Brownout detector...");
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
if (wifiManager.autoConnect("HannaBox"))
{
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
@ -438,6 +450,9 @@ void setup()
Serial.println("Wifi timed out. Fallback no Wifi.");
}
Serial.println("Activating Brownout detector...");
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
xTaskCreatePinnedToCore(
loop2, /* Function to implement the task */
"RFIDTask", /* Name of the task */
@ -459,7 +474,6 @@ void named_song_action(AsyncWebServerRequest *request)
for (int i = 0; i < params; i++)
{
AsyncWebParameter *p = request->getParam(i);
Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
if (p->name() == "title")
{
playSongByName(p->value());
@ -477,7 +491,6 @@ void progress_action(AsyncWebServerRequest *request)
for (int i = 0; i < params; i++)
{
AsyncWebParameter *p = request->getParam(i);
Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
if (p->name() == "value")
{
audio.setAudioPlayPosition(atoi(p->value().c_str()));
@ -495,7 +508,6 @@ void volume_action(AsyncWebServerRequest *request)
for (int i = 0; i < params; i++)
{
AsyncWebParameter *p = request->getParam(i);
Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
if (p->name() == "value")
{
audio.setVolume(atoi(p->value().c_str()));