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.