Smart Cube : La télécommande gestuelle nouvelle génération pour la maison connectée
Composants et fournitures
| Composant | Quantité |
|---|---|
| Arduino 101 | 1 |
| LED (générique) - 1 bleue, 1 jaune, 1 verte, 2 rouges | 5 |
| Résistance 221 Ω | 5 |
| Plaque d'essai (breadboard) générique (non obligatoire) | 1 |
| Seeed Base Shield V2 | 1 |
| Seeed Grove LCD RGB Rétroéclairage | 1 |
| Seeed Grove Capteur de son | 1 |
| Seeed Grove Buzzer | 1 |
| Seeed Grove Capteur de température | 1 |
| Clavier matriciel (Keypad) | 1 |
| Fils de liaison (jumper wires) génériques | 1 |
| Pile 9V (générique) | 1 |
| Connecteur pile 9V | 1 |
| Panneau de fibres à densité moyenne (MDF) 20x30 cm, 3 mm | 1 |
Outils et machines nécessaires
- Découpeuse laser (générique)
- Fer à souder (générique)
Applications et services en ligne
- Arduino IDE
- Nordic Semiconductor nRF Connect SDK (non obligatoire)
À propos du projet
Qu'est-ce que SMART CUBE ?
Smart Cube est un contrôleur pour vos appareils domotiques.
De nos jours, gérer de manière plus intelligente tous les appareils de notre foyer devient une exigence. Nous avons besoin de quelque chose de simple et intuitif à utiliser. Smart Cube pourrait être une solution : c'est un appareil portable qui contient une carte Arduino 101 et des capteurs qui communiquent avec les appareils et actionneurs de votre maison connectée.
L'innovation de cette télécommande est liée à l'innovation de la carte Arduino 101. Elle utilise le Bluetooth (BLE) pour contrôler les lumières, la température et votre TV, et vous pouvez aussi la synchroniser avec votre smartphone. Mais la véritable innovation réside dans la façon dont vous interagissez avec Smart Cube par vos gestes grâce au gyroscope et à l'accéléromètre. Le cube a 6 faces et chacune contrôle une fonction particulière. La fonction que vous voulez utiliser est détectée grâce au gyroscope qui reconnaît la face supérieure. Par exemple, vous pouvez allumer les lumières de la pièce où vous vous trouvez simplement en positionnant le cube avec la « face lumière » en position haute. Si vous voulez éteindre la lumière, il suffit de secouer le cube.
Si une face est HAUTE et ne bouge pas pendant plus de 2 secondes, la fonction correspondante est activée. Ce délai est prévu pour que vous ayez le temps de tourner et manipuler le cube pour trouver la face dont vous avez besoin sans activer accidentellement d'autres fonctions. Lorsque vous secouez le cube pendant plus de 2 secondes, la dernière fonction activée est fermée.
Ce projet vise à vous aider à construire un contrôleur intelligent. Cet appareil a besoin d'un récepteur (centrale domotique sur l'image) qui interprète les données et gère les fonctions de votre maison connectée. La principale sortie du cube est un signal BLE qui peut être utilisé de multiples façons : par exemple, vous pouvez connecter le cube avec une application smartphone (ou créer la vôtre), ou construire une station avec un autre Arduino qui collecte les données BLE et contrôle directement les appareils de votre maison. Comme les cas d'usage sont variés, cette partie dépend de vos besoins. Dans ce guide, nous verrons comment construire un Smart Cube et comment le personnaliser.

Fonctions :
La structure du code est facile à personnaliser (nous l'analyserons plus tard) pour que vous puissiez décider quelles fonctions contrôler. Voici celles que j'ai choisies :

LUMIÈRES : Cette face en position HAUTE allume les lumières de la pièce où vous êtes. Si vous secouez le cube, les lumières s'éteignent et une LED jaune sur cette face s'allume pour retrouver le cube dans l'obscurité. La communication avec vos lampes se fait via le BLE de la carte 101.
TEMPÉRATURE : Cette face HAUTE active (via BLE) la climatisation s'il fait chaud ou le chauffage s'il fait froid. Elle détecte la température à l'aide d'un capteur thermique et allume une LED bleue si la climatisation est active (flocon de neige) ou une rouge si le chauffage est activé (soleil).
MINUTERIE : Cette face HAUTE démarre un minuteur visible sur l'écran LCD. Un buzzer fonctionne comme alarme quand le compte à rebours est fini. Si vous secouez, vous arrêtez le minuteur et voyez le temps restant. Quand le compte à rebours se termine, la couleur du LCD passe du bleu au rouge et le buzzer émet trois bips.
TV : Cette face HAUTE allume la TV. Le cube devient une télécommande pour votre TV. Un panneau de boutons avec chiffres est activé uniquement si cette face est HAUTE pour éviter les touches accidentelles. Le chiffre appuyé est envoyé via BLE à la centrale qui est connectée à votre TV. Secouer le cube éteint la TV.
SON : Cette face HAUTE active une LED dont la luminosité est basée sur le niveau sonore de la pièce. Le bruit est détecté grâce au capteur de son. Si vous secouez le cube, vous fermez cette fonction. (Si vous le souhaitez, vous pouvez activer votre fonction personnelle en claquant des mains).
Face OFF : Si vous ne secouez pas le cube, cette face est comme une position neutre où rien ne change. Si vous voulez tout éteindre, positionnez le cube avec la face OFF en HAUT et secouez-le. Ce geste est comme le bouton Home de votre smartphone pour sortir rapidement. Une LED rouge permet de retrouver le cube dans l'obscurité.
Différences par rapport au concept initial :
Le plan initial prévoyait d'utiliser aussi la communication IR pour connecter directement votre TV au cube. Comme l'Arduino 101 ne supporte pas (pour l'instant) la bibliothèque gérant les signaux IR, j'ai décidé d'envoyer l'information via BLE vers une station capable de gérer cette bibliothèque (comme un Arduino UNO). À cause de ce problème, j'ai supprimé la fonction radio (très similaire à la face TV), la remplaçant par une face capteur de son. Cette face pourrait servir à reconnaître un bruit fort (comme des applaudissements) pour activer quelque chose. Le plus grand changement concerne le matériau du cube. Au départ, je pensais l'imprimer en 3D mais j'ai opté pour la découpe laser. Ainsi, il est plus facile de remplacer une face si vous voulez changer une fonction. Par exemple, vous pouvez retirer la face minuteur et la remplacer par une face qui remplit automatiquement la gamelle de votre chat. Étant modulaire, vous n'avez pas besoin de reconstruire toute la structure !

Construisons-le :
Suivez ces instructions pour construire votre propre Smart Cube. Nous commencerons par le matériel, en assemblant d'abord les composants électroniques, puis le corps du cube découpé au laser en MDF. Ensuite, j'expliquerai comment le code fonctionne et comment le personnaliser. Après avoir téléversé le code sur votre Arduino 101, vous pourrez télécharger l'application pour voir la sortie BLE du cube ou le connecter directement à votre maison connectée !

Matériel - Électronique :
Partons de votre Arduino 101. Voici le schéma Fritzing à suivre :

Montez le Grove Base Shield sur votre carte et commencez les connexions.


Keypad : connectez les fils dans l'ordre aux broches : 10, 8, 7, 6, 5, 4, 2.



Connexions LED :
Préparez d'abord les LED :
- Connectez la patte longue (anode) à une résistance 220 Ω puis à un fil rouge (câble vers la broche)
- Connectez la patte courte (cathode) à un fil blanc (ira au GND)
- Soudez et isolez avec du ruban électrique
- Regroupez tous les fils blancs en un seul (vers GND) et soudez-les ensemble
Connectez maintenant les fils rouges à votre Arduino : LED VERTE broche 9, LED JAUNE broche 11, LED ROUGE broche 12, LED BLEUE broche 13, dernière ROUGE broche A2.




Capteurs Grove :
Connectez les capteurs Grove au shield (voir schéma en pièce jointe). Buzzer sur D3, LCD RGB sur I2C, Capteur température sur A0, Capteur son sur A1.

Tous les composants électriques sont maintenant connectés. Passons au boîtier.
Matériel - Boîtier
Vous pouvez télécharger le plan du cube pour la découpe laser. Les lignes rouges sont les symboles des faces, gravez-les simplement. Les lignes noires doivent être découpées. La dimension interne du cube est de 9 cm. Le plan est prévu pour du matériau 3 mm, si vous utilisez une épaisseur différente, vous devrez le modifier (utilisez ce site : makercase.com).
Le matériau choisi est du MDF (Medium Density Fiber) mais vous pouvez utiliser ce que vous voulez.
Voici quelques photos de la découpe laser :




Maintenant, il faut l'assembler.
J'ai collé des morceaux de carton pour créer de l'épaisseur pour les LED. Ainsi, elles seront alignées avec la surface.



Montons maintenant le keypad. Insérez-le dans le trou, retirez le film adhésif, puis rebranchez les broches.



Maintenant le LCD RGB. Il s'insère parfaitement dans le trou.


Préparons le connecteur de pile :
J'ai découpé une vieille fiche de transformateur et l'ai connectée à un connecteur de pile. Cela fait gagner de la place à l'intérieur.



À ce stade, vous devriez avoir ceci :

Il ne reste plus qu'à connecter la pile, téléverser le code et fermer le cube !
ASTUCE : fixez la carte et la pile au boîtier pour qu'ils restent stables quand vous secouez le cube.

Code
Le code se trouve dans les pièces jointes. Téléversez-le sur votre carte avec l'Arduino IDE (pensez à mettre à jour votre logiciel pour la compatibilité Arduino 101).
J'ai commenté presque chaque ligne pour le rendre le plus compréhensible possible. Ne soyez pas effrayé par les 500+ lignes, la structure n'est pas si compliquée.
Au début se trouvent les bibliothèques et la déclaration de toutes les variables.
Dans cette partie, il y a aussi la définition des services et caractéristiques BLE. J'ai utilisé le service Automation IO. J'ai utilisé la caractéristique Digital pour les lumières et la température (2 bits, donc 4 cas possibles) et l'Analog pour la TV (pour envoyer tous les codes du keypad).
Puis le setup. Cette partie s'exécute une seule fois au début. On y initialise les composants en entrées/sorties, le BLE et le gyroscope de la carte 101.
La partie principale est la loop. Elle est divisée en quatre parties :
- 1 La première partie vient du tutoriel Arduino : (https://www.arduino.cc/en/Tutorial/Genuino101CurieIMUAccelerometerOrientation) cette partie est exécutée en permanence et renvoie l'orientation de la carte.
- 2 La deuxième partie active une face seulement si elle est en position haute pendant plus de deux secondes. On utilise la fonction millis pour compter le temps. Quand la position change, on mémorise la valeur de millis et si l'orientation reste la même après un intervalle (2 sec), on entre dans une zone if où la face sélectionnée devient vraie (pour la 4e partie).
- 3 La troisième partie s'active seulement si le cube est secoué avec une certaine intensité et pendant plus de 2 secondes. La dernière face activée est fermée et la face est mise à false. Si la face est false, elle ne peut pas entrer dans la 4e partie.
- 4 La quatrième partie est réservée aux faces vraies. C'est là qu'est le cœur des fonctions du Smart Cube. Dans cette partie, seules les faces vraies sont exécutées en boucle.
Vous pouvez modifier les fonctions des faces avec quelques modifications du code. La structure principale doit rester telle que décrite. Vous pouvez changer la partie à l'intérieur des conditions if de chaque face.
if (face2 == true) { // TEMPERATURE face
//START CHANGING HERE
digitalWrite (LEDOFF, LOW); // si cette face est vraie, la LED OFF est LOW
if (central.connected() == true) { // si le cube est connecté en BLE
// lecture valeur température
int val = analogRead(pinTemp); // valeur analogique
resistance=(float)(1023-val)*10000/val; // résistance
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcul température
// conditions d'activation
if (temperature > tooHot) { // activer clim
digitalWrite(LEDhot, LOW); // éteindre LED chauffage
digitalWrite(LEDcold, HIGH); // allumer LED clim
termoChar.setValue(1); // 1 = clim on - chauffage off
}
if (temperature < tooCold) { // activer chauffage
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = clim off - chauffage on
}
if (temperature > tooCold && temperature < tooHot) { // température idéale
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = clim off - chauffage off
}
}
//END HERE
}
Vous devez aussi coder la partie « false » quand le cube est secoué :
// TEMPERATURE désactivation
if (lastFUNCTION == 2) { // TEMPERATURE face
//START CHANGING HERE
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // éteindre LED température rouge
digitalWrite(LEDcold, LOW); // éteindre LED température bleue
termoChar.setValue(0); // signal BLE température: 0 = clim off - chauffage off
}
//END HERE
Serial.println("TEMPERATURE false - CLOSE");
face2 = false; // face TEMPERATURE devient false
}
N'oubliez pas de mettre la face à false quand vous la secouez.
Application :
Pour voir les sorties BLE du cube, vous pouvez télécharger cette application : nRF Connect
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=it
À l'ouverture, recherchez les appareils et connectez-vous à « smartcubesketch ». Vous verrez trois onglets « Automation IO », cliquez dessus et activez la collecte continue de données.
Il est important de connecter le cube car certaines fonctions (lumières, température, TV) ne s'exécutent que si le cube est connecté.
Fonctionnement : VIDÉO
Téléversez le code, insérez la pile, fermez la boîte et...
... vous avez maintenant un SMART CUBE !
J'ai fait une vidéo pour vous montrer toutes les fonctions du cube et comment l'utiliser.
Conclusions
Ce projet n'est que la première étape vers une maison connectée. Mon but était d'utiliser le potentiel de la carte Arduino 101 pour créer quelque chose de nouveau. Je pense que l'accéléromètre et le gyroscope offrent à la carte de nouvelles opportunités en termes de mobilité. Avec le BLE, en plus d'être portable, il est aussi facile à connecter.
C'est la première fois que je réalise concrètement l'un de mes projets (un prototype fonctionnel). Ce fut difficile et il y eut des obstacles, mais à la fin j'ai beaucoup appris et je suis satisfait du résultat. J'espère que tous ceux qui liront ce guide pourront apprendre de mon travail et adapter ce projet à leurs besoins. Excusez mon anglais approximatif, j'espère que les images vous aideront.
Dans le futur de ce projet, je compte créer la centrale qui fera le pont entre le Smart Cube et les actionneurs (lumières, température, TV...). Cette centrale recevra le signal BLE du cube et utilisera cette information pour faire des choses intelligentes chez vous.
Je suis très content d'avoir pu utiliser l'Arduino 101 et le Grove kit (le kit est très simple et rapide pour le prototypage).
J'espère que l'utilisation de la carte de cette façon pourra être une inspiration pour vos projets. Vous pouvez le personnaliser comme vous voulez : je suis curieux de voir quelles fonctions vous créerez et dans quels contextes différents vous l'utiliserez !
Ce n'est peut-être pas une révolution, mais c'est une nouvelle façon d'interagir avec votre maison.
J'espère que ce tutoriel vous a plu.
Maintenant, c'est à votre tour : mettez la main sur le cube et hackez-le !
Code
SMART CUBE - Code complet commenté (Arduino)
// Libraries
#include "CurieIMU.h" // Accéléromètre & Gyroscope
#include <CurieBLE.h> // Bluetooth Low Energy
#include <Wire.h>
#include "rgb_lcd.h" // LCD
#include <Keypad.h> // Keypad
rgb_lcd lcd; // Initialisation LCD
// Initialisation Bluetooth:
BLEPeripheral blePeripheral; // Périphérique BLE (la carte que vous programmez)
// Services BLE
BLEService lightsService("1815"); // Automation IO (1815) - infos lumières
BLEService termoService("1815"); // Automation IO - infos température
BLEService TVService("1815"); // Automation IO - infos TV
// Caractéristiques BLE
BLEUnsignedCharCharacteristic lightsChar("2A56", // Digital (2A56) - lumières
BLERead | BLENotify);
BLEUnsignedCharCharacteristic termoChar("2A56", // Digital - température
BLERead | BLENotify);
BLEUnsignedCharCharacteristic TVChar("2A58", // Analog (2A58) - TV
BLERead | BLENotify);
// Constantes et déclaration variables:
// Fonctions orientation face et shake:
int lastOrientation = -1; // orientation précédente (pour comparaison)
unsigned long previousMillis = 0; // dernier temps mis à jour
unsigned long interval = 2000; // temps à attendre en position haute avant activation face
unsigned long SHAKEpreviousMillis = 0; // dernier temps mis à jour
unsigned long SHAKEinterval = 2000; // temps à attendre pendant secousse pour désactivation face
boolean keep = false; // utilisé pour compter une seule fois le changement d'orientation
int lastFUNCTION = -1; // utilisé pour connaître l'orientation précédente
// Initialisation faces: au début toutes fausses
boolean face0 = false;
boolean face1 = false;
boolean face2 = false;
boolean face3 = false;
boolean face4 = false;
boolean face5 = false;
// Face LUMIÈRES
const int LEDlights = 11; // broche 11: LED jaune
// Face TEMPÉRATURE
const int pinTemp = A0; // broche A0: capteur température
const int LEDhot = 12; // broche 12: LED rouge
const int LEDcold = 13; // broche 13: LED bleue
float temperature; // mémorisation température
int B=3975; // valeur B du thermistor
float resistance; // mémorisation résistance
float tooHot = 26.0; // température activation clim [RÉGLABLE]
float tooCold = 23.0; // température activation chauffage [RÉGLABLE]
// Face MINUTERIE
int BUZZER = 3; // broche 3: buzzer
boolean KEEPtime = false; // utilisé pour compter une seule fois le changement (ne pas redémarrer pendant comptage)
int TIMERmillis = 0; // pour détermination compte à rebours
int prevSHOWsecond = 0;
int CountdownInMillis = 0;
int SHOWmillis = 0; // résultat calcul millis
int SHOWminute = 0; // minutes à afficher sur moniteur
int SHOWseconds = 0; // secondes à afficher sur moniteur
const int SETminute = 2; // régler minuteur 2 minutes [RÉGLABLE]
const int SETsecond = 30; // régler 30 secondes [RÉGLABLE]
// Face SON
const int soundLED = 9; // broche 9: LED verte
const int soundSENSOR = A1; // broche A1: capteur son
int brightness = 0; // initialisation luminosité LED verte
// Face TV
const byte ROWS = 4; // 4 lignes keypad
const byte COLS = 3; // 3 colonnes keypad
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
}; // valeurs boutons keypad
byte rowPins[ROWS] = {10,8,7,6}; // broches 10,8,7,6: lignes keypad
byte colPins[COLS] = {5,4,2}; // broches 5,4,2: colonnes keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // initialisation keypad
// Face OFF
const int LEDOFF = A2; // broche A2: LED rouge
void setup() {
pinMode(LEDlights, OUTPUT); // toutes les LED en sortie
pinMode(LEDhot, OUTPUT);
pinMode(LEDcold, OUTPUT);
pinMode(soundLED, OUTPUT);
pinMode(LEDOFF, OUTPUT);
Serial.begin(9600); // communication série
CountdownInMillis = (SETminute*60 + SETsecond)*1000; // calcul millis correspondant aux minutes/secondes
lcd.begin(16, 2); // initialisation LCD
lcd.setRGB(0, 0, 0); // LCD RGB éteint au début
// initialisation dispositif
Serial.println("Initializing IMU device...");
CurieIMU.begin(); // initialisation IMU
CurieIMU.setAccelerometerRange(2); // plage accéléromètre 2G
// Activation détection choc
CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 7000); // 7.0g = 7000 mg (intensité choc)
CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 2000); // 2000ms (durée choc)
CurieIMU.interrupts(CURIE_IMU_SHOCK); // interruption sur choc
// Initialisation BLE
blePeripheral.setLocalName("SmartCubeSketch"); // nom du projet
blePeripheral.setAdvertisedServiceUuid(lightsService.uuid()); // UUID service lumières
blePeripheral.addAttribute(lightsService); // service BLE lumières
blePeripheral.addAttribute(lightsChar); // caractéristique BLE lumières
lightsChar.setValue(3); // valeur initiale = 3
// Signification valeurs BLE lumières: 0=éteint, 1=allumé, 3=état initial, 4=non utilisé
blePeripheral.setAdvertisedServiceUuid(termoService.uuid()); // UUID service température
blePeripheral.addAttribute(termoService); // service BLE température
blePeripheral.addAttribute(termoChar); // caractéristique BLE température
termoChar.setValue(0); // valeur initiale 0: clim off - chauffage off
// Signification BLE température: 0=clim off-chauffage off, 1=clim on-chauffage off, 2=clim off-chauffage on, 3=non utilisé
blePeripheral.setAdvertisedServiceUuid(TVService.uuid()); // UUID service TV
blePeripheral.addAttribute(TVService); // service BLE TV
blePeripheral.addAttribute(TVChar); // caractéristique TV
TVChar.setValue('x'); // valeur initiale (x = rien)
// Signification BLE TV: #chiffre=bouton pressé, C: fermer TV, O: ouvrir TV, x: état initial
blePeripheral.begin();
Serial.println("Bluetooth device active, waiting for connections...");
} // fin setup
void loop() {
BLECentral central = blePeripheral.central(); // connexion BLE
unsigned long currentMillis = millis(); // temps actuel en millisecondes
// Code provenant de www.arduino.cc/en/Tutorial/Genuino101CurieIMUAccelerometerOrientation
// Utilisé pour détecter l'orientation de la carte
int orientation = -1; // orientation de la carte
String orientationString; // chaîne pour description orientation
// lecture accéléromètre:
int x = CurieIMU.readAccelerometer(X_AXIS);
int y = CurieIMU.readAccelerometer(Y_AXIS);
int z = CurieIMU.readAccelerometer(Z_AXIS);
// valeurs absolues pour déterminer la plus grande
int absX = abs(x);
int absY = abs(y);
int absZ = abs(z);
if ((absZ > absX) && (absZ > absY)) { // orientation base sur Z
if (z > 0) { orientationString = "up"; orientation = 0; }
else { orientationString = "down"; orientation = 1; }
} else if ((absY > absX) && (absY > absZ)) { // orientation base sur Y
if (y > 0) { orientationString = "digital pins up"; orientation = 2; }
else { orientationString = "analog pins up"; orientation = 3; }
} else { // orientation base sur X
if (x < 0) { orientationString = "connector up"; orientation = 4; }
else { orientationString = "connector down"; orientation = 5; }
}
// Fin code tutoriel.
// À ce point, vous avez la valeur d'orientation constamment mise à jour:
/* Orientations de la carte:
0: à plat, processeur face haute (MINUTERIE)
1: à plat, processeur face basse (TV)
2: paysage, broches analogiques bas (TEMPÉRATURE)
3: paysage, broches analogiques haut (OFF)
4: portrait, connecteur USB haut (LUMIÈRES)
5: portrait, connecteur USB bas (SON) */
// Pour ce projet, il faut savoir si la face a changé par rapport à la précédente [lastFUNCTION != orientation]
// Mais cette info n'est affichée que si la face reste en position HAUTE pendant plus de [interval] temps
// Et une seule fois [keep] (pas besoin d'activer constamment, une fois suffit)
// Comme orientation est constamment mise à jour, il faut commencer à compter quand elle change [orientation != lastOrientation]
if (orientation != lastOrientation) {
// si orientation a changé, commencer à compter le temps
lastOrientation = orientation; // mémoriser orientation actuelle
previousMillis = currentMillis; // mémoriser temps du changement
keep = false;
} else if (currentMillis - previousMillis > interval && keep == false && lastFUNCTION != orientation) {
// cette condition affiche l'orientation seulement si la face est haute pour un intervalle
// et une seule fois (keep)
// et seulement si la face est différente de la boucle précédente
Serial.println(orientationString); // afficher orientation
// la face courante [orientation] est mise à true (fonction face activée)
if (orientation == 1) { // face TV
face1 = true;
lastFUNCTION = orientation;
Serial.println("TV true");
TVChar.setValue('O'); // O: signal ouverture TV (BLE): TV ouverte une seule fois
}
if (orientation == 4) { // face LUMIÈRES
face4 = true;
lastFUNCTION = orientation;
Serial.println("LIGHTS true");
}
if (orientation == 3) { // face OFF
face3 = true;
lastFUNCTION = orientation;
Serial.println("OFF true");
}
if (orientation == 5) { // face SON
face5 = true;
lastFUNCTION = orientation;
Serial.println("SOUND true");
}
if (orientation == 2) { // face TEMPÉRATURE
face2 = true;
lastFUNCTION = orientation;
Serial.println("TEMPERATURE true");
}
if (orientation == 0) { // face MINUTERIE
face0 = true;
lastFUNCTION = orientation;
Serial.println("TIMER true");
if (KEEPtime == false) { // minuteur activé seulement si 1er cycle ou arrêté
TIMERmillis = currentMillis; // commencer à compter
}
}
keep = true; // [keep] change pour ne pas réentrer dans cette condition si face ne change pas
}
// Condition pour fonction shake: si secoué plus de [SHAKEinterval] temps, face désactivée
if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK) && currentMillis - SHAKEpreviousMillis > SHAKEinterval) {
Serial.println("SHAKE"); // afficher "SHAKE" si secousse détectée
// la dernière face activée [lastFUNCTION] est mise à false (fonction désactivée)
// Désactivation TV
if (lastFUNCTION == 1) { // face TV
TVChar.setValue('C'); // C: signal fermeture TV BLE
Serial.println("TV false - CLOSE");
face1 = false; // face TV devient false
}
// Désactivation LUMIÈRES
if (lastFUNCTION == 4) { // face LUMIÈRES
if (central.connected() == true) { // si centrale connectée
lightsChar.setValue(0); // signal BLE lumières OFF
digitalWrite(LEDlights, HIGH); // allumer LED jaune pour voir cube dans noir
}
Serial.println("LIGHTS false - CLOSE");
face4 = false; // face LUMIÈRES devient false
}
// Face OFF
if (lastFUNCTION == 3) { // face OFF
// Face OFF secouée: tout fermer et LED rouge OFF allumée
digitalWrite(LEDOFF, HIGH); // LED rouge OFF allumée quand cube fermé
// Fermer toutes fonctions activées:
// FERMER TV
TVChar.setValue('C'); // C: signal fermeture TV BLE
Serial.println("TV false - CLOSE");
face1 = false;
// FERMER LUMIÈRES
Serial.println("LIGHTS false - CLOSE");
if (central.connected() == true) {
lightsChar.setValue(0);
digitalWrite(LEDlights, LOW); // LED lumières éteinte si face OFF secouée
}
face4 = false;
// FERMER SON
analogWrite(soundLED, LOW); // éteindre LED son
Serial.println("SOUND false - CLOSE");
face5 = false;
// FERMER TEMPÉRATURE
if (central.connected() == true) {
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // signal BLE température: 0 = clim off - chauffage off
}
Serial.println("TEMPERATURE false - CLOSE");
face2 = false;
// FERMER MINUTERIE
Serial.println("TIMER false - CLOSE");
lcd.setRGB(0, 0, 0); // LCD RGB éteint
lcd.clear();
KEEPtime = false;
face0 = false;
// Cube inactif, seule LED OFF active
Serial.println("OFF false - CLOSE");
face3 = false; // face OFF devient false
}
// Désactivation SON
if (lastFUNCTION == 5) { // face SON
analogWrite(soundLED, LOW); // éteindre LED son
Serial.println("SOUND false - CLOSE");
face5 = false; // face SON devient false
}
// Désactivation TEMPÉRATURE
if (lastFUNCTION == 2) { // face TEMPÉRATURE
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // éteindre LED température rouge
digitalWrite(LEDcold, LOW); // éteindre LED température bleue
termoChar.setValue(0); // signal BLE température: 0 = clim off - chauffage off
}
Serial.println("TEMPERATURE false - CLOSE");
face2 = false; // face TEMPÉRATURE devient false
}
// Désactivation MINUTERIE
if (lastFUNCTION == 0) { // face MINUTERIE
Serial.println("TIMER false - CLOSE");
face0 = false; // face MINUTERIE devient false
// si on secoue le cube pendant que le temps tourne, LCD devient rouge et affiche temps restant
lcd.setRGB(180, 40, 0); // rétroéclairage RGB rouge
lcd.clear(); // LCD effacé
lcd.setCursor(0, 0);
lcd.print("STOP AT ");
lcd.setCursor(8, 0);
lcd.print(SHOWminute); // minutes au moment de la secousse
lcd.setCursor(9, 0);
lcd.print(":");
lcd.setCursor(10, 0);
lcd.print(SHOWseconds); // secondes au moment de la secousse
tone(BUZZER,1000,1000); // son court
delay(2000);
lcd.clear(); // effacer LCD
lcd.setRGB(0, 0, 0); // rétroéclairage LCD éteint
KEEPtime = false; // face MINUTERIE devient false
}
SHAKEpreviousMillis = currentMillis; // mémoriser pour calcul [SHAKEinterval]
}
// Instructions suivantes exécutées en boucle seulement si face activée
if (face1 == true) { // face TV
digitalWrite(LEDOFF, LOW); // si face vraie, LED OFF LOW
if (central.connected() == true) { // si cube connecté BLE
char key = keypad.getKey(); // lecture valeur keypad
if (key && orientation == 1) { // si touche pressée et seulement si face TV haute (évite pressions involontaires)
if (key == '0') { TVChar.setValue(key); Serial.println(key); }
if (key == '1') { TVChar.setValue(key); Serial.println(key); }
if (key == '2') { TVChar.setValue(key); Serial.println(key); }
if (key == '3') { TVChar.setValue(key); Serial.println(key); }
if (key == '4') { TVChar.setValue(key); Serial.println(key); }
if (key == '5') { TVChar.setValue(key); Serial.println(key); }
if (key == '6') { TVChar.setValue(key); Serial.println(key); }
if (key == '7') { TVChar.setValue(key); Serial.println(key); }
if (key == '8') { TVChar.setValue(key); Serial.println(key); }
if (key == '9') { TVChar.setValue(key); Serial.println(key); }
if (key == '*') { TVChar.setValue(key); Serial.println(key); }
if (key == '#') { TVChar.setValue(key); Serial.println(key); }
}
}
}
if (face4 == true) { // face LUMIÈRES
digitalWrite(LEDOFF, LOW);
if (central.connected() == true) {
lightsChar.setValue(1); // signal BLE lumières ACTIVÉES
digitalWrite(LEDlights, LOW); // LED jaune éteinte car lumières maison allumées
}
}
if (face3 == true) { // face OFF
// quand face OFF haute, rien n'est fait
digitalWrite(LEDOFF, LOW); // LED OFF activée seulement quand cube secoué, donc LOW maintenant
}
if (face5 == true) { // face SON
digitalWrite(LEDOFF, LOW);
// capteur son activé, luminosité LED régulée par le son
// code issu exemple régulation luminosité
long sum = 0;
for (int i=0; i<32; i++) {
sum += analogRead(soundSENSOR);
}
sum >>= 5;
brightness = (sum*255)/1024; // calcul valeur luminosité
analogWrite(soundLED, brightness); // intensité LED verte régulée par bruit
delay(50); // fin exemple régulation
}
if (face2 == true) { // face TEMPÉRATURE
digitalWrite(LEDOFF, LOW);
if (central.connected() == true) {
// lecture température
int val = analogRead(pinTemp); // valeur analogique
resistance=(float)(1023-val)*10000/val; // résistance
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcul température
// conditions activation
if (temperature > tooHot) { // activer clim
digitalWrite(LEDhot, LOW); // éteindre LED chauffage
digitalWrite(LEDcold, HIGH); // allumer LED clim
termoChar.setValue(1); // 1 = clim on - chauffage off
}
if (temperature < tooCold) { // activer chauffage
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = clim off - chauffage on
}
if (temperature > tooCold && temperature < tooHot) { // température idéale
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = clim off - chauffage off
}
}
}
if (face0 == true) { // face MINUTERIE activée
digitalWrite(LEDOFF, LOW);
// calcul temps à afficher
SHOWmillis = (CountdownInMillis - (currentMillis - TIMERmillis))/1000;
SHOWminute = SHOWmillis/60; // minutes pour LCD
SHOWseconds = SHOWmillis%60; // secondes pour LCD
lcd.setRGB(50, 100, 70); // LCD RGB bleu
if (prevSHOWsecond != SHOWseconds) { // rafraîchir écran chaque seconde
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TIMER ");
lcd.setCursor(7, 0);
lcd.print(SETminute); // minutes réglées
lcd.setCursor(8, 0);
lcd.print(":");
lcd.setCursor(9, 0);
lcd.print(SETsecond); // secondes réglées
lcd.setCursor(0, 1);
lcd.print(SHOWminute); // minutes restantes
lcd.setCursor(1, 1);
lcd.print(":");
lcd.setCursor(2, 1);
lcd.print(SHOWseconds); // secondes restantes
KEEPtime = true;
prevSHOWsecond = SHOWseconds; // pour rafraîchir chaque seconde
}
if (SHOWminute == 0 && SHOWseconds == 0) { // fin compte à rebours
lcd.clear();
lcd.setCursor(4, 0);
lcd.setRGB(180, 40, 0); // LCD RGB rouge
lcd.print("TIME OUT");
tone(BUZZER,1000,500); // trois sons
delay(900);
tone(BUZZER,1000,500);
delay(900);
tone(BUZZER,1000,1000);
delay(1500);
lcd.clear(); // effacer et fermer LCD
lcd.setRGB(0, 0, 0);
face0 = false; // face MINUTERIE fermée (false)
KEEPtime = false;
}
}
} // fin loop
Pièces personnalisées et boîtiers
Fichier (.dxf) à charger sur votre découpeuse laser. J'ai utilisé du MDF (panneau de fibres à densité moyenne) de 3 mm. Découpez les lignes noires et gravez les lignes rouges. Important : si l'épaisseur de votre matériau diffère, vous devez modifier ce plan.
smart_cube_8sVCflFmhM.dxf
Même fichier mais dans un format différent : .pdf
Schémas
Schéma Fritzing (fils jaunes = composants Grove)

Schéma des connexions sur le Grove Shield
_cI0IwUsPVZ.Base%20shield%20connections
Processus de fabrication
- Panneaux solaires : un investissement judicieux pour votre maison
- Pourquoi un design légèrement plus grand peut accélérer l'innovation et réduire les risques
- Comment la technologie maison intelligente transforme la vie quotidienne
- Construire un réseau de capteurs sans fil abordable pour votre maison
- Surveiller la température de votre maison avec un tableau de bord Raspberry Pi
- Combler le fossé des compétences smart home : pourquoi la Grande-Bretagne traîne l'Europe
- Évolution maison intelligente : ce que l'avenir réserve pour le connected living
- Sécurité intelligente : stratégies d'experts pour protéger vos appareils IoT domestiques des hackers
- Comment renforcer la sécurité de votre maison intelligente : conseils d'experts