Le programme ou sketch est déroulé en mode texte ci-dessous, et en fichier .ino dans le zip avec les fichiers de réalisation.
Je ne vais pas m'étendre sur les commentaires, car le détail est donné en bout de chaque ligne pour en comprendre ce que j'ai voulu faire.
Le gros avantage, c'est que chacun peut personnaliser son sketch au gré de ses besoins et de ses idées .
/* Ultrasonic Switch Relay activ up by the distance and the time preseted.
* by Bernard LECLERC 08/2018
*/
#include <LiquidCrystal.h> // include library code
#define TRIGG 10 // Output TRIGGER
#define ECHO 9 // Input Return ECHO
#define BUTTON 8 // Input Button
#define REL 7 // Output Relais
#define LED 6 // Command Back light
int tempo; // value loop relay activ
int numlight; // Value loop backlight
const long TIMEOUT = 25000UL; // 25ms = ~8m à 340m/s
float son= 340.0 / 1000; //sound's speed (mm/µs)
float Dmin, Dmax, Dprevious, DSetAl, SetTime; // Other data values
byte trend = ' '; //trend of distance measurements, up or down
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // LCD Pin's connection
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // initialize the library by associating any needed LCD interface pin
byte up[8] = { //defines upward arrow character
B00100,
B01110,
B10101,
B00100,
B00100,
B00100,
B00100,
};
byte down[8] = { //defines downward arrow character
B00100,
B00100,
B00100,
B00100,
B10101,
B01110,
B00100,
};
void setup()
{
lcd.createChar(0, up); //creates custom character (gylph) number 0 following definition "byte up[8]"
lcd.createChar(1, down); //creates custom character (gylph) number 1 following definition "byte down[8]"
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
pinMode(TRIGG, OUTPUT); //Set the pin as Output
digitalWrite(TRIGG, LOW); // Set the TRIGGER pin to LOW stat..
pinMode(ECHO, INPUT); //Set the pin as Input
pinMode(BUTTON, INPUT_PULLUP); //Set a pull up résistor on the button
pinMode(REL, OUTPUT); //Set an Output Relay
digitalWrite(REL, LOW); // Set the Relay pin to LOW stat..
pinMode(LED, OUTPUT); //Set an output back light
digitalWrite(LED, HIGH); // Set the LED pin activ max..
}
void loop()
{
debut:
digitalWrite(TRIGG, HIGH); // Mesurement begin by send
delayMicroseconds(10); //a puls HIGH to 10µs on the pin TRIGGER
digitalWrite(TRIGG, LOW);
int mesure = pulseIn(ECHO, HIGH, TIMEOUT); // Time between send et receive the ultra-sound
float distance_mm = mesure / 2.0 * son; //calcul the distance by the time
if (distance_mm<Dmin)
{Dmin=distance_mm;}
if (distance_mm>Dmax)
{Dmax=distance_mm;}
if (distance_mm > (Dprevious + 50)) //distance is increasing
{trend = byte(1);
digitalWrite(LED, HIGH);
numlight = 0;
}
if (distance_mm < (Dprevious - 50)) //distance is decreasing
{trend = byte(0);
}
if (numlight > 15){digitalWrite(LED,LOW);} //Shutdown backlight after many loop
if (Dmin<1 )//Preset first time a minimal value
{Dmin = 3500; }
Dprevious = distance_mm; //remember current measurement
lcd.clear(); // Clean display and show the messages and values
lcd.print("Dist = ");
lcd.print(distance_mm,0);
lcd.print("mm ");
lcd.write(trend); // write upward or downward arrow
lcd.setCursor(0, 1);
lcd.print("Mi ");
lcd.print(Dmin, 0);
lcd.print(" Ma ");
lcd.print(Dmax, 0);
delay (1000);
if (distance_mm < DSetAl) { //Alarm didtance detected and jump sub-routine
goto alarme;
}
if (tempo > SetTime) { // Time to hold the relay on; Nb loop
tempo = 0; //reset the Nb of loop
digitalWrite(REL, LOW); //shut down the relay
}
if (digitalRead (BUTTON)==LOW) { //Jump to sub-routine "Set the baklight time"when the button is pressed
goto dist_set;
}
numlight = numlight + 1; //increase value for backlight time
tempo = tempo + 1; //increase value for relay time
goto debut;
dist_set:
digitalWrite(LED, HIGH);
DSetAl = DSetAl + 10;
lcd.clear();
lcd.print("Alarme = ");
lcd.print(DSetAl,0);
lcd.print("mm ");
delay (200);
if (digitalRead(BUTTON)==LOW) {// More and more since the button is pressed
goto dist_set;
}
delay (3000);
goto time_set; // and jump to the sub-routine "Set relay time"
time_set:
SetTime = SetTime + 1;
lcd.clear();
lcd.print("Tempo = ");
lcd.print(SetTime,0);
lcd.print("sec ");
delay (200);
if (digitalRead(BUTTON)==LOW) {// More and more since the button is pressed
goto time_set;
}
delay (5000);
digitalWrite(LED,LOW);
goto debut;
alarme:
digitalWrite(REL, HIGH);
digitalWrite(LED, HIGH);
goto debut;
}

Dans un souci d'économie d'énergie, lorsque l'alimentation est assurée par des piles ou des batteries, le programme coupe le rétro-éclairage du LCD. celui-ci se ré-allume si la distance diminue ( un mobile s'approche ) ce qui donne une intensité de 20mA allumé et 10mA éteint . Une idée d'extinction progressive est tout-à-fait possible en utilisant la fonction PWM (modulation de largeur d'impulsion ) de la sortie utilisée par l'ajout d'une ou deux lignes de programme .

Le Boîtier :

Le boitier est réalisé avec l'imprimante 3D, ajusté au circuit, en fil PLA et se compose de 6 pièces:
- Une rosace de fixation murale.
- Une chape mobile en rotation dans la rosace.
- Un support mobile, à basculement avec la chape, et fixé par les même vis que le circuit et la partie inférieure du boitier.
- La partie inférieure de la boite avec deux trous pour les transducteurs ultrasoniques .
- La partie supérieure avec une fenêtre de visualisation pour le LCD 2 lignes 16 caractères, les oreillettes de verouillage et le guide du bouton.
- Le bouton, avec sa plaquette d'appui sur le micro poussoir .
La création est faite par DesignSpark Méchanical et ensuite exportée en fichier .stl pour être traîté par le puissant pilote d'impression Repétier Host .

Et Ici, tout ce qui sert à la réalisation :
Tlm (77.63 Ko)