#include <iostream>
using Millis_t = decltype(millis());
// Klasse zum Steuern von nicht blockierenden Delays
class MonoFlop {
public:
MonoFlop() : Timestamp {0}, IsActive {false} {}
void start() {
if (!IsActive) {
Timestamp = millis();
IsActive = true;
}
}
void reset() { IsActive = false; }
bool operator()(const Millis_t Duration) {
if (IsActive && millis() - Timestamp >= Duration) {
return !(IsActive = false); // Return true only once!
}
return false;
}
operator bool() const { return IsActive; } // true if timer is not expired
private:
Millis_t Timestamp;
bool IsActive;
};
// Datentyp zum Speichern der Statusdaten für die Steuerung der Überwachung des Audioaus- bzw. Audioeingangs
struct AudioPort {
const uint_fast8_t AdcPin;
const uint16_t AdcThreshold;
const uint_fast8_t Pin;
const uint16_t gcHysteresis;
const Millis_t Delay_ms;
MonoFlop& Delay;
uint16_t AdcValue;
};
// Indexbezeichner (Arrays) Audioausgang (gcOut) = Musik, Audioeingang (gcIn) = Mikrofon
constexpr uint_fast8_t gcOut {0};
constexpr uint_fast8_t gcIn {1};
// Index 0 Audio gcOut Index 1 Audio gcIn
constexpr uint_fast8_t gcAdcPins[2] = {34, 35};
constexpr uint_fast8_t gcIndicatorPins[2] = {18, 16};
// Einstellbare Parameter / hier für beide Audioanschlüsse gleich
constexpr uint16_t gcThreshold {2000}; // Wert am Analog Pin34 kleiner -> Verzögerung startet
constexpr Millis_t gcSwitchDelay_ms {2000}; // Verzögerung in Millisekunden
constexpr uint16_t gcHysteresis {10}; // Hysterese = Der ADC Wert muss sich um mehr Einheiten ändern als
// der Hysteresewert, bevor eine Wertänderung als solche anerkannt wird.
MonoFlop DelayTimer[2];
// Statusdaten initialisieren
// PinNr, ADC Grenzwert, LED Pins, ADC Hysterese, Umschaltverzögerung, Verzögerungstimer, ADC-Wert Speicher
AudioPort OutIn[2] = {
{gcAdcPins[gcOut], gcThreshold, gcIndicatorPins[gcOut], gcHysteresis, gcSwitchDelay_ms, DelayTimer[gcOut], 0},
{gcAdcPins[gcIn], gcThreshold, gcIndicatorPins[gcIn], gcHysteresis, gcSwitchDelay_ms, DelayTimer[gcIn], 0}
};
void checkAudioPort(AudioPort& Audio) {
uint16_t AdcValue = analogRead(Audio.AdcPin);
bool IsBeyondThreshold = (AdcValue > Audio.AdcThreshold);
if (abs(Audio.AdcValue - AdcValue) > Audio.gcHysteresis) {
Audio.AdcValue = AdcValue;
if (!IsBeyondThreshold && !Audio.Delay && digitalRead(Audio.Pin)) {
std::cout << "Grenze unterschritten. Starte Timer.\r\n";
Audio.Delay.start();
} else if (IsBeyondThreshold && Audio.Delay) {
std::cout << "Grenze überschritten. Stoppe Timer.\r\n";
Audio.Delay.reset();
}
}
bool IsPinHigh = static_cast<bool>(digitalRead(Audio.Pin));
if ((Audio.Delay(Audio.Delay_ms) && IsPinHigh) || (IsBeyondThreshold && !IsPinHigh)) {
std::cout << "Schalte LED an Pin " << Audio.Pin << ' ' << (IsPinHigh ? "aus" : "ein") << "\r\n";
digitalWrite(Audio.Pin, IsBeyondThreshold);
}
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
for (const auto& Pin : gcIndicatorPins) {
pinMode(Pin, OUTPUT);
digitalWrite(Pin, false);
}
}
void loop() {
for (auto& Channel : OutIn) { checkAudioPort(Channel); }
}
Musik
Mikrofon