Pluviomètre à Godet Basculant Avancé avec Intégration Arduino
Composants et Fournitures
| Composant | Quantité |
|---|---|
| Arduino Nano R3 | 1 |
| Module RTC I2C DS1307 (Tiny RTC) | 1 |
| Module Carte SD - LC Studios | 1 |
| Alimentation 7-12 VDC (ou adaptateur secteur) | 1 |
| Écran LCD Standard Adafruit 16x2 Blanc sur Bleu | 1 |
| Registre à Décalage Texas Instruments SN74HC595N (Série vers Parallèle) | 1 |
| Résistance 1 kΩ | 2 |
| Résistance 330 Ω | 2 |
| Condensateur 100 nF | 1 |
| Potentiomètre Monotour 10 kΩ | 1 |
| Bouton Poussoir CI Momentané | 1 |
| Interrupteur à Reed (ILS) SPST-NO | 1 |
| Aimant (7 mm Ø x 7 mm long) | 1 |
| Plaque d'essai Simple Face 5x10 cm | 1 |
Outils et Machines Nécessaires
- Imprimante 3D (générique)
- Fer à souder (générique)
À Propos de ce Projet
Ce pluviomètre à godet basculant s'inspire des modèles utilisés par les météorologues professionnels. L'eau de pluie est dirigée par un entonnoir vers un godet basculant type bascule : chaque compartiment contient ~2 ml. Quand l'un se remplit, il bascule et l'eau remplit l'autre. À chaque bascule, un contact à reed (ILS) s'active brièvement, envoyant un signal à l'interruption matérielle de l'Arduino. L'Arduino compte chaque bascule et la convertit en pluviométrie (mm/pouces) selon le volume du godet et la surface du collecteur (107,1 cm² / 16,605 pouces²).
L'unité d'affichage intérieure propose un menu : 'heure courante', 'heure précédente', 'jour courant', 'jour précédent'.
À chaque bascule, un événement horodaté est écrit sur la carte SD. Ce fichier peut être importé dans Excel pour analyse et graphiques.
Bien que je n'aie pas de vidéo du basculement réel, cette vidéo montre l'enregistrement d'un épisode pluvieux réel.
Étape 1 : Impression 3D de Tous les Composants
J'ai utilisé du PETG pour tous les composants (résistant UV et températures pour usage extérieur). Pour le filtre supérieur, désactivez toutes les couches horizontales (haut/bas) pour créer la porosité.
Étape 2 : Préparation Circuit Panneau Avant
Insérez le LCD sur la plaque PY-5x10cm (sans souder) avec broche 1 du LCD dans le trou C-1. Percez la plaque aux 4 trous de fixation du LCD. Retirez le LCD pour assemblage ultérieur.
Étape 3 : Assemblage Circuit Panneau Avant
Placez le 74HC595N, interrupteurs et résistances comme indiqué. Câblez tous les fils nécessaires (voir schéma) vers les points de connexion du LCD, ainsi que 15 cm pour connexion à la seconde carte.
Étape 4 : Montage du LCD
Montez le LCD sur la carte panneau avant avec les entretoises imprimées pour dégager le CI. Fixez avec vis M3x15mm et écrous. (Toute visserie chez Fastenal/McMaster-Carr)
Étape 5 : Assemblage Carte Principale
Insérez l'Arduino avec broche D12 au trou R27. Ajoutez condensateur, résistances, câblez tout avant d'insérer modules SD et RTC. Référez-vous au schéma de câblage.
Étape 6 : Modules SD et RTC
Montez lecteur SD aux trous A-3 à B-10. Montez TinyRTC aux trous C-24 à I-24. Soudez toutes connexions.
Étape 7 : Boîtier Unité Intérieure
Percez le boîtier pour les deux fils vers l'unité extérieure, et pour l'alimentation secteur. Passez les fils, soudez aux bons emplacements. Glissez la carte principale dans le boîtier, fixez avec 2 vis M3x6mm. Insérez le bouton poussoir dans la façade, fixez le circuit panneau avant avec vis M3x6mm. Note : j'ai utilisé une petite pièce en laiton tourné pour le bouton au lieu de la pièce imprimée, préférant le "toucher".
Étape 8 : Fixation Façade
Vissez la façade avec vis M3-0.5 x 10mm tête plate.
Étape 9 : Test Initial
Branchez USB au PC, téléversez le programme RTC pour régler l'horloge. Après mise à l'heure, téléversez le programme principal. Insérez carte SD. Testez en court-circuitant les fils vers le contact reed de l'unité extérieure. Les totaux pluviométriques doivent s'incrémenter à chaque fermeture de contact. Vérifiez la carte SD sur PC (Notepad/WordPad) : fichier "Text.txt" avec horodatage pour chaque bascule.
Étape 10 : Assemblage Unité Extérieure
Fixez le contact reed sur la sous-base avec colliers de serrage. Fixez l'aimant sur le godet, montez le godet sur un tube laiton 1/8" (≈5 cm). Avant assemblage, passez un foret 1/8" dans les trous du godet pour éliminer les bavures. Le godet doit basculer librement sans friction. Limez si nécessaire. Ajoutez une petite rondelle 1/8" côté extérieur pour réduire le jeu. Déterminez la fixation extérieure : j'ai utilisé un profilé aluminium 1". Fixez la base au profilé avec boulons 1/4-20 de l'intérieur vers l'extérieur. Fixez la sous-base au fond de l'unité extérieure avec vis M3-0.5x10mm.
Étape 11 : Entonnoir et Protection Oiseaux
Insérez l'entonnoir dans le couvercle supérieur. Coupez ~24 morceaux de fil galvanisé 18 gauge (2"). Chauffez chaque morceau au chalumeau/briquet et pressez dans le plastique supérieur. Ces fils dissuadent les oiseaux de se poser. Mesurez la pluie, pas les fientes ! Fixez le couvercle au boîtier principal avec (4) vis M3-0.5x6mm. Installez le filtre dans l'entonnoir (retient feuilles, évite colmatage). Vérifiez/nettoyez périodiquement.
Étape 12 : Installation Extérieure
Montez l'unité extérieure, tirez les fils vers l'unité intérieure. Assurez-vous que le sommet de l'unité extérieure est de niveau dans les deux directions.
Étape 13 : Mise en Service
Alimentez et versez de l'eau dans l'unité extérieure pour vérifier le fonctionnement.
Étape 14 : Vérification Précision (Optionnel)
Versez TRÈS LENTEMENT une tasse d'eau (236,6 ml = 14,44 pouces³). L'appareil doit afficher 0,87" (22 mm) de pluie. (Surface collecteur 16,605 pouces² → Pluie = 14,44/16,605 = 0,87"). Ajustez le facteur de correction dans le programme principal si votre appareil diffère.
Félicitations ! Profitez du suivi de vos précipitations.
Code
Code Arduino pour Réglage Heure RTC
Chargez ce code en premier pour régler l'heure du RTC. Modifiez date/heure réelles avant téléversement.
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte decToBcd(byte val) { return (val/10*16) + (val%10); }
byte bcdToDec(byte val) { return (val/16*10) + (val%16); }
void setDateDs1307() {
second = 0; minute = 11; hour = 12;
dayOfWeek = 5; dayOfMonth = 24; month = 7; year = 20;
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(decToBcd(0));
Wire.write(decToBcd(second)); // Bit 7 = 0 démarre l'horloge
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs1307() {
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(decToBcd(0)); Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
second = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0x3f);
dayOfWeek = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
Serial.print(hour); Serial.print(":"); Serial.print(minute); Serial.print(":"); Serial.print(second);
Serial.print(" "); Serial.print(month); Serial.print("/"); Serial.print(dayOfMonth); Serial.print("/"); Serial.print(year);
Serial.println();
}
void setup() { Wire.begin(); Serial.begin(19200); setDateDs1307(); }
void loop() { delay(2000); getDateDs1307(); }
Programme Principal Pluviomètre (Arduino)
Installez toutes les bibliothèques associées avant compilation. Référence pour mise à jour bibliothèque LiquidCrystal : roboindia.com
/* Pluviomètre à Godet Basculant - Écrit par Bob Torrence */
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_SR.h> // Version spéciale pour LCD série 3 broches
// LCD et broches : Data/Enable=6, Clock=5, Latch=9
LiquidCrystal_SR lcd(6, 5, 9);
RTC_DS3231 rtc;
int backlight = 7; // Rétroéclairage sur D7
const byte interruptPin_bucket = 3; // Godet (ILS)
const byte interruptPin_menu = 2; // Bouton menu
volatile int Bucket_Tip_Occurence = 0;
volatile int Menu_Select = 0;
float Bucket_tip_hour_total = 0;
float Bucket_tip_current_hour_total = 0;
float Bucket_tip_previous_hour_total = 0;
float Bucket_tip_current_day_total = 0;
float Bucket_tip_previous_day_total = 0;
int current_minute, loop_minute, current_hour, loop_hour, current_day, loop_day;
int tip_counter = 0;
float conversion_factor = 0.00854; // Pouces par bascule (calculé : volume godet / surface collecteur)
volatile unsigned long backlightOfftime;
volatile unsigned long backlightOnDuration = 30000; // 30s rétroéclairage après appui menu
String print_time(DateTime timestamp) {
char message[120];
sprintf(message, "%02d:%02d:%02d %02d/%02d",
timestamp.hour(), timestamp.minute(), timestamp.second(),
timestamp.month(), timestamp.day());
return String(message);
}
File myFile;
void setup() {
lcd.begin(16, 2);
lcd.home();
rtc.begin();
pinMode(10, OUTPUT);
pinMode(backlight, OUTPUT);
digitalWrite(backlight, HIGH);
backlightOfftime = millis() + backlightOnDuration;
if (!SD.begin(4)) { lcd.print("Inserez carte SD"); return; }
pinMode(interruptPin_bucket, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin_bucket), count, FALLING);
pinMode(interruptPin_menu, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin_menu), menu, RISING);
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) { myFile.println("Pluviomètre prêt - mise sous tension"); myFile.close(); }
DateTime now = rtc.now();
current_minute = loop_minute = now.minute();
current_hour = loop_hour = now.hour();
current_day = loop_day = now.day();
lcd.setCursor(0, 0); lcd.print(print_time(now));
lcd.setCursor(1, 1); lcd.print("Pluviometre");
}
void loop() {
DateTime now = rtc.now();
current_minute = now.minute(); loop_minute = now.minute();
current_hour = now.hour(); loop_hour = now.hour();
current_day = now.day(); loop_day = now.day();
// Boucle jour
while (loop_day - current_day == 0) {
// Boucle heure
while (loop_hour - current_hour == 0) {
if (millis() > backlightOfftime) digitalWrite(backlight, LOW);
if (Bucket_Tip_Occurence == 1) {
Bucket_Tip_Occurence = 0;
tip_counter++;
DateTime now = rtc.now();
myFile = SD.open("test.txt", FILE_WRITE);
myFile.print("Evenement ");
myFile.print(now.year()); myFile.print('/'); myFile.print(now.month()); myFile.print('/'); myFile.print(now.day());
myFile.print(" "); myFile.print(now.hour()); myFile.print(':'); myFile.print(now.minute()); myFile.print(':'); myFile.print(now.second());
myFile.print(" "); myFile.print(conversion_factor, 5); myFile.println();
myFile.close(); delay(200);
} else {
DateTime now = rtc.now(); loop_hour = now.hour();
}
// Affichage selon menu
switch (Menu_Select) {
case 1: lcd.clear(); lcd.setCursor(0,0); lcd.print("Heure Courante"); lcd.setCursor(0,1); lcd.print(tip_counter * conversion_factor); delay(500); break;
case 2: lcd.clear(); lcd.setCursor(0,0); lcd.print("Heure Precedente"); lcd.setCursor(0,1); lcd.print(Bucket_tip_previous_hour_total); delay(500); break;
case 3: lcd.clear(); lcd.setCursor(0,0); lcd.print("Jour Courant"); lcd.setCursor(0,1); lcd.print(Bucket_tip_current_day_total + tip_counter * conversion_factor); delay(500); break;
case 4: lcd.clear(); lcd.setCursor(0,0); lcd.print("Jour Precedent"); lcd.setCursor(0,1); lcd.print(Bucket_tip_previous_day_total); delay(500); break;
}
}
// Fin d'heure : totalisation
DateTime now = rtc.now();
current_hour = now.hour(); loop_day = now.day(); loop_hour = now.hour();
Bucket_tip_previous_hour_total = tip_counter * conversion_factor;
Bucket_tip_current_day_total += Bucket_tip_previous_hour_total;
tip_counter = 0;
}
// Fin de jour : totalisation
Bucket_tip_previous_day_total = Bucket_tip_current_day_total;
Bucket_tip_current_day_total = 0;
Bucket_tip_current_hour_total = 0;
tip_counter = 0;
}
// Interruption godet (ILS) - anti-rebond 300ms
void count() {
static unsigned long last_interrupt_time_bucket = 0;
unsigned long interrupt_time_bucket = millis();
if (interrupt_time_bucket - last_interrupt_time_bucket > 300) {
Bucket_Tip_Occurence = 1;
}
last_interrupt_time_bucket = interrupt_time_bucket;
}
// Interruption bouton menu - anti-rebond 300ms
void menu() {
static unsigned long last_interrupt_time_menu = 0;
unsigned long interrupt_time_menu = millis();
if (interrupt_time_menu - last_interrupt_time_menu > 300) {
if (digitalRead(backlight) == LOW) digitalWrite(backlight, HIGH);
else {
Menu_Select++; if (Menu_Select > 4) Menu_Select = 1;
}
backlightOfftime = millis() + backlightOnDuration;
}
last_interrupt_time_menu = interrupt_time_menu;
}
Pièces Personnalisées et Boîtiers (STL)
- Base unité extérieure (PETG, 30% remplissage)
- Couvercle unité extérieure (PETG, 30%)
- Entonnoir unité extérieure (PETG, 30%)
- Filtre entonnoir (PETG, 20%, sans couches horizontales haut/bas pour porosité)
- Sous-base godet (PETG, 30%)
- Godet basculant (PETG, 30%)
- Boîtier unité intérieure (PETG, 30%)
- Façade unité intérieure (PETG, 30%)
- Entretoises LCD (PETG, 30%)
- Modèle Fusion 360 assemblage extérieur (
.f3d,.step) - Modèle CAO unité intérieure (
.step,.f3z) - Bouton poussoir imprimé
Schémas
Schéma de câblage complet du projet
rain_gauge_NtjqXF6QEw.fzzProcessus de fabrication
- Manomètres de précision pour applications industrielles et de sécurité
- Stores intelligents : contrôle automatisé de la lumière avec Arduino et énergie solaire
- Jauges de hauteur numériques : Mesure précise et solutions de contrôle qualité
- Micromètre : Définition, Histoire, Composants et Utilisation Pratique
- Manomètres : types, fonctionnement, avantages et guide de sélection
- Maîtriser les jauges de contrainte : conversion du stress mécanique en signaux électriques précis
- Le manomètre Pirani : principes, applications et avantages
- Manomètres à membrane : précision et fiabilité expliquées
- Maîtriser les manomètres Bourdon : conception, fonctionnement et applications