esp32-stuff/sound_sensor.h

115 lines
No EOL
4 KiB
C++

#include "esphome.h"
// ===== CONFIGURATIE (deze kun je hier nog steeds aanpassen) =====
const int ADC_PIN = 36;
const int SAMPLE_WINDOW_MS = 250;
const float SENSITIVITY = 45.0;
const int NOISE_FLOOR = 25;
// ================================================================
// Dit is de hoofdklasse die de metingen doet.
// Deze is grotendeels ongewijzigd gebleven.
class SoundSensor : public PollingComponent {
public:
SoundSensor() : PollingComponent(1000) {} // Update-interval van 1 seconde
// Setters om de sensor-objecten vanuit de YAML te koppelen
void set_db_sensor(sensor::Sensor *s) { this->db_sensor_ = s; }
void set_volume_sensor(sensor::Sensor *s) { this->volume_sensor_ = s; }
void set_raw_sensor(sensor::Sensor *s) { this->raw_sensor_ = s; }
void setup() override {
pinMode(ADC_PIN, INPUT);
}
void update() override {
unsigned long startMillis = millis();
unsigned int sample;
long sum_of_squares = 0;
int sample_count = 0;
while (millis() - startMillis < SAMPLE_WINDOW_MS) {
sample = analogRead(ADC_PIN);
long signal = sample - 2048;
sum_of_squares += signal * signal;
sample_count++;
delay(0);
}
if (sample_count == 0) return;
double rms = sqrt(sum_of_squares / (double)sample_count);
if (this->raw_sensor_ != nullptr) this->raw_sensor_->publish_state(rms);
if (rms < NOISE_FLOOR) {
if (this->db_sensor_ != nullptr) this->db_sensor_->publish_state(0);
if (this->volume_sensor_ != nullptr) this->volume_sensor_->publish_state(0);
} else {
float db_value = SENSITIVITY * log10(rms);
if (this->db_sensor_ != nullptr) this->db_sensor_->publish_state(db_value);
float volume_percent = map(db_value, 0, 90, 0, 100);
volume_percent = constrain(volume_percent, 0, 100);
if (this->volume_sensor_ != nullptr) this->volume_sensor_->publish_state(volume_percent);
}
}
protected:
sensor::Sensor *db_sensor_{nullptr};
sensor::Sensor *volume_sensor_{nullptr};
sensor::Sensor *raw_sensor_{nullptr};
float map(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
};
// =========== NIEUWE CODE VOOR INTEGRATIE MET ESPHOME ===========
// Dit deel is de "lijm" tussen je YAML en de C++ klasse.
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
// Definieer de configuratie-sleutels die we in YAML gebruiken
static const char* const CONF_DB_SENSOR = "db_sensor";
static const char* const CONF_VOLUME_SENSOR = "volume_sensor";
static const char* const CONF_RAW_SENSOR = "raw_sensor";
// Definieer het "schema" voor ons component, zodat ESPHome weet welke opties geldig zijn.
// Dit moet overeenkomen met de structuur in je YAML.
#define SOUND_SENSOR_SCHEMA(name) \
cv::Schema{ \
cv::Required(name): sensor::sensor_schema(), \
}
// Dit is de "fabriek" die ons component bouwt op basis van de YAML configuratie
esp_err_t sound_sensor_to_code(esphome::config_parser::ASTNode* config) {
auto* ss = new SoundSensor();
App.register_component(ss);
// Koppel de 'db_sensor' configuratie uit YAML aan ons C++ object
if (config->has_key(CONF_DB_SENSOR)) {
auto conf = config->get_node(CONF_DB_SENSOR);
sensor::Sensor* s = cg::new_Pvariable(conf->get_id());
sensor::setup_sensor(s, conf);
cg::add(ss->set_db_sensor(s));
}
// Koppel de 'volume_sensor' configuratie
if (config->has_key(CONF_VOLUME_SENSOR)) {
auto conf = config->get_node(CONF_VOLUME_SENSOR);
sensor::Sensor* s = cg::new_Pvariable(conf->get_id());
sensor::setup_sensor(s, conf);
cg::add(ss->set_volume_sensor(s));
}
// Koppel de 'raw_sensor' configuratie
if (config->has_key(CONF_RAW_SENSOR)) {
auto conf = config->get_node(CONF_RAW_SENSOR);
sensor::Sensor* s = cg::new_Pvariable(conf->get_id());
sensor::setup_sensor(s, conf);
cg::add(ss->set_raw_sensor(s));
}
return esp_err_t::ESP_OK;
}