Bonsoir à tous,
Je vous partage un petit projet de station météo en cours de réalisation. Une majorité du projet est de la récup.
- Les capteurs sur mat sont une récup de déchetterie, l'anémomètre était cassé (env. 20€ sur ali, fdp incl.), j'ai juste oublié le bouclier Stevenson donc à venir.
- Dans le boitier qui est de récup au taff, une pile 18V 15Ah qui contient 12 piles type "D" 1.5V donc petit atelier mise en dérivation d'ensemble de 3 piles série et paf ça donne une pile 4.5V. Le bornier c'est du fond de tiroir. Seule la partie électronique (prototype) est "presque" neuve.
Pour le code, sous ESPhome, j'ai un peux fouillé à droite et a gauche sur le web et j'ai tout mixé avec des ajouts pour m'entrainer aux fonctions ESPhome.
#####################
## CONFIG:
## INA 3221 Puissance, Tension et Intensité du circuit
## WH-SP-WS02 Anémomètre, Girouette et Pluviomètre
## BME280 Température, Humidité et Pression atmosphérique
## BH1750 intensité lumineuse
## en cours ADS1115 Multiplexeur Analog>I²C
## à faire SI1145 Ultraviolets librairie à ajouter
## à faire SDS011 Particules fines
## à faire MHZ19 CO2
## à faire Geiger
#####################
## CONFIG E/S
## A0 - ADC0 - Girouette
## D0 - GPIO16 -
## D1 - GPIO5 - I²C SCL
## D2 - GPIO4 - I²C SDA
## D3 - GPIO0 - Pluviomètre
## D4 - GPIO2 - Anémomètre
## D5 - GPIO14
## D6 - GPIO12
## D7 - GPIO13
## D8 - GPIO15
#####################
## ADRESSES I²C
## 0x23 BH1750
## 0x40 INA3221
## 0x48 ADS1115
## 0x76 BME280
substitutions:
system_name: weatherstation
friendly_name: Station Météo
device_description: "Station Météo"
packages:
device: !include devices/esp01_1m.yaml
i2c:
frequency: 100kHz
ads1115:
- address: 0x48
#####################
## SENSORS:
#####################
sensor:
#####################
## WIFI
#####################
- platform: ina3221
address: 0x40
channel_1:
shunt_resistance: 0.1 ohm
current:
name: "INA3221 Channel 1 Current"
power:
name: "INA3221 Channel 1 Power"
bus_voltage:
name: "INA3221 Channel 1 Bus Voltage"
shunt_voltage:
name: "INA3221 Channel 1 Shunt Voltage"
#channel_2:
# ...
#channel_3:
# ...
update_interval: 60s
- platform: uptime
name: Uptime Sensor
id: uptime_sensor
update_interval: 60s
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state : !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? to_string(days) + "d " : "") +
(hours ? to_string(hours) + "h " : "") +
(minutes ? to_string(minutes) + "m " : "") +
(to_string(seconds) + "s")
).c_str();
- platform: ads1115
multiplexer: 'A0_GND'
gain: 4.096
name: "ADS1115 Channel A0-GND"
#####################
## CLIMAT EXT
#####################
- platform: bme280
temperature:
name: "Température extérieure"
id: bme280_temperature
oversampling: 16x
pressure:
name: "Pression atmosphérique"
id: bme280_pressure
humidity:
name: "Humidité extérieure"
id: bme280_humidity
address: 0x76
update_interval: 60s
- platform: template
name: "Altitude"
lambda: |-
const float STANDARD_SEA_LEVEL_PRESSURE = 1013.25; //in hPa, see note
return ((id(bme280_temperature).state + 273.15) / 0.0065) *
(powf((STANDARD_SEA_LEVEL_PRESSURE / id(bme280_pressure).state), 0.190234) - 1); // in meter
update_interval: 15s
icon: 'mdi:signal'
unit_of_measurement: 'm'
- platform: template
name: "Humidité absolue"
lambda: |-
const float mw = 18.01534; // molar mass of water g/mol
const float r = 8.31447215; // Universal gas constant J/mol/K
return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) /
(id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) /
((273.15 + id(bme280_temperature).state) * r); // in grams/m^3
accuracy_decimals: 2
update_interval: 15s
icon: 'mdi:water'
unit_of_measurement: 'g/m³'
- platform: template
name: "Point de rosée"
lambda: |-
return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/
(243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)-
((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state))));
unit_of_measurement: °C
icon: 'mdi:thermometer-alert'
- platform: template
name: "Pression relative 1"
icon: "mdi:gauge"
##formule esphome.io possiblement fausse
lambda: |-
const float STANDARD_ALTITUDE = 8; // en metres
return id(bme280_pressure).state / powf(1 - ((0.0065 * STANDARD_ALTITUDE) /
(id(bme280_temperature).state + (0.0065 * STANDARD_ALTITUDE) + 273.15)), 5.257); // in hPa
update_interval: 15s
unit_of_measurement: 'hPa'
- platform: template
name: "Pression relative 2"
icon: "mdi:gauge"
##formule possiblement vraie
lambda: |-
const float STANDARD_ALTITUDE = 8; // in meters, see note
return (id(bme280_pressure).state)/powf((1-((float)(STANDARD_ALTITUDE))/44330), 5.255);
update_interval: 60s
unit_of_measurement: 'hPa'
#####################
## LUMIOSITE EXT
#####################
- platform: bh1750
name: "Luminosité"
address: 0x23
update_interval: 60s
#####################
## ANEMOMETRE
#####################
- platform: pulse_counter
pin:
number: GPIO2
mode: INPUT_PULLUP
unit_of_measurement: 'm/s'
name: "vent vitesse m/s"
id: wind_meter_mps
icon: 'mdi:weather-windy'
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
internal_filter: 13us
update_interval: 60s
## rotations_par_sec = impulsions / 2 / 60
## circ_m = 0.09 * 2 * 3.14 = 0.5652
## mps = 1.18 * circ_m * rotations_par_sec
## mps = 1.18 * 0.5652 / 2 / 60 = 0.0055578
filters:
- multiply: 0.0055578
#- sliding_window_moving_average:
# window_size: 2
# send_every: 1
- platform: template
name: 'vent vitesse km/h'
icon: 'mdi:weather-windy'
id: wind_meter_kmph
lambda: return id(wind_meter_mps).state;
unit_of_measurement: 'km/h'
## convertion des m/s en km/h pour une meilleure perception de la vitesse
## 1 m/s = 3.6 km/h
filters:
- multiply: 3.6
- platform: template
name: 'vent vitesse noeud'
icon: 'mdi:weather-windy'
id: wind_meter_knot
lambda: return id(wind_meter_mps).state;
unit_of_measurement: 'nd'
update_interval: 60s
## convertion des m/s en noeud avec indication de l'échelle de Beaufort
## 1 m/s = 1.94384 nd
filters:
# - throttle_average: 5s
- multiply: 1.94384
on_value:
lambda: |-
if (id(wind_meter_knot).state < 1) {
id(wind_scale).publish_state("Calme");
} else if (id(wind_meter_knot).state >= 1 && id(wind_meter_knot).state < 3) {
id(wind_scale).publish_state("Très légère brise");
} else if (id(wind_meter_knot).state >= 3 && id(wind_meter_knot).state < 7) {
id(wind_scale).publish_state("Légère brise");
} else if (id(wind_meter_knot).state >= 7 && id(wind_meter_knot).state < 11) {
id(wind_scale).publish_state("Petite brise");
} else if (id(wind_meter_knot).state >= 11 && id(wind_meter_knot).state < 16) {
id(wind_scale).publish_state("Jolie brise");
} else if (id(wind_meter_knot).state >= 16 && id(wind_meter_knot).state < 21) {
id(wind_scale).publish_state("Bonne brise");
} else if (id(wind_meter_knot).state >= 21 && id(wind_meter_knot).state < 27) {
id(wind_scale).publish_state("Vent frais");
} else if (id(wind_meter_knot).state >= 27 && id(wind_meter_knot).state < 34) {
id(wind_scale).publish_state("Grand frais");
} else if (id(wind_meter_knot).state >= 34 && id(wind_meter_knot).state < 41) {
id(wind_scale).publish_state("Coup de vent");
} else if (id(wind_meter_knot).state >= 41 && id(wind_meter_knot).state < 48) {
id(wind_scale).publish_state("Fort coup de vent");
} else if (id(wind_meter_knot).state >= 48 && id(wind_meter_knot).state < 56) {
id(wind_scale).publish_state("Tempête");
} else if (id(wind_meter_knot).state >= 56 && id(wind_meter_knot).state < 64) {
id(wind_scale).publish_state("Violente tempête");
} else if (id(wind_meter_knot).state >= 64) {
id(wind_scale).publish_state("Ouragan");
} else {
id(wind_scale).publish_state("Null");
}
#####################
## PLUVIOMETRE
#####################
- platform: pulse_counter
pin:
number: GPIO0
mode: INPUT_PULLUP
unit_of_measurement: 'mm'
name: "pluviomètre"
icon: 'mdi:weather-rainy'
id: rain_gauge
internal: true
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
internal_filter: 13us
update_interval: 60s
filters:
# Each 0.011" (0.2794mm) of rain causes one momentary contact closure
- multiply: 0.2794
accuracy_decimals: 4
- platform: integration
name: "pluie par min"
id: rain_per_min
time_unit: min
unit_of_measurement: 'mm'
icon: 'mdi:weather-rainy'
sensor: rain_gauge
- platform: total_daily_energy
name: "pluie journalière"
power_id: rain_gauge
unit_of_measurement: 'mm'
icon: 'mdi:weather-rainy'
# x60 To convert to aggregated rain amount
filters:
- multiply: 60
#####################
## GIROUETTE
#####################
- platform: adc
id: source_sensor
pin: A0
name: ADC
internal: true
update_interval: 60s
accuracy_decimals: 1
filters:
- multiply: 0.846153 # 3.9 -> 3.3V
- platform: resistance
sensor: source_sensor
id: resistance_sensor
configuration: DOWNSTREAM
resistor: 10kOhm
internal: true
name: Resistance Sensor
reference_voltage: 3.9V
accuracy_decimals: 1
filters:
- median:
window_size: 7
send_every: 4
send_first_at: 3
- heartbeat: 30s
on_value:
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 2061
below: 2082
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "N"
- sensor.template.publish:
id: wind_heading
state: 0.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 987
below: 1008
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "NNE"
- sensor.template.publish:
id: wind_heading
state: 22.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 1130
below: 1150
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "NE"
- sensor.template.publish:
id: wind_heading
state: 45.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 193
below: 212
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "ENE"
- sensor.template.publish:
id: wind_heading
state: 67.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 215
below: 234
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "E"
- sensor.template.publish:
id: wind_heading
state: 90.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 153
below: 174
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "ESE"
- sensor.template.publish:
id: wind_heading
state: 112.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 432
below: 453
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "SE"
- sensor.template.publish:
id: wind_heading
state: 135.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 288
below: 309
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "SSE"
- sensor.template.publish:
id: wind_heading
state: 157.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 683
below: 704
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "S"
- sensor.template.publish:
id: wind_heading
state: 180.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 575
below: 596
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "SSO"
- sensor.template.publish:
id: wind_heading
state: 202.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 1592
below: 1613
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "SO"
- sensor.template.publish:
id: wind_heading
state: 225.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 1505
below: 1526
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "OSO"
- sensor.template.publish:
id: wind_heading
state: 247.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 2556
below: 2577
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "O"
- sensor.template.publish:
id: wind_heading
state: 270.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 2183
below: 2204
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "ONO"
- sensor.template.publish:
id: wind_heading
state: 292.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 2368
below: 2389
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "NO"
- sensor.template.publish:
id: wind_heading
state: 315.0
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 1810
below: 1831
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "NNO"
- sensor.template.publish:
id: wind_heading
state: 337.5
- if:
condition:
sensor.in_range:
id: resistance_sensor
above: 2770
below: 2780
then:
- text_sensor.template.publish:
id: wind_dir_card
state: "erreur"
- sensor.template.publish:
id: wind_heading
state: "400"
- platform: template
name: "vent angle"
id: wind_heading
unit_of_measurement: "°"
- platform: template
name: "résistance anémomètre"
id: resistance_sensor_value
lambda: return id(resistance_sensor).state;
unit_of_measurement: 'ohm'
#####################
## TEXT SENSOR
#####################
text_sensor:
#####################
## ECHELLE DE BEAUFORT
#####################
- platform: template
name: 'vent échelle de Beaufort'
icon: 'mdi:tailwind'
id: wind_scale
update_interval: 60s
#####################
## VENT VITESSE
#####################
- platform: template
name: "vent direction cardinale"
id: wind_dir_card
update_interval: 60s
- platform: template
name: Uptime Human Readable
id: uptime_human
icon: mdi:clock-start
#####################
## INTERVAL
#####################
interval:
- interval: 60s
then:
- sensor.integration.reset: rain_per_min
Le projet va évoluer : capteur UV, gaz, ... Si vous avez des idées je suis preneur et si vous trouvez des erreurs je suis prenneur également.
[MàJ 22-04-22 Mise à dispo du câblage]
Voici le câble de la V1
Le schéma fritzing est pour le principe les couleurs ne correspondent pas à la réalité et les contacts reed symbolisent les capteurs. Les couleurs sont spécifiées dans la partie borniers dans le schéma ci dessous.



