forked from fritob/Camper-Monitor
Die überarbeitete Firmware liess sich prüfen und fehlerfrei übersetzen, blieb auf dem Gerät aber stumm - keine Werte, keine Ausgabe über die serielle Schnittstelle. Der Umbau war zu gross für das, was sich ohne Gerätezugriff absichern lässt: config und compile sagen nichts über das Laufzeitverhalten. Die Firmware setzt jetzt wieder auf dem bewährten Stand 1.0 auf und ändert daran nur zweierlei: die Kalibrierung über Bluetooth funktioniert (die Charakteristik war beschreibbar, hatte aber keine Aktion hinterlegt und tat nichts), und der ESP-NOW-Rest ist entfernt, der bei jedem Messwert ein "hallo" an eine feste MAC schickte. Kein notify, kein aktives Setzen der Werte, kein Zugriff auf den BLE-Server aus dem Boot-Ablauf heraus. In der App fällt damit ein Denkfehler auf: fehlende Kalibrier-Offsets galten als "nicht kalibriert" statt als "unbekannt". Bei Firmware, die sie nicht meldet, stünde dauerhaft eine Warnung, die sich nicht abstellen lässt. Gewarnt wird jetzt nur, wenn das Gerät ausdrücklich Nulloffsets meldet. Der Rücksetz-Knopf hing an derselben Bedingung und wäre sonst unerreichbar gewesen. Das Abfragen im Takt war bereits als Rückfallebene eingebaut und trägt diesen Aufbau ohne Änderung. Ausserdem nimmt die .gitignore jetzt virtuelle Python-Umgebungen aus. Eine solche war versehentlich mitversioniert worden - über 14000 Dateien, die maschinenabhängig sind und im Repo nichts zu suchen haben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
213 lines
5.8 KiB
YAML
213 lines
5.8 KiB
YAML
# 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
|
|
|
|
- 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
|
|
|
|
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:
|
|
- id: pitch_ble
|
|
uuid: cad48e28-7fbe-41cf-bae9-d77a6c233424
|
|
description: "Pitch"
|
|
read: true
|
|
value: !lambda |-
|
|
std::vector<unsigned char> v(sizeof(float));
|
|
float val = id(pitch).state;
|
|
memcpy(v.data(), &val, sizeof(float));
|
|
return v;
|
|
- id: roll_ble
|
|
uuid: cad48e28-7fbe-41cf-bae9-d77a6c233425
|
|
description: "Roll"
|
|
read: true
|
|
value: !lambda |-
|
|
std::vector<unsigned char> v(sizeof(float));
|
|
float val = id(roll).state;
|
|
memcpy(v.data(), &val, sizeof(float));
|
|
return v;
|
|
- 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"};
|