Ma femme et moi nous occupons (entre autres) de chambres d’hôtes. La chasse d’eau de l’une des chambres est branchée sur une fosse étanche et comme toutes les chasses d’eau, il lui arrive de rester bloquée. Quand cela se produit alors que les hôtes viennent de partir, personne n’est là pour s’en rendre compte (à part nous éventuellement mais nous ne surveillons pas en permanence ce qui se passe dans les chambres…) et l’eau coule dans la fosse étanche, cette dernière coûtant très cher à vider (220 € pour 3 m3 !).
D’où l’intérêt d’un système de surveillance automatique qui prévient dès que le réservoir de la chasse reste vide pendant un certain temps ( ce qui signifie que le remplissage de la chasse coule directement dans la fosse étanche).
Il y a deux boitiers : un derrière la chasse d’eau de la chambre d’hôtes et un dans la maison principale. Ces deux boitiers communiquent via une liaison série radio (j’ai choisi ce modèle. Il possède une portée de transmission assez importante car les murs de la maison sont très épais ; le Wifi a par exemple ne passe pas et j’ai tout mon réseau local en CPL)
Pour le boitier « chasse d’eau », j’ai acheté un capteur de niveau d’eau que j’ai mis dans le réservoir de la chasse. Il s’agit de deux bandes de cuivre sur un circuit imprimé ; quand l’eau remplit le réservoir, cela fait contact entre les deux bandes. Ce capteur vient en fait avec une électronique de traitement (voir 1 sur la photo ci-dessous) qui commande un relais. Le relais est branché sur une entrée digitale de la carte micro-contrôleur (2 sur la photo). Ce n’est pas une carte Arduino mais comme le micro est un Atmega 328, j’ai utilisé l’environnement Arduino pour la programmer (voir le code plus loin).
Quand le réservoir est vide (parce qu’une chasse vient d’être tirée, par exemple), un signal est transmis via la liaison série radio (3 sur la photo) à un autre boitier se trouvant dans la maison principale (voir plus loin).
Enfin, tout ceci est alimenté via une double alimentation 5V – 12V : le 5V pour la carte micro-contrôleur, le 12V pour le relais. J’ai utilisé une alimentation de disque dur externe, qui ressort la masse, le 5V et le 12V sur une prise DIN (2 broches par type de signal, donc 6 en tout). Cette prise est connectée sur une carte prototype (4 sur la photo) sur laquelle j’ai mis un relais qui pour l’instant ne sert à rien, mais qui aura son utilité dans le futur.

Voici le code du micro-contrôleur du boitier « chasse d’eau ».
int etatChasse = 0; // 0: pas de chasse - 1: début chasse - 2: alarme chasse int compteurChasse = 0;
void setup() {
Serial.begin(9600);
// Signal niveau d'eau pinMode(2, INPUT);
}
void loop() {
int sensorValue = digitalRead(2);
// Début chasse
if ((sensorValue==1) && (etatChasse==0)) {
etatChasse = 1;
compteurChasse = 0;
Serial.print(etatChasse);
}
// Chasse en cours
else if ((sensorValue==1) && (etatChasse==1)) {
compteurChasse++;
}
// Fin chasse après chasse normale
if ((sensorValue==0) && (etatChasse==1)) {
etatChasse = 0;
compteurChasse = 0;
Serial.print(etatChasse);
}
// Fin chasse après alarme chasse
if ((sensorValue==0) && (etatChasse==2)) {
etatChasse = 0;
compteurChasse = 0;
Serial.print(etatChasse);
}
// Alarme chasse
if ((compteurChasse>=20) && (etatChasse==1)) {
etatChasse = 2;
Serial.print(etatChasse);
}
delay(10000); }
Lorsque le réservoir de la chasse d’eau reste est vide, le boitier « maison » reçoit un signal via la liaison série radio (1 sur la photo ci-dessous). Le signal est transmis au micro-contrôleur (un Arduino Nano, voir 2 sur la photo). Celui-ci stocke l’info sur une SD Card (voir 3 sur la photo) pour que je fasse éventuellement des statistiques un jour. Le jour est la date sont enregistrés car l’Arduino est aussi connecté à un module horloge RTC (4 sur la photo). Dans le même temps, la diode jaune d’allume (5 sur la photo) alors qu’elle est verte lorsque le réservoir est plein. Le micro entame alors une mesure du temps pendant lequel le réservoir est vide. Si ça dure plus de 3 minutes, le micro allume la diode rouge et commute un relais (6 sur la photo). Ce relais est branché sur un transmetteur téléphonique (que j’ai acheté à une époque mais qui ne me servait plus) via deux fils soudés sur une des touches d’alarme du transmetteur (voir dernière photo). Ce transmetteur est branché sur ma ligne de téléphone Internet et m’appelle automatiquement sur mon portable.


