# VanAlign Pro - Neigungsmessung über BLE # # Bewusst nah am bewährten Stand 1.0 gehalten. Gegenüber diesem geändert: # # * Die Kalibrierung funktioniert. Die Charakteristik ...3427 war zwar # beschreibbar, hatte aber keine Aktion hinterlegt und tat nichts; der # Kalibrier-Knopf war nur über den Webserver erreichbar, der # auskommentiert ist. Kalibrieren war damit auf keinem Weg möglich. # * Der ESP-NOW-Rest ist entfernt. Er schickte bei jedem einzelnen # Messwert ein "hallo" an eine fest eingetragene MAC-Adresse. # # Bewusst NICHT geändert: Pitch und Roll bleiben reine Lesewerte mit # hinterlegtem Ausdruck. Eine Fassung mit notify und aktiv gesetzten Werten # liess das Gerät verstummen - sie ist in der Projektgeschichte unter # "Neigungsmesser VanAlign einbinden" nachlesbar, aber nicht in Betrieb. # Der Client fragt die Werte stattdessen im Takt ab. esphome: name: vanalign friendly_name: "VanAlign Pro" esp32: board: esp32-s3-devkitc-1 framework: type: esp-idf logger: level: WARN espnow: channel: 1 sensor: - platform: mpu6050 #address: 0x69 gyro_x: name: "MPU6050 Gyro X-Achse" id: mpu_gyro_x gyro_y: name: "MPU6050 Gyro Y-Achse" id: mpu_gyro_y gyro_z: name: "MPU6050 Gyro Z-Achse" id: mpu_gyro_z accel_x: name: "MPU6050 Accel X" id: accel_x internal: true accel_y: name: "MPU6050 Accel Y" id: accel_y internal: true accel_z: name: "MPU6050 Accel Z" id: accel_z internal: true update_interval: 0.1s - platform: template name: "Neigung Pitch" id: pitch icon: mdi:caravan unit_of_measurement: "°" accuracy_decimals: 1 update_interval: 0.1s lambda: |- if (isnan(id(accel_x).state) || isnan(id(accel_y).state) || isnan(id(accel_z).state)) { return NAN; } float raw = atan2(id(accel_y).state, sqrt(pow(id(accel_x).state, 2) + pow(id(accel_z).state, 2))) * (180.0 / 3.14159265); return raw - id(pitch_offset); // Offset wird hier subtrahiert filters: - sliding_window_moving_average: window_size: 8 send_every: 1 - exponential_moving_average: alpha: 0.2 on_value: then: - ble_server.characteristic.set_value: id: pitch_ble value: !lambda |- std::vector v(sizeof(float)); float val = x; memcpy(v.data(), &val, sizeof(float)); return v; - platform: template name: "Neigung Roll" id: roll icon: mdi:axis-x-rotate-clockwise unit_of_measurement: "°" accuracy_decimals: 1 update_interval: 0.1s lambda: |- if (isnan(id(accel_x).state) || isnan(id(accel_z).state)) { return NAN; } float raw = atan2(-id(accel_x).state, id(accel_z).state) * (180.0 / 3.14159265); return raw - id(roll_offset); // Offset wird hier subtrahiert filters: - sliding_window_moving_average: window_size: 8 send_every: 1 - exponential_moving_average: alpha: 0.2 on_value: then: - ble_server.characteristic.set_value: id: roll_ble value: !lambda |- std::vector v(sizeof(float)); float val = x; memcpy(v.data(), &val, sizeof(float)); return v; globals: - id: pitch_offset type: float restore_value: yes initial_value: '0.0' - id: roll_offset type: float restore_value: yes initial_value: '0.0' - id: enable_captive type: bool restore_value: yes initial_value: 'false' esp32_ble_server: services: - uuid: 2a24b789-7aab-4535-af3e-ee76a35cc42d advertise: true characteristics: # Ohne "value:" – der Wert wird bei jeder Messung gesetzt, siehe # on_value beim Sensor. Ein getemplatetes "value:" führt ESPHome nur # einmal aus, in setup(); die Charakteristik behielte dann für immer # den Wert vom Start, und jede Abfrage lieferte dieselbe Zahl. - id: pitch_ble uuid: cad48e28-7fbe-41cf-bae9-d77a6c233424 description: "Pitch" read: true - id: roll_ble uuid: cad48e28-7fbe-41cf-bae9-d77a6c233425 description: "Roll" read: true - id: calib_ble uuid: cad48e28-7fbe-41cf-bae9-d77a6c233427 description: "Kalibriere Neigung" write: true on_write: then: - lambda: |- bool reset = !x.empty() && (x[0] == 0x00 || x[0] == '0'); if (reset) { id(reset_calibration).execute(); } else { id(calibrate_level).execute(); } i2c: sda: GPIO8 scl: GPIO9 scan: true #web_server: # port: 80 #ota: # platform: web_server #wifi: # ap: # ssid: "VanAlign-Setup" # password: "kalibrierung" script: # Die aktuelle Lage wird zur neuen Null. Knopf und Bluetooth laufen hier # zusammen, damit sie nicht auseinanderdriften. - id: calibrate_level then: - lambda: |- if (isnan(id(accel_x).state) || isnan(id(accel_y).state) || isnan(id(accel_z).state)) { ESP_LOGW("vanalign", "Kalibrierung abgebrochen: keine Sensorwerte"); return; } id(pitch_offset) = atan2(id(accel_y).state, sqrt(pow(id(accel_x).state, 2) + pow(id(accel_z).state, 2))) * (180.0 / 3.14159265); id(roll_offset) = atan2(-id(accel_x).state, id(accel_z).state) * (180.0 / 3.14159265); ESP_LOGI("vanalign", "Kalibriert: pitch_offset=%.2f roll_offset=%.2f", id(pitch_offset), id(roll_offset)); - id: reset_calibration then: - lambda: |- id(pitch_offset) = 0.0f; id(roll_offset) = 0.0f; ESP_LOGI("vanalign", "Kalibrierung zurückgesetzt"); button: - platform: template name: "Kalibriere Neigung" id: calib_button on_press: - script.execute: calibrate_level - platform: template name: "Kalibrierung zurücksetzen" id: calib_reset_button on_press: - script.execute: reset_calibration - platform: restart name: "ESP Restart" text_sensor: - platform: template name: "Firmware Version" id: firmware_version icon: mdi:tag lambda: |- return {"v1.0.2"};