Moin, nachfolgend habe ich meinen Code. Der Code funktioniert soweit, den hab ich mit Hilfe von ChatGPT geschrieben. Nun fehlen mir noch ein paar Funktionen, die die KI nicht hinbekommt und hoffe, dass mir jemand helfen kann.
gewünschte Zusatzfunktionen bzw. änderungen:
-
Ich habe einen reconnect, der sich nur mit dem ersten Gerät nach dem flashen verbindet und nicht mit dem zuletzt verbundenen Gerät.
-
Bei geringer Lautstärke soll mehr Bass wiedergegeben werden und wenn´s lauter gestellt wird wieder rausnehmen.
-
ich bekomme das mit dem Callback einfach nicht hin. Mir ist wichtig, wenn der Akku leer ist, ein Ton abgespielt wird.
Ich weiß die Spannungswerte sind komisch, die Kalibrierung ist nicht so einfach, hab also die Spannungen vom Labor netzteil eingestellt und was im Serial Monitor angezeigt wird so übernommen. Das heißt, Die LED zeigt den richtigen Akkustatus an.
#include "ESP_I2S.h"
#include "BluetoothA2DPSink.h"
#include <Adafruit_NeoPixel.h>
#include "esp_task_wdt.h"
// I2S-Pins für PCM5102 DAC
const uint8_t I2S_SCK = 5; // BCK
const uint8_t I2S_WS = 25; // LCK
const uint8_t I2S_SDOUT = 26; // DIN
I2SClass i2s;
BluetoothA2DPSink a2dp_sink(i2s);
// Akkuüberwachung & Verbrauchersteuerung
#define PIN_NEOPIXEL 12 // GPIO für NeoPixel
#define NUMPIXELS 1 // Anzahl der NeoPixel
#define BATTERY_PIN 34 // ADC-Pin für Akkuspannungsmessung
#define R1 18060.0 // Spannungsteiler-Widerstände
#define R2 9360.0
#define MAX_ADC 4094.0
#define REF_VOLTAGE 3.3
#define VOLUME_FACTOR 0.1
// Lautstärkereduzierung
void read_data_stream(const uint8_t *data, uint32_t length)
{
int16_t *ptr16 = (int16_t*) data;
uint32_t len16 = length/2;
for(int j=0;j<len16;j++){
ptr16[j] = 0.30 * ptr16[j];
}
}
Adafruit_NeoPixel strip(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
unsigned long lastBatteryReadTime = 0; // Zeitpunkt der letzten Akku-Messung
const unsigned long batteryReadInterval = 200; //Intervall für Akkustand
// Funktion zum stabilen Messen der Akku-Spannung
float readBatteryVoltage() {
long sum = 0;
int samples = 100;
// Mehrere Messungen machen, um den Wert zu stabilisieren
for (int i = 0; i < samples; i++) {
sum += analogRead(BATTERY_PIN);
delay(1);
yield(); // Watchdog zurücksetzen
}
// Durchschnitt der Messungen berechnen
float average = sum / samples;
float voltage = average * (REF_VOLTAGE / MAX_ADC); // Umrechnung in Spannung
float batteryVoltage = voltage * ((R1 + R2) / R2); // Spannungsteiler-Anpassung
batteryVoltage = constrain(batteryVoltage, 0.0, 10.0); // Begrenze (0V bis 10V)
return batteryVoltage;
}
volatile bool isBluetoothActive = false;
// Bluetooth Task mit Lautstärkeregelung
void bluetoothTask(void *parameter) {
Serial.println("Starting Bluetooth A2DP Sink...");
a2dp_sink.set_auto_reconnect(true);
a2dp_sink.start("DS Music");
a2dp_sink.set_stream_reader(read_data_stream);
while (true) {
if (a2dp_sink.is_connected()) {
Serial.println("Bluetooth connected");
delay(2000);
// Blinken blau Bluetooth-Verbindung
if (!isBluetoothActive) {
isBluetoothActive = true; // Setze Flag, dass Bluetooth aktiv ist
for (int i = 0; i < 1; i++) {
strip.setPixelColor(0, strip.Color(0, 0, 200)); // Blau
strip.show();
delay(100); // Kurze Verzögerung für Blinken
strip.show();
}
isBluetoothActive = false;
}
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
// Akkuüberwachung
void batteryMonitorTask(void *parameter) {
while (true) {
if (!isBluetoothActive && millis() - lastBatteryReadTime >= batteryReadInterval) {
lastBatteryReadTime = millis();
// Akku-Spannung lesen
float batteryVoltage = readBatteryVoltage();
Serial.print("Battery Voltage: ");
Serial.println(batteryVoltage);
// Akku-Anzeige mit NeoPixel
if (!isBluetoothActive) {
if (batteryVoltage >= 7.51) {
strip.setPixelColor(0, strip.Color(0, 100, 0)); // Grün (Akku voll)
strip.show();
delay(1000);
}
else if (batteryVoltage >= 6.7) {
strip.setPixelColor(0, strip.Color(100, 40, 0)); // Gelb (Akku mittel)
strip.show();
delay(1000);
}
else if (batteryVoltage >= 6.5) {
// Rotes Blinken für niedrigen Akku
strip.setPixelColor(0, strip.Color(120, 0, 0)); // Rot
strip.show();
delay(1000);
}
else if (batteryVoltage <= 6.4) {
// Rotes Blinken für kritischen Akku
strip.setPixelColor(0, strip.Color(255, 0, 0)); // Rot
strip.show();
delay(200);
strip.setPixelColor(0, strip.Color(0, 0, 0)); // Rot aus
strip.show();
delay(200);
}
}
strip.show();
}
yield(); // Watchdog zurücksetzen
}
}
void setup() {
Serial.begin(115200);
esp_task_wdt_deinit(); // Watchdog deaktivieren
// Watchdog konfigurieren
esp_task_wdt_config_t wdt_config = {
.timeout_ms = 30000,
};
esp_task_wdt_init(&wdt_config);
esp_task_wdt_add(NULL);
// I2S Initialisieren
i2s.setPins(I2S_SCK, I2S_WS, I2S_SDOUT);
Serial.println("Initializing I2S...");
if (!i2s.begin(I2S_MODE_STD, 44100, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH)) {
Serial.println("Failed to initialize I2S!");
while (1); // Stoppe das Programm hier, wenn I2S fehlschlägt
}
Serial.println("I2S initialized successfully.");
// NeoPixel initialisieren
strip.begin();
strip.show(); // NeoPixel aus
delay(1000);
// Starte Bluetooth-Task auf Core 0
xTaskCreatePinnedToCore(bluetoothTask, "BluetoothTask", 4096, NULL, 1, NULL, 0);
// Starte Akkuüberwachungs-Task auf Core 1
xTaskCreatePinnedToCore(batteryMonitorTask, "BatteryMonitorTask", 4096, NULL, 1, NULL, 1);
}
void loop() {
yield(); // Watchdog zurücksetzen
}