top of page
Difficile de faire plus simple : une seule pièce d'habitation et un toit plat.
Dimensions extérieures : environ 45 x 54 x 33 mm.
Quatre ouvertures dont une porte.
... et c'est tout.
Plus modeste, on peut pas.
Les murs ont une épaisseur de 3 mm.
Difficile de faire plus simple : une seule pièce d'habitation et un toit plat.
Dimensions extérieures : environ 45 x 54 x 33 mm.
Quatre ouvertures dont une porte.
... et c'est tout.
Plus modeste, on peut pas.
Les murs ont une épaisseur de 3 mm.
Pour imprimer cette petite maison j'ai choisi du fil PolyWood. C'est un PLA avec du bois qui donne à la pièce un aspect "bois mat" ou "terre sèche". Facile à enduire et à peindre.
Suivant l'imprimante utilisée, il sera nécessaire de réduire au papier de verre les dimensions du toit pour qu'il s'encastre correctement et vienne en appui sur les petites nervures qui ceinturent le bâtiment à l'intérieur des murs.
Pour éviter l'affaissement des linteaux l'impression est paramétrée avec "supports d'impression", c'est à dire que les porte et fenêtres (ben oui, ya qu'une porte ! ) seront remplies d'une sorte de nid d'abeille qui supportera les linteaux au moment de leur impression.
Il faudra ensuite désoperculer toutes les ouvertures pour les débarrasser de ces supports, puis ébavurer correctement.
La maison, avec son toit, et la porte partiellement désoperculée.
Note :
Cette petite maison peut être facilement imprimée à l'échelle "N".
Il suffit, dans CURA by Dagoma, d'utiliser les mêmes fichiers ".stl" et d'appliquer le coefficient de réduction 0,54. (Hé oui ! Pas besoin de redessiner).
L'impression prendra 20 minutes et 4 grammes de PLA pour un coût matière de l'ordre de 0,20€ !
Si l'échelle 1:43 vous tente, il suffit d'appliquer un coefficient x2 dans CURA.
Il faudra 5 heures d'impression et 73 grammes de PLA (moins de 4€).
C'est encore jouable.
Ah ! petite remarque : le bâtiment est marqué "HUGO 2017" à l'intérieur.
Mon petit fils voulait que "son œuvre" soit signée ! (c'est la seule chose que j'ai faite sur ce modèle).
Téléchargements :
Petite maison en adobe
Un de mes petits fils voulait absolument dessiner et imprimer une maison en 3D.
J'ai orienté son choix vers un modèle simple : une petite maison de paysan modeste de la région de Santa Fe, en adobe, qui va me servir sur mon réseau. Tant qu'à faire...
Nombre de visites :
9
Orage
Nombre de visites :
Compteur de visites
ORAGE
-
14 séquences sonores de coups de tonnerre ;
-
éclairs aléatoires en durée et en intensité ;
-
volume sonore avec intensité et retard modulés en fonction de l'intensité des salves d'éclairs ;
-
intervalle aléatoire entre salves d'éclairs ;
-
télécommande infrarouge.
Date de création : 01/02/2022
Dernière modification : 09/02/2022
Cette animation lumineuse et sonore est la première que j'ai réalisée.
Elle fait suite à l'animation uniquement lumineuse (et sans télécommande IR), disponible ICI, et destinée à servir d'exercice de programmation en ARDUBLOCKLY pour mes camarades de club.
Si cette animation a un sens pour agrémenter votre réseau, alors n'hésitez surtout pas : le résultat est IMPRESSIONNANT !
Bon. OK. Faut pas habiter en immeuble !
PRÉSENTATION DU PROJET
Plus la salve d'éclairs est lumineuse, plus elle est proche, donc plus le son arrive rapidement et plus il est intense.
C'est ce que j'ai cherché à réaliser, et je dois dire que le résultat est à hauteur de mes attentes !
-
le nombre d'éclats par salve est aléatoire.
-
l'intensité de chaque éclat est aléatoire.
-
l'intensité lumineuse globale d'une salve d'éclairs est aléatoire.
-
la séquence sonore associée à une salve est aléatoire.
Le départ et l'arrêt de l'orage est télécommandé par infrarouge.
Suivant le code de démarrage saisi, on opte pour un orage à 4, 8 ou 16 coups de tonnerre (mais on peut paramétrer différemment).
Un son de coup de tonnerre contient pas mal de graves.
Il est donc important d'utiliser une enceinte de qualité. Pas forcément volumineuse.
Celle que j'utilise est une enceinte Sony de récupération (chez Émaüs. Pub gratuite) et qui mesure environ
30 x 20 x 18 cm.
En réalité j'ai choisi d'utiliser 2 HP :
-
une enceinte planquée sous la montagne ;
-
un petit HP de diamètre 60 mm caché derrière un bâtiment, éloigné d'environ 1 mètre de l'enceinte, et qui diffuse un peu plus d'aigus tout en augmentant la spatialisation du son.
Attention toutefois à l'impédance résultante des 2 HP en parallèle.
Le petit HP fait office de tweeter : il faut l'alimenter à travers un condensateur non polarisé d'environ 2,2 µF.
SCHÉMA
Deux particularités :
VS1838
Deux condensateurs sont raccordés sur l'entrée «3».
Leur rôle est d'empêcher que l'entrée «2» de l'ARDUINO reçoive des signaux parasites captés par les fils de liaison du VS1838 et interprétés comme de faux codes IR.
Si la liaison en question mesure moins de 2 ou 3 cm, on peut se passer de ces condensateurs.
MOSFET
L'étage de puissance qui alimente les LED est connecté à la sortie «9» de l'ARDUINO.
Cet étage sera alimenté par une source capable de délivrer 2 A sous 5 V DC, et indépendante de celle qui alimente l'ARDUINO et le DFPlayer.
En effet, même avec une alimentation commune fortement dimensionnée, les signaux PWM qui pilotent les LED avec un fort courant perturberaient – perturbent... expérience vécue – le fonctionnement de l'ARDUINO.
.
MATÉRIEL
-
x1 DFPlayer Mini ;
-
x1 carte «TF» (micro SD) ;
-
x1 ARDUINO Nano ;
-
X1 récepteur infrarouge VS1838B ;
-
x1 télécommande SONY TV compatible ;
-
x5 résistances 1/4 watt ;
-
x2 bornier à vis, pour la sortie HP et pour les LED ;
-
connecteurs supports pour le DFPlayer et l'ARDUINO Nano ;
-
x1 HP ou mini-enceinte ;
-
x1 bloc d'alimentation 4,5 ou 5 V DC ;
-
x1 bloc d'alimentation indépendant 5 V DC / 1 ou 2 A, pour l'alimentation des LED ;
Concernant les LED
J'écris «les» LED alors que le schéma n'en représente qu'une seule.
C'est que pour mon prototype j'ai utilisé un «panel» avec 9 LED directement alimenté en 5V DC comme celui représenté ci-contre.
La résistance de limitation est d'origine montée sur le panel.
Le fonctionnement est très satisfaisant mais...
... mais ce «panel» d'environ 35 x 39 mm n'est pas facile à loger dans le décor.
Il doit éclairer une bonne partie de l'arrière plan. Il doit donc être assez reculé, sans être directement visible par le spectateur.
D'autre part je voulais ajouter une composante bleue à la lumière des éclairs.
Au final j'ai opté pour une solution bien plus compacte : 2 LED de 3 watts.
Une blanche et une bleue.
Elle ne sont pas nécessairement installées côte à côte.
La LED blanche consomme environ 1 A pour 3 watts.
Elle sera alimentée à travers une résistance de 2 à 3,3 ohms.
En régime continu cette résistance R8 de 2 ohms dissiperait 2 watts.
Compte-tenu que les éclairs n'allument la LED que par salves courtes, très espacées, et à un niveau moyen qui ne dépasse pas 50% du maximum, on peut en fait se contenter d'un modèle dissipant 1 watt (ou même 1/2 watt) :
De même, la LED n'a pas besoin d'être montée sur un refroidisseur, pour exactement les mêmes raisons.
La LED bleue, si on l'utilise, sera alimentée à travers une résistance 1/2 watt d'une valeur de 10 à 56 ohms (ou plus) suivant l'effet désiré.
.
As-tu réfléchi à la possibilité de rendre relativement indépendants les éclairs blancs et les éclairs bleus ?
Ah ! Toi et ta relativité !
Jamais content...
Bon. OK... J'y réfléchirai... plus tard...
Concernant la platine de prototypage
J'ai utilisé une platine comme celle représentée ci-contre.
À l'une des extrémités elle comporte des emplacements pour connecter les alimentations.
Blocs de connexion
Pour les sorties vers les LED de puissance et le HP, j'ai utilisé des blocs à vis au pas de 5,08 mm.
PROTOTYPE sur BREADBOARD
L'implantation ci-dessous correspond au montage avec 2 étages de sortie à MOSFET – comme le suggère Albert – et dont le schéma et les modifications du programme sont donnés en additif à la fin de cet article.
Personnellement j'ai utilisé 2 platines de prototypage comme dans les animations précédentes, ce qui explique l'implantation sur 2 breadboards de 420 points, dessinée dans Tinkercad.
Désolé : Tinkercad ne propose pas le composant «ARDUINO Nano», ni le module DFPlayer.
(Clic sur les images pour les agrandir).
Remarques :
-
les deux alimentations de labo figurent les deux blocs d'alimentations 5 V DC.
-
les LED de puissance ne sont pas représentées. Seuls leurs connecteurs sont figurés sur le braedboard.
Pour monter les blocs de connexion à vis il est préférable d'inverser la position du connecteur et du MOSFET, de façon à donner accès aux vis de serrage. -
en JI-J2 et J7-J8 j'ai monté deux LED auxiliaires. Elles sont destinées à vérifier le fonctionnement du montage sans que les LED de puissance soient raccordées.
-
les MOSFET sont montés sans radiateur. Le modèle IRF540 est capable de délivrer 3 à 5 A sans nécessiter de radiateur ;
-
le connecteur du VS1838 est taillé dans une barrette wrapping au pas de 2,54 mm ;
-
(image de droite) les condensateurs C1 = 100nF et C2 = 10µF sont représentés par 2 petits traits blancs.
Attention à la polarité du condensateur de 10µF. -
les résistances en D2-F2, D4-F4, D8-F8 et D10-F10 seront réellement montées plus courtes en E2-F2, E4-F4, E-F8 et E10-F10 pour laisser la place de souder les petits ponts de couleur verte.
Attention
Image de droite : entourée en rouge, l'extrémité de la résistance G?-G4 est en l'air. (Tinkercad ne permet qu'un seul empattement pour l'implantation des résistances).
Cette résistance sera en réalité montée à l'emplacement G1-G4.
Encore une précaution
Sur les dessins d'implantation, on voit que le connecteur de téléversement de l'ARDUINO Nano est tourné vers la droite, et que la carte «T» sur le DFPlayer est tourné vers la gauche.
Il faut veiller à éloigner suffisamment les deux modules pour permettre d'insérer le cordon de téléversement sans être gêné par le DFPlayer et sa carte mémoire.
LE CODE C++
Au lieu d'une seule séquence sonore, il y en a 15.
Pour chaque coup de tonnerre le programme choisit aléatoirement une séquence sonore de coup de tonnerre et détermine aléatoirement un facteur de proximité.
En fonction de cette valeur de la proximité, il calcule :
-
le volume sonore ;
-
le retard entre la salve d'éclairs et le son ;
-
l'intensité moyenne des éclairs d'une salve ;
Le son n° 015 est un peu plus long. Il «joue» le bruit de la pluie.
Il est utilisé soit directement (on n'entend pas l'orage, mais seulement la pluie qui tombe), soit à la fin de l'orage : une sorte de retour au calme après l'orage.
L'application utilise les codes 10 à 14 pour démarrer.
Elle utilise les codes 19 et 1 + POWER pour stopper.
#include et déclarations de variables
#include <IRremote.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
int IRpin = 4 ; // entrée du capteur IR
IRrecv irrecv(IRpin);
decode_results results;
// Seules les touches utilisées pour cette application sont «libérées» :
const int Touche_9 = 272 ;
//const int Touche_8 = 3600 ;
//const int Touche_7 = 1552 ;
//const int Touche_6 = 2576 ;
//const int Touche_5 = 528 ;
const int Touche_4 = 3088 ;
const int Touche_3 = 1040 ;
const int Touche_2 = 2064 ;
const int Touche_1 = 16 ;
const int Touche_0 = 2320 ;
//const int Touche_Up = 1904 ;
//const int Touche_Down = 3952 ;
//const int Touche_Left = 2800 ;
//const int Touche_Right = 752 ;
//const int Touche_VolUp = 1168 ;
//const int Touche_VolDown = 3216 ;
//const int Touche_CH_Up = 144 ;
//const int Touche_CH_Down = 2192 ;
const int Touche_POWER = 2704 ;
//const int Touche_Menu = 112 ;
const int Numero_du_son_de_la_pluie = 15 ;
//--- Variables globales ---
int Numero_du_son;
int Volume;
int Retard;
int Facteur_d_intensite;
int Proximite;
int Nombre_de_sons_enregistres ;
int Duree_de_l_orage ; // Détermine le nombre de salves
// (et coups de tonnerre) de l'orage complet.
const int Liaison_BUSY = 10 ; // Pour connaître la fin de diffusion des sons
const int MOSFET = 9 ;
SoftwareSerial mySoftwareSerial(2,3);
DFRobotDFPlayerMini myDFPlayer;
void loop()
void loop()
{
irrecv.resume() ;
Attente_du_code_de_demarrage() ;
for (int count2 = 1; count2 <= Duree_de_l_orage; count2++)
{
Retard_du_son_Volume_et_Facteur_d_intensite();
Salve();
Coup_de_tonnerre();
if (Attente_fin_du_son() == 99) {break ; } // pour écourter la durée de l'orage.
// Le code d'arrêt doit être saisi
// pendant la diffusion du son.
}
Fin_de_l_orage(); // Diffusion du son n°15 (pluie).
}
La variable Duree_de_l_orage contient le nombre de coups de tonnerre de l'orage complet.
La fonction void Attente_du_code_de_demarrage() appelle la fonction void Code_a_2_chiffres().
void Code_a_2_chiffres() intercepte les 2 codes infrarouges et détermine la valeur de Duree_de_l_orage :
-
si le code est 10 ⇒ Duree_de_l_orage = 1 (1 seul coup de tonnerre) ;
-
...
-
si le code est 13⇒ Duree_de_l_orage = 16 (16 coup de tonnerre) ;
-
si le code est 14 ⇒ bruit de la pluie uniquement et retour au début du programme.
void setup()
Rien de très particulier.
void setup()
{
irrecv.enableIRIn();
Serial.begin(9600);
pinMode(MOSFET, OUTPUT); // Sortie vers le MOSFET
mySoftwareSerial.begin(9600);
pinMode(Liaison_BUSY, INPUT); // Indispensable pour tester la fin
// de la diffusion du son en cours.
myDFPlayer.begin(mySoftwareSerial);
myDFPlayer.volume(20);
Nombre_de_sons_enregistres = myDFPlayer.readFileCounts();
// ----EQUALIZER : PARAMETRAGES POSSIBLES
// myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
}
Fonction personnelle
«int Interception_du_premier_code_IR_SONY()»
Cette fonction attend indéfiniment la réception d'un premier code infrarouge.
Cette fonction est appelée par la fonction void Code_a_2_chiffres().
Elle prend la valeur Code_touche_obtenu du premier code IR reçu qu'elle transmet à la fonction appelante.
int Interception_du_premier_code_IR_SONY() // Appelée par la fonction
// «Code_a_2_chiffres».
// Cette fonction attend indéfiniment
// la saisie du premier code.
{
int Code_touche_obtenu = 999 ; // On impose a priori un code incorrect
// hors du champs des codes possibles.
// Le code «999» n'existe pas dans la liste
// de codes de la télécommande SONY TV.
irrecv.resume() ;
while (!(irrecv.decode(&results)))
// Attend indéfiniment la réception du 1er code.
{
// boucle d'attente
delay(100) ;
}
Code_touche_obtenu = results.value ;
//Serial.print(" Code touche obtenu pour le 1er chiffre = ") ;
//Serial.println(Code_touche_obtenu) ;
delay(600) ; // Delai avant la saisie du code suivant
irrecv.resume() ;
return Code_touche_obtenu ;
}
Fonction personnelle
«int Interception_du_premier_code_IR_SONY_avec_delay()»
Cette fonction n'attend pas indéfiniment le premier code IR.
La variable locale int Limite_du_delai_d_attente limite cette attente à 2 secondes (modifiable).
Cette fonction est appelée par la fonction int Code_d_arret_a_2_chiffres().
Elle prend la valeur Code_touche_obtenu du premier code IR reçu qu'elle transmet à la fonction appelante.
.
// Appelée par la fonction «Code_a_2_chiffres».
// Pour le 2e code, le délai de saisie en secondes est limité par la valeur de
// «Limite_du_delai_d_attente».
// Passé ce délai, on revient au début de void loop pour attendre un nouveau
// premier code.
int Interception_du_premier_code_IR_SONY_avec_delay()
{
int Code_touche_obtenu = 999 ;
int Limite_du_delai_d_attente = 2 ;
irrecv.resume() ;
int Temps_IN = millis() / 1000 ;
int Temps_OUT ;
while (!(irrecv.decode(&results))) // Attend la réception du
// 2e code pendant «Limite_du_delai_d_attente», en secondes.
{
// boucle d'attente
delay(100) ;
int Temps_OUT = millis() / 1000 ;
if ((Temps_OUT - Temps_IN) > Limite_du_delai_d_attente)
{
//Serial.println(" Dépassement du temps 1er chiffre") ;
return 999 ;
}
}
Code_touche_obtenu = results.value ;
//Serial.print(" Code touche obtenu pour le 1er chiffre = ") ;
//Serial.println(Code_touche_obtenu) ;
delay(600) ; // Delai avant la saisie du code suivant
irrecv.resume() ;
return Code_touche_obtenu ;
}
Fonction personnelle
«int Interception_du_deuxieme_code_IR_SONY()»
Cette fonction n'attend pas indéfiniment le deuxième code IR.
La variable locale int Limite_du_delai_d_attente limite cette attente à 2 secondes (modifiable).
Cette fonction est appelée par la fonction int Code_a_2_chiffres().
Elle prend la valeur Code_touche_obtenu du premier code IR reçu qu'elle transmet à la fonction appelante.
// Appelée par la fonction «Code_a_2_chiffres».
// Pour le 2e code, le délai de saisie en secondes est limité par la valeur de
// «Limite_du_delai_d_attente».
// Passé ce délai, on revient au début de void loop pour attendre un nouveau
// premier code.
int Interception_du_deuxieme_code_IR_SONY()
{
int Code_touche_obtenu = 999 ;
int Limite_du_delai_d_attente = 2 ;
irrecv.resume() ;
int Temps_IN = millis() / 1000 ;
while (!(irrecv.decode(&results))) // Attend la réception
// du 2e code pendant «Limite_du_delai_d_attente», en secondes.
{
// boucle d'attente à durée limitée.
delay(100) ;
int Temps_OUT = millis() / 1000 ;
if ((Temps_OUT - Temps_IN) > Limite_du_delai_d_attente)
{
//Serial.println(" Dépassement du temps 2e chiffre") ;
return 999 ;
}
}
Code_touche_obtenu = results.value ;
//Serial.print(" Code touche obtenu pour le 2e chiffre = ") ;
//Serial.println(Code_touche_obtenu) ;
irrecv.resume() ;
delay(1000) ; // Delai avant la saisie du code suivant
results.value = 0 ;
irrecv.resume() ;
return Code_touche_obtenu ;
}
Fonction personnelle
«int Code_a_2_chiffres()»
Cette fonction est appelée par la fonction Attente_du_code_de_demarrage() ;
Elle traite les codes de démarrage :
-
si le code à 2 chiffres reçu est 10, la variable Duree_de_l_orage vaut 1 ⇒ un seul coup de tonnerre ;
-
si le code à 2 chiffres reçu est 11, la variable Duree_de_l_orage vaut 4 ⇒ 4 coups de tonnerre ;
-
si le code à 2 chiffres reçu est 12, la variable Duree_de_l_orage vaut 8 ⇒ 8 coups de tonnerre ;
-
si le code à 2 chiffres reçu est 13, la variable Duree_de_l_orage vaut 16 ⇒ 16 coups de tonnerre ;
-
si un de ces 4 codes est reçu, cette fonction prend la valeur true qu'elle transmet à la fonction appelante ;
-
si le code à 2 chiffres reçu est 14, la fonction appelle la fonction Fin_de_l_orage ⇒ l'orage sera ainsi écourté ;
À la fin de l'orage (son de la pluie), l'instruction loop() ; force le redémarrage du programme.
int Code_a_2_chiffres()
{
bool Code = false ;
int Premier_chiffre = Interception_du_premier_code_IR_SONY() ;
int Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;
if (Premier_chiffre == Touche_1)
{
if (Deuxieme_chiffre == Touche_0) {Code = true ; Duree_de_l_orage = 1 ; }
// 1 salve ;
if (Deuxieme_chiffre == Touche_1) {Code = true ; Duree_de_l_orage = 4 ; }
// 4 salves ;
if (Deuxieme_chiffre == Touche_2) {Code = true ; Duree_de_l_orage = 8 ; }
// ...
if (Deuxieme_chiffre == Touche_3) {Code = true ; Duree_de_l_orage = 16 ; }
if (Deuxieme_chiffre == Touche_4) {Code = true ; Fin_de_l_orage() ; loop();}
}
return Code ;
}
Note :
Les codes 15 à 19 sont éventuellement disponibles pour paramétrer le démarrage avec d'autres avleurs de durée de l'orage, ou même pour diffuser d'autres sons.
Fonction personnelle
«int Code_d_arret_a_2_chiffres()»
Cette fonction est appelée par la fonction int Attente_fin_du_son().
Elle permet d'interrompre prématurément le déroulement de l'orage.
Pour que le code d'arrêt puisse être pris en compte, il doit donc être saisi pendant le déroulement d'un son.
En effet, lorsqu'un son se déroule, le programme ne fait qu'attendre que le DFPlayer indique que la diffusion du son est terminée (liaison BUSY).
Or le DFPlayer ne mobilise pas l'ARDUINO pendant la diffusion du son ⇒ pendant cette phase, l'ARDUINO a tout le temps pour intercepter les codes IR d'arrêt.
Les 2 codes d'arrêt valides sont :
-
le code 19 ;
-
le code 1 + POWER.
(Ce double code d'arrêt est une fantaisie dont on peut se passer).
.
int Code_d_arret_a_2_chiffres()
{
bool Code = false ;
int Premier_chiffre = Interception_du_premier_code_IR_SONY_avec_delay() ;
int Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;
// Traitement du code d'arrêt
if (Premier_chiffre == Touche_1)
{
//if (Deuxieme_chiffre == Touche_0) {Code = true ; }
//if (Deuxieme_chiffre == Touche_1) {Code = true ; }
//if (Deuxieme_chiffre == Touche_2) {Code = true ; }
//if (Deuxieme_chiffre == Touche_3) {Code = true ; }
//if (Deuxieme_chiffre == Touche_4) {Code = true ; }
//if (Deuxieme_chiffre == Touche_5) {Code = true ; }
//if (Deuxieme_chiffre == Touche_6) {Code = true ; }
//if (Deuxieme_chiffre == Touche_7) {Code = true ; }
//if (Deuxieme_chiffre == Touche_8) {Code = true ; }
if (Deuxieme_chiffre == Touche_9) {Code = true ; }
if (Deuxieme_chiffre == Touche_POWER) {Code = true ; }
}
return Code ;
}
Fonction personnelle
«int mathRandomInt(int min, int max)»
On sait que la fonction random() – ou rand() – ne génère pas une vraie série aléatoire, mais toujours la même suite de nombre à chaque redémarrage du programme.
Très vite on se rend compte que chaque orage qu'on déclenche déroule la même séquence de sons et d'éclairs... et la surprise n'existe plus.
Pour améliorer le côté aléatoire, on ajoute l'instruction randomSeed(...) qui choisit la «graine», c'est-à-dire la valeur sur laquelle s'appuie la fonction rand() pour débuter sa série.
Pour que cette «graine» soit vraiment différente, quoi de plus simple que de lui affecter la valeur millis() du temps courant – compté en millisecondes à partir de l'allumage de l'ARDUINO – au moment aléatoire où on appelle la fonction int mathRandomInt(int min, int max) ?
Cette une fonction avec «passage d'arguments» : on l'appelle en lui fournissant les 2 valeurs extrêmes entre lesquelles on souhaite que se situe la valeur aléatoire.
La fonction rand(x, y) renvoie un nombre compris entre x et (y-1).
La fonction int mathRandomInt(int min, int max) renvoie un nombre compris entre min et max inclu.
Sympa !
.
int mathRandomInt(int min, int max)
{
randomSeed(millis()) ; // Ajouté le 23/01/2022.
// Pour se rapprocher d'un véritable tirage aléatoire.
if (min > max)
{
int temp = min; // Swap min and max to ensure min is smaller.
min = max;
max = temp;
}
return min + (rand() % (max - min + 1));
}
Fonction personnelle
«void Salve() »
Cette fonction est appelée par void loop().
La sortie 9, qui commande la LED de puissance par l'intermédiaire du MOSFET, est pilotée en analogique.
C'est ce qui permet de moduler le niveau lumineux des éclairs.
.
void Salve()
{
int repeat = mathRandomInt(2, 4) * 5; // Nombre d'éclairs par salve.
for (int count = 0; count < repeat ; count++)
{
analogWrite(9, (mathRandomInt(1, 4) * (Facteur_d_intensite * 8)));
// Intensité «haute» de l'éclair.
delay((mathRandomInt(1, 4) * 25));
// Durée de l'intensité «haute».
analogWrite(9, (mathRandomInt(0, 4) * (Facteur_d_intensite * 5)));
// Intensité «basse» de l'éclair.
delay((mathRandomInt(1, 4) * 15));
// Durée de l'intensité «basse».
}
analogWrite(9, 0);
}
À la fin d'une salve, on force la sortie 9 au niveau 0 pour éteindre la LED à coup sûr, ce que ne fait pas la fonction analogWrite(9, mathRandom(0, 4)... ou très exceptionnellement.
Fonction personnelle
«void Coup_de_tonnerre() »
Cette fonction est appelée par void loop().
Elle choisit au hasard un son parmi les 15 sons enregistrés sur la carte «T».
En fait, Nombre_de_sons_enregistres-1 évite de choisir le son n°15, qui est le son de la pluie seule.
Le son débute avec un retard et une intensité déterminés dans la fonction :
void Retard_du_son_Volume_et_Facteur_d_intensite()
.
void Coup_de_tonnerre()
{
Numero_du_son = mathRandomInt(1, Nombre_de_sons_enregistres-1);
// «... -1» pour exclure le son final de la pluie
delay(Retard);
myDFPlayer.volume(Volume);
myDFPlayer.play(Numero_du_son);
}
Fonction personnelle
«int Attente_fin_du_son()»
... et interception d'un éventuel code d'arrêt.
Cette fonction est appelée par la fonction Coup_de_tonnerre() dans void loop().
Tant que le son est en cours de diffusion, la broche BUSY du DFPlayer reste à l'état LOW.
Pendant cette phase, le programme est disponible pour tester l'arrivée d'un code IR en appelant la fonction
Code_d_arret_a_2_chiffres().
À la fin, la variable Duree_du_son – comme son nom l'indique – permet de connaître la durée du son qui vient d'être diffusé.
J'ai utilisé cette variable pendant la phase de mise au point du programme.
Les instructions qui permettent l'impression des différents paramètres d'un coup de tonnerre sont passée en commentaires pour ne pas surcharger inutilement le microcontrôleur.
.
int Attente_fin_du_son()// ... et interception du code d'arrêt.
{
delay(1000); // Pour être sûr que la pin 10 (BUSY) est bien passée à «LOW».
long Initialisation_timer = millis();
long Duree_du_son = 0 ;
while (digitalRead(Liaison_BUSY) == LOW)
{
if (Code_d_arret_a_2_chiffres() == true) // Permet de saisir le code «19»
// pour écourter la durée de l'orage.
{
irrecv.resume();
delay(100) ;
return 99 ;
}
}
Duree_du_son = (millis() - Initialisation_timer) + 1000;
/*
Serial.print("Fin du son n° ") ;
Serial.println(Numero_du_son) ;
Serial.print("Durée du son = ") ;
Serial.print(Duree_du_son) ;
Serial.println(" millisecondes");
Serial.print("- Current elapsed time (ms) = ");
Serial.println(millis());
Serial.println("");
*/
}
Fonction personnelle
«void Retard_du_son_Volume_et_Facteur_d_intensite()»
Cette fonction est appelée par void loop().
C'est un peu le cœur du programme : Pour chaque coup de tonnerre, un facteur de proximité est déterminé aléatoirement.
En fonction de ce facteur, le programme détermine :
-
le volume sonore du coup tonnerre ;
-
le retard entre la salve d'éclairs et le son ;
-
le facteur d'intensité moyenne des éclairs.
Note :
Les paramètres d'impression sont mis en commentaires pour alléger le code téléversé.
.
void Retard_du_son_Volume_et_Facteur_d_intensite()
{
Proximite = mathRandomInt(1, 8) * 5; // Aléatoire de 8 à 40 :
// Proximité = 5 ⇒ lointain ;
// Proximité = 40 ⇒ proche.
Volume = Proximite;
Retard = (40 - Proximite) * 100; // Ce coefficient varie de «0» à 3200 ms.
Facteur_d_intensite = Proximite / 5; // Ce coefficient varie de 1 à 8.
/*
Serial.print("- Volume = ");
Serial.println(Volume);
Serial.print("- Retard = ");
Serial.print(Retard);
Serial.println(" millisecondes");
Serial.print("- Facteur d\'intensité = ");
Serial.println(Facteur_d_intensite);
*/
}
Fonction personnelle
«void Attente_du_code_de_demarrage()»
Cette fonction est appelée par void loop().
Elle appelle la fonction Code_a_2_chiffres().
.
void Attente_du_code_de_demarrage()
{
//Serial.println("Attente code") ;
while (!(Code_a_2_chiffres() == true))
{
//Serial.println("code non reçu ou incorrect. Nouvel essai...") ;
irrecv.resume();
delay(50) ;
}
}
Fonction personnelle
«void Fin_de_l_orage() »
Cette fonction est appelée par la fonction int Code_a_2_chiffres() et par void loop().
Dans void loop(), elle diffuse le son de la pluie à la fin du déroulement de l'orage.
Dans int Code_a_2_chiffres(), elle diffuse uniquement le son de la pluie, à la place de l'orage.
.
void Fin_de_l_orage()
{
myDFPlayer.volume(20);
myDFPlayer.play(Numero_du_son_de_la_pluie);
Attente_fin_du_son() ;
}
PARAMÈTRAGES
Dans void setup()
myDFPlayer.EQ(DFPLAYER_EQ_JAZZ); ⇒ six paramètres disponibles pour ajuster la tonalité du son en fonction du HP utilisé, mais aussi de la qualité des sons enregistrés.
Dans void Fin_de_l_orage()
myDFPlayer.volume(20); ⇒ pour régler le volume du son de la pluie.
Dans void Retard_du_son_Volume_et_Facteur_d_intensite()
Les 4 paramètres sont réglables, mais attention :
-
dans Proximite = mathRandomInt(1, 8) * 5;
-
et dans Facteur_d_intensite = Proximite / 5;
... les deux valeurs en gras doivent être identiques.
Dans void Salve()
Tous les paramètres sont réglables... mais allez-y avec prudence.
Dans int Code_a_2_chiffres()
Duree_de_l_orage = 4 ; } // 4 salves ; ⇒ les 4 occurrences pour 1 à 16 salves peuvent être ajustées à convenance.
Les codes 15 à 19 sont disponibles pour d'autres modes de démarrage du programme : plus de durées d'orages disponibles, autres son de pluie, etc.
Dans les déclarations
const int Numero_du_son_de_la_pluie = 15 ;
Si d'autres séquences sonores sont prévues (comme par exemple celle son de la pluie en n°15), elles seront déclarés à la suite et paramétrées dans la fonction int Code_a_2_chiffres().
.
That's all Folks !
SCHÉMA POUR 2 LED, BLANCHE ET BLEUE,
INDÉPENDANTES
(ajouté le 09/02/2022)
Un 2e étage de puissance est connecté sur la sortie 10 de l'ARDUINO, pour piloter la LED bleue.
Fonction personnelle modifiée
«void Salve()»
Cette fonction est appelée par void loop().
.
void Salve()
{
int repeat = mathRandomInt(2, 4) * 5; // Nombre d'éclairs par salve.
for (int count = 0; count < repeat ; count++)
{
analogWrite(9, (mathRandomInt(1, 4) * (Facteur_d_intensite * 8)));
// Intensité «haute» de l'éclair blanc.
delay((mathRandomInt(1, 4) * 12));
analogWrite(10, (mathRandomInt(1, 4) * (Facteur_d_intensite * 4)));
// Intensité «haute» de l'éclair bleu.
delay((mathRandomInt(1, 4) * 12)); // Durée de l'intensité «haute».
analogWrite(9, (mathRandomInt(0, 4) * (Facteur_d_intensite * 5)));
// Intensité «basse» de l'éclair blanc.
delay((mathRandomInt(1, 4) * 7));
analogWrite(10, (mathRandomInt(0, 4) * (Facteur_d_intensite * 2)));
// Intensité «basse» de l'éclair bleu.
delay((mathRandomInt(1, 4) * 7)); // Durée de l'intensité «basse».
}
analogWrite(9, 0);
}
Réalisations avec DFPlayer Mini
bottom of page