Keine Wolke am Himmel, oder doch?
Ein einfacher Weg, die Bewölkung mit einem MLX90614 Infrarotsensor zu berechnen zeige ich hier per ESPHome und Home Assistant. Dies funktioniert bei mir seit Jahren ohne Probleme. Der Sensor besteht aus einem Infrarot-empfindlichen Sensor, der die Temperatur auf der Unterseite einer Wolke misst sowie einen Ambient Sensor, der die Umgebungstemperatur über das Gehäuse misst. Um die Temperatur der Wolkenunterseite zu messen, muss der IR-Sensor mit freier Sicht zum Himmel nach oben ausgerichtet werden. Für die Umgebungstemperatur benutze ich nicht den im Sensor eingebauten Temperatursensor, sondern nehme die Werte eines extrenen SHT21D, der lichtgeschützt in einem anderen Bereich der Wetterstation verbaut ist.
Die Formel für die Umrechnung beider Temperaturen in den Bewölkungsgrad von 0 – 100%:
AMBtemp ist die gemessene Aussentemperatur eines beliebigen Sensors und IRtemp ist die gemessene Temperatur der Wolkenunterseite. Die min/max Funktion rechnet den Wert in den Bereich 0 bis 100% um. Umgesetzt für ESPHome auf einem ESP8266 sieht dies so aus::
- platform: template
name: 'Bewölkung'
id: clouds
lambda: |-
return min(max((1 - (id(sensor_ambtemp).state - id(sensor_irtemp).state) / 20) * 100.0, 0.0), 100.0);
filters:
- sliding_window_moving_average:
window_size: 7
send_every: 4
update_interval: 30s
device_class: 'moisture'
state_class: 'measurement'
unit_of_measurement: '%'
accuracy_decimals: 1

In Home Assistant steht dieser Wert für weitere Berechnungen und Automationen zur Verfügung. Mit einem Textsensor zeige ich beispielsweise auf meinen Dashboards im Haus die aktuelle Bewölkung als Textausgabe an.
Dazu berechne ich im ESP8266 aus dem Bewölkungsgrad 0-100% einen Index von 0-7 und referenziere In Home Assistant in einem Text-Template auf eine angelegte String-Tabelle mit acht Elementen:
- platform: template
name: 'Cloudindex'
lambda: |-
return (id(clouds).state * 7) / 100;
update_interval: 30s
device_class: 'aqi'
state_class: 'measurement'
accuracy_decimals: 0
- sensor:
- name: "Wetterzustand"
state: >
{% set v = ('Wolkenlos','Sehr leicht bewölkt','Leicht bewölkt','Teilweise bewölkt','Wolkig','Überwiegend wolkig','Stark bewölkt','Bedeckt') %}
{% set stat = states('sensor.cloudindex')|int(0) %}
{{ v[stat] }}
Zusätzlich werte ich noch aus, ob es gerade regnet bzw. schneit oder ein Gewitter aktiv ist. In dem Fall erweitere ich den String um mehr Informationen. Bei meinen Dashboards wird dann noch Anzahl Blitzeinschläge und Entfernung angezeigt. Diese Information beziehe ich aus der Blitzortung-Integration. Der Fantasie sind hier kaum Grenzen gesetzt.