Voici le code du micro-contrôleur du boitier « maison » :
#include <SdFat.h> #include <SdFatUtil.h> #include <WProgram.h> #include <Wire.h> #include <DS1307.h> // written by mattt on the Arduino forum and modified by D. Sjunnesson
#define LED_VERTE 3 #define LED_JAUNE 4 #define LED_ROUGE 5
// file system object SdFat sd;
// binary file object SdFile file;
// buffer to format data - makes it eaiser to echo to Serial char buf[200]; //------------------------------------------------------------------------------ // store error strings in flash to save RAM #define error(s) sd.errorHalt_P(PSTR(s)) //------------------------------------------------------------------------------
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT);
// Allumage des 3 LEDs pendant 3s à l'init digitalWrite(LED_VERTE, HIGH); digitalWrite(LED_JAUNE, HIGH); digitalWrite(LED_ROUGE, HIGH); delay(3000); digitalWrite(LED_VERTE, LOW); digitalWrite(LED_JAUNE, LOW); digitalWrite(LED_ROUGE, LOW);
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with // breadboards. use SPI_FULL_SPEED for better performance. // if SD chip select is not SS, the second argument to init is CS pin number if (!sd.init(SPI_HALF_SPEED)) sd.initErrorHalt();
// create a new file in root, the current working directory
char name[] = "datalog.txt";
file.open(name, O_CREAT | O_WRITE | O_APPEND);
if (!file.isOpen()) {
error("file.open");
while(1) {
blink_led(LED_JAUNE,1000);
}
}
//format header in buffer obufstream bout(buf, sizeof(buf));
bout << pstr("Initialisation");
// add CR/LF for Windows style file (file.write is binary, not text) bout << "\r\n"; file.write(buf);
// force write of header to SD card file.sync();
if (file.writeError) {
error("write header failed");
while(1) {
blink_led(LED_JAUNE,1000);
}
}
else {
digitalWrite(LED_VERTE, HIGH);
}
}
void loop() {
// make a string for assembling the data to log: String dataString = "";
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte);
if (incomingByte==49) {
Serial.print("Debut chasse: ");
digitalWrite(LED_VERTE, LOW);
digitalWrite(LED_JAUNE, HIGH);
printDate();
writeDataString(1);
}
if (incomingByte==48) {
Serial.print("Fin chasse: ");
digitalWrite(LED_JAUNE, LOW);
digitalWrite(LED_ROUGE, LOW);
digitalWrite(LED_VERTE, HIGH);
printDate();
writeDataString(0);
}
if (incomingByte==50) {
Serial.print("Alarme chasse: ");
digitalWrite(LED_JAUNE, LOW);
digitalWrite(LED_ROUGE, HIGH);
printDate();
writeDataString(2);
digitalWrite(2, HIGH);
delay(500);
digitalWrite(2, LOW);
}
} }
void writeDataString(int typeLog) {
// use buffer stream to format line
obufstream bout(buf, sizeof(buf));
switch (typeLog) {
case 0:
bout << pstr("Fin chasse: ");
break;
case 1:
bout << pstr("Debut chasse: ");
break;
case 2:
bout << pstr("Alarme chasse: ");
break;
}
// add CR/LF for Windows style file (file.write is binary, not text)
bout << RTC.get(DS1307_HR,true);//read the hour and also update all the values by pushing in true
bout << ":";
bout << RTC.get(DS1307_MIN,false);//read minutes without update (false)
bout << ":";
bout << RTC.get(DS1307_SEC,false);//read seconds
bout << " "; // some space for a more happy life
bout << RTC.get(DS1307_DATE,false);//read date
bout << "/";
bout << RTC.get(DS1307_MTH,false);//read month
bout << "/";
bout << RTC.get(DS1307_YR,false); //read year
bout << "\r\n";
file.write(buf);
file.sync();
// check for errors
if (file.writeError) {
error("write data failed");
while(1) {
blink_led(LED_JAUNE, 500);
}
}
}
void printDate() {
Serial.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
Serial.print(":");
Serial.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
Serial.print(":");
Serial.print(RTC.get(DS1307_SEC,false));//read seconds
Serial.print(" "); // some space for a more happy life
Serial.print(RTC.get(DS1307_DATE,false));//read date
Serial.print("/");
Serial.print(RTC.get(DS1307_MTH,false));//read month
Serial.print("/");
Serial.print(RTC.get(DS1307_YR,false)); //read year
Serial.println();
}
void blink_led(int led, int delai) {
// Attention: mettre dans une boucle infinie
digitalWrite(led, HIGH); // set the LED on
delay(delai); // wait for a second
digitalWrite(led, LOW); // set the LED off
delay(delai); // wait for a second
}
Au passage, voici le code du programme permettant de mettre à l’heure l’horloge RTC (vous constaterez que j’ai mis tout ça en route entre Noël et le jour de l’an…).
/*Reads the value from a Real Time Clock (RTC) DS1307 and displays it in the serial monitor * *Created by D. Sjunnesson 1scale1.com d.sjunnesson (at) 1scale1.com * *Created with combined information from *http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1180908809 *http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1191209057 * * *Big credit to mattt (please contact me for a more correct name...) from the Arduino forum *which has written the main part of the library which I have modified * */
#include <WProgram.h> #include <Wire.h> #include <DS1307.h> // written by mattt on the Arduino forum and modified by D. Sjunnesson
void setup()
{
Serial.begin(9600);
RTC.stop(); RTC.set(DS1307_SEC,1); //set the seconds RTC.set(DS1307_MIN,05); //set the minutes RTC.set(DS1307_HR,12); //set the hours RTC.set(DS1307_DOW,4); //set the day of the week RTC.set(DS1307_DATE,29); //set the date RTC.set(DS1307_MTH,12); //set the month RTC.set(DS1307_YR,11); //set the year RTC.start();
}
void loop()
{
Serial.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
Serial.print(":");
Serial.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
Serial.print(":");
Serial.print(RTC.get(DS1307_SEC,false));//read seconds
Serial.print(" "); // some space for a more happy life
Serial.print(RTC.get(DS1307_DATE,false));//read date
Serial.print("/");
Serial.print(RTC.get(DS1307_MTH,false));//read month
Serial.print("/");
Serial.print(RTC.get(DS1307_YR,false)); //read year
Serial.println();
delay(1000);
}
En résumé, lorsque le réservoir de la chasse est vide pendant plus de trois minutes, cela signifie qu’il ne se remplit pas car la chasse est probablement bloquée en position « tirée ». Le système me permet alors d’être prévenu par téléphone.
Ce système est bien sûr perfectible car lorsque je ne suis pas là, je ne peux rien faire. Mais j’ai prévu de nombreuses évolutions. Je les mettrai en œuvre dès que j’aurai reçu le Raspberry Pi (l’ordinateur embarqué à 35$, pour ceux qui ne connaissent pas) que j’ai enfin pu commander il y a peu. Voici ces évolutions à venir :
J’envisage aussi de mesurer le débit d’eau (avec ça) quand la chasse se remplit pour savoir à quel moment je dois appeler le vidangeur de fosse (celle-ci se trouvant sous une dalle de béton presque insoulevable, ça me permettrait d’éviter de me bousiller le dos pour surveiller le niveau de la fosse).
Bien sûr, je pourrais rajouter simplement une interface ethernet à l’Arduino Nano, mais mon Raspberry Pi est destiné à être le « cerveau domotique » de la maison et il ne servira pas qu’à cette seule application. Donc autant tout gérer sur un matériel unique.
Un dernier petit mot pour dire que je n’ai pas acheté grand-chose (voir rien) chez AlphaCrucis pour faire ça car je ne connaissais pas l’existence de ce site à l’époque, et c’est bien dommage ! En effet, je me rends compte que je pourrais maintenant trouver ici la quasi-totalité de ce dont j’ai déjà eu besoin pour ce projet et mes autres projets passés. Promis, pour les projets futurs, je serai un bon client !
Aucun nouveau produit à l'heure actuelle