Projets IoT

Projet DIY IoT : Construire une jardinière intelligente à faible coût

Maria Hernández
· 11 min de lecture
Envoyer par email

Il y a quelques semaines, j'ai décidé d'acheter une plante succulente pour mon bureau uniquement en raison des avantages qu'elle peut apporter à l'environnement. Au cas où vous ne le sauriez pas, la culture de plantes grasses ou de cactus peut vous être bénéfique de plusieurs manières : elles aident à purifier l'air, à améliorer l'humidité des espaces et à ajouter de l'oxygène frais à l'environnement.

Après quelques jours passés à avoir Lana (Oui, je l'ai nommée Lana 💕) sur mon bureau, j'ai commencé à sentir qu'il manquait quelque chose. En tant que créateur passionné et IoT chez Ubidots , j'ai décidé de créer un " Smart Planter " pour Lana en utilisant nos outils. Après quelques jours de travail acharné et de nombreux problèmes d'impression, j'ai finalement obtenu ce résultat sympa, et j'avais hâte de partager avec vous mon processus 🙆‍♀️💚 :

Ce projet a été inspiré par un précédent créé par Paul a Maker 👨‍💻 (Impression 3D, Electronique, Logiciel) que j'ai suivi il y a des mois, et je peux dire que j'ai appris de nombreux trucs et astuces grâce à lui. Si vous cherchez de l'inspiration pour vos projets électroniques, vous devriez le suivre , croyez-moi.

Personnellement, j'aime beaucoup trouver ma propre inspiration en suivant les projets de quelqu'un d'autre. De toute façon, je trouverai toujours un moyen d'ajouter mon propre style, de donner des crédits et, bien sûr, de partager le résultat final avec d'autres personnes comme moi. inspiré également. 🤓 🤓

Cet article contient une étape par étape de mon projet, ainsi que toutes les ressources nécessaires pour reproduire le " Smart Planter ".

Exigences

Étape par étape

  1. Impression 3D
  2. Câblage
  3. Enveloppe
  4. Noeud de programmationMCU ESP8266
  5. Dashboard - Contrôle et surveillance
  6. Résumé

1. Impression 3D

Mes compétences en matière de modélisation de pièces 3D sont assez limitées (j'y travaille pour créer davantage de projets en utilisant l'imprimante 3D), mais il existe une communauté ouverte appelée Thingiverse qui nous facilite la vie. Il s'agit d'une communauté de conception florissante permettant de découvrir, de créer et de partager des objets imprimables en 3D. Après avoir regardé de nombreux modèles de jardinières, j'ai décidé d'imprimer celui-ci :

Cliquez ici pour télécharger le design - thing:2857938

J'ai vraiment aimé ce design car il s'agissait déjà d'une jardinière IoT et la lampe était un accessoire magnifique et cool. En gros, ce modèle correspondait parfaitement à ce que j’avais en tête depuis le début :

  • Lampe pour télécommande.
  • Espace pour placer des composants électroniques pour ajouter quelques capteurs.

Cependant, je savais que l'espace réservé à l'électronique n'était pas suffisant pour toutes les fonctionnalités que je souhaitais inclure. Pour résoudre ce problème, j'ai imprimé 2 fois la pièce du bas :

  • Pièce blanche : Pour placer le NodeMCU ESP8266, les capteurs et les fils.
  • Pièce transparente : Pour placer l'anneau NeoPixel.

Ayant pour résultat le chef-d'œuvre ci-dessous :

NOTE : La bague NeoPixel n'est pas obligatoire pour ce projet, c'était juste un accessoire qui le rendait plus joli. Vous pouvez également n'utiliser qu'une seule pièce.

2. Câblage

Selon le firmware fourni dans ce guide, reportez-vous au schéma et au tableau ci-dessous pour établir une connexion appropriée entre les composants utilisés.

3. Boîtier

Une fois les connexions électriques appropriées déjà établies, placez tous les composants à l'intérieur du pot comme indiqué ci-dessous :

Comme vous pouvez le remarquer, j'ai placé le NodeMCU dans une planche à pain PCB avec 10 en-têtes à angle droit. L'idée était d'établir la connexion avec les capteurs et de gagner de la place pour l'électronique. Pour être honnête, j'aurais pu faire un meilleur travail en organisant les câbles. Cependant, l’idée était de créer un PCB personnalisé pour le planteur, à un moment donné, tout serait intégré. De plus, j'ai percé la pièce blanche pour y faire passer les câbles de l'anneau NeoPixel. Pour finir, j'ai collé l'anneau NeoPixel pointant vers le bas, puis j'ai collé la pièce transparente sur la blanche afin de flouter la lumière. Au final j'ai eu ce résultat génial :

4. Programmation du nœud MCU ESP8266

1. Pour pouvoir travailler avec la ESP8266 dans l'IDE Arduino, vous devrez installer la plateforme ESP8266 Arduino Board Manager préconfiguré . Si vous n'êtes pas familier avec l'ajout d'une carte avec l'IDE Arduino, reportez-vous à cet article pour obtenir des conseils supplémentaires .

2. Une fois la plateforme ESP8266 installée, sélectionnez l'appareil ESP8266 avec lequel vous travaillez. Dans le cas, nous travaillons avec un « NodeMCU 1.0 ». Pour sélectionner votre carte dans l'IDE Arduino, sélectionnez Outils > Carte « Module générique ESP8266 » .

3. Téléchargez et installez la Ubidots MQTTESP8266 . Pour une explication détaillée de la façon d'installer des bibliothèques à l'aide de l'IDE Arduino, reportez-vous à ce guide .

4. Collez le code ci-dessous dans l'IDE Arduino. Ensuite, attribuez votre TOKEN Ubidots unique , votre SSID (nom WiFi ) et votre mot de passe du réseau disponible.

REMARQUE : N'oubliez pas d'attribuer les bonnes broches aux composants utilisés au cas où vous utiliseriez une connexion différente de celle fournie ci-dessus.

Dépôt GitHub

/* Jardinière intelligente RVB intégrée à Ubidots pour la surveillance et le contrôle. Ce code fonctionne pour : 1) Lire deux capteurs : DHT11 et humidité du sol. 2) Publier les lectures des capteurs sur Ubidots . 3) Abonnez-vous à plusieurs variables pour le contrôle à distance. Bibliothèques requises : - Ubidots ESP8266 MQTT - ( ubidots / ubidots -mqtt-esp) - Adafruit NeoPixel - (https://github.com/adafruit/Adafruit_NeoPixel) - DHT - (https:// github.com/adafruit/DHT-sensor-library) Réalisé par : Maria Hernández - Défenseure des développeurs IoT @ Ubidots Révision : José García - Responsable du développement et du support @ Ubidots /*************** ************************* * Inclure les bibliothèques ********************** ******************/ #inclure<Adafruit_NeoPixel.h> #inclure<stdio.h> #inclure<map> #include "DHT.h" #include " Ubidots ESPMQTT.h" /************************************ ****** * Définir les broches ****************************************/ #define LIGHTPIN D1 // Broche numérique pour lampe LED. #define DHTPIN D5 // Broche numérique pour capteur DHT. #define NEOPIXELSPIN D6 // Broche numérique pour NeoPixel Ring. #define MOISTUREPIN A0 // Broche analogique pour capteur d'humidité. /**************************************** * Définir les constantes ****** **********************************/ #define TOKEN "BBFF-xxxxxxxxxx" // Attribuez votre JETON Ubidots . #define WIFINAME "xxxxxxxxxx" // Attribuez votre SSID. #define WIFIPASS "xxxxxxxxxx" // Attribuez votre mot de passe WiFi. #define DEVICE "planteur" // Étiquette du périphérique Ubidots . #define VAR_PUB_1 "temperature" // Libellé des variables Ubidots pour la publication des données. #define VAR_PUB_2 "humidité" #define VAR_PUB_3 "sol-humidité" #define VAR_PUB_4 "heat-index" #define VAR_SUB_1 "light-1" // Étiquette des variables Ubidots pour l'abonnement aux données ; \ // Ces variables doivent être créées chez Ubidots . #define VAR_SUB_2 "light-2" #define NUMPIXELS 12 // Anneau NeoPixel 12 bits // Décommentez le type que vous utilisez #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) typedef enum { rouge, vert, bleu, jaune, blanc, noir } NeoPixelColor; // R, G, B uint8_t myColors[][6] = {{250, 0, 0}, // Rouge. {0, 255, 0}, // Vert. {0, 0, 255}, // Bleu. {255, 255, 0}, // Jaune. {255, 255, 255}, // Blanc. {0, 0, 0}} ; // Noir. const uint8_t numberOfVariables = 2 ; // Nombre de variables pour l'abonnement. char *variableLabels[numberOfVariables] = {VAR_SUB_1, VAR_SUB_2}; // Libellé des variables pour l'abonnement. valeur flottante ; // Stocke la valeur entrante. int dernièreValeur ; bool bottomLight; // drapeau pour contrôler les conditions de la lumière inférieure. initTime long non signé ; // Stocke l'heure d'initialisation. const long SECONDS_TO_RECONNECT = 180 000 ; // Période pour reconnecter la connexion MQTT. // Foncteur de comparaison pour mapper les fonctions. struct cmp_str { bool Operator()(char const *a, char const *b) const { return strcmp(a, b) < 0; } } ; // Déclaration de la fonction Map. typedef std :: fonction<void()> Type de fonction ; typedef std :: map<const char *, FunctionType, cmp_str> mapTopicSubscription ; /**************************************** * Définir les instances ****** **********************************/ Client Ubidots (JETON) ; Adafruit_NeoPixel pixels (NUMPIXELS, NEOPIXELSPIN, NEO_GRB + NEO_KHZ800) ; DHT dht(DHTPIN, DHTTYPE); mapTopicSubscription ubiSubTopic; /****************************************** * Fonctions principales ****** **********************************/ void setup() { initTime = millis(); // Enregistre l'heure d'initialisation Serial.begin(115200); pinMode(LIGHTPIN, SORTIE); // Déclarer le mode pin // Définit les fonctions mappées pour gérer l'événement d'abonnement. ubiSubTopic[VAR_SUB_1] = &subscriptionHandler1; ubiSubTopic[VAR_SUB_2] = &subscriptionHandler2; client. ubidots SetBroker(" ubidots .com"); // Définit correctement le courtier pour le // compte professionnel. client.setDebug(true); // Passez une valeur booléenne true ou false pour activer les messages de débogage. client.wifiConnection(WIFINAME, WIFIPASS); // Établit une connexion WiFi. client.begin(rappel); dht.begin(); // Initialise le capteur DHT. pixels.begin(); // Initialise l'anneau NeoPixel. pixels.clear(); // Définit toutes les couleurs de pixels sur "off". // Établit l'abonnement avec les variables définies. client. ubidots Abonnez-vous (DEVICE, VAR_SUB_1); client. ubidots Abonnez-vous (DEVICE, VAR_SUB_2); } void loop() { // Rétablit l'abonnement avec les variables définies lorsque la connexion est perdue ou toutes les 3 minutes. if (!client.connected() || abs(millis() - initTime) > SECONDS_TO_RECONNECT) { initTime = millis(); client.reconnect(); client. ubidots Abonnez-vous (DEVICE, VAR_SUB_1); client. ubidots Abonnez-vous (DEVICE, VAR_SUB_2); } client.reconnect(); // Lecture des valeurs de température, d'humidité et d'humidité du sol.a float Moisture = dht.readHumidity(); température flottante = dht.readTemperature(); int solMoisture = analogRead(MOISTUREPIN); // Calcule l'indice de chaleur en Celsius (isFahreheit = false). float heatIndexC = dht.computeHeatIndex(température, humidité, false); // Vérifiez si des lectures ont échoué et quittez plus tôt (pour réessayer). if (isnan(humidité) || isnan(température)) { Serial.println(F("Échec de la lecture du capteur DHT !")); } // Contrôle les couleurs de NeoPixel en fonction des valeurs de température. if (bottomLight) { if (inRange(temperature, 0, 16)) colorWipe(bleu, 50); if (inRange(temperature, 16, 21)) colorWipe(green, 50); if (inRange(temperature, 21, 26)) colorWipe(jaune, 50); if (inRange(temperature, 26, 40)) colorWipe(red, 50); } // Ajoute des variables à publier sur Ubidots . client.add(VAR_PUB_1, température); client.add(VAR_PUB_2, humidité); client.add(VAR_PUB_3, humidité du sol); client.add(VAR_PUB_4, heatIndexC); // Publie toutes les variables ajoutées dans le périphérique défini. client. ubidots Publier(DEVICE); client.loop(); retard (1000); } /**************************************** * Fonctions d'abonnement ***** ***********************************/ // Fonction à exécuter lorsque var_sub_1 change d'état. void souscriptionHandler1() { if (value == 1) { Serial.println("Lampe de jardinière allumée."); digitalWrite (LIGHTPIN, HAUT); } else { Serial.println("Lampe de jardinière éteinte."); digitalWrite (LIGHTPIN, FAIBLE); } } ; // Fonction à exécuter lorsque var_sub_2 change de statut. void souscriptionHandler2() { if (value != lastValue) { if (value == 1) { Serial.println("Lumière inférieure du planteur allumée."); pour (int i = 0; i < 3; i++) { colorWipe(rouge, 50); colorWipe (vert, 50); colorWipe (bleu, 50); } ; couleurWipe (blanc, 200); bottomLight = vrai ; } else { Serial.println("Lumière inférieure du pot éteinte."); couleurWipe (blanc, 50); couleurWipe (noir, 200); bottomLight = faux ; } } lastValue = valeur ; } ; /****************************************** * Fonctions auxiliaires ****** **********************************/ // Renvoie un int avec la longueur d'un char int strLen(char *s) {int l = 0 ; tandis que (*s != '\0') { s++; l++; } retourner (l); } // Rappel pour gérer l'abonnement void callback(char *topic, byte *payload, unsigned int length) { char *variableLabel = (char *)malloc(sizeof(char) * 30); getVariableLabelTopic(sujet, variableLabel); // Enregistre l'étiquette de la variable. valeur = btof (charge utile, longueur); // Enregistre la valeur de la variable souscrite. exécuterCases(variableLabel); // Exécute le gestionnaire de fonctions pour la // variable à laquelle vous êtes abonné. free(étiquettevariable); // Mémoire libre. } // Analyse le sujet reçu pour extraire le label de la variable. void getVariableLabelTopic(char *topic, char *variableLabel) { sprintf(variableLabel, ""); for (int i = 0; i < numberOfVariables; i++) { char *resultLv = strstr(topic, variableLabels[i]); if (resultLv != NULL) { uint8_t len ​​= strlen(resultLv); résultat de caractères[100] ; uint8_t je = 0; pour (i = 0; i < len - 3; i++) { result[i] = resultLv[i]; } résultat[i] = '\0'; snprintf(variableLabel, strLen(result) + 1, "%s", résultat); casser; } } } // Converti un tableau de caractères en valeur flottante. float btof(byte *payload, unsigned int length) { char *demo_ = (char *)malloc(sizeof(char) * 10); for (int i = 0; i < length; i++) { demo_[i] = payload[i]; } return atof(demo_); } // Exécute la « Fonction d'abonnement » respective en fonction de la valeur reçue. void exécuterCases(char *variableLabel) { if (ubiSubTopic.find(variableLabel) != ubiSubTopic.end()) { mapTopicSubscription::iterator i = ubiSubTopic.find(variableLabel); (i->seconde)(); } } // Remplit les pixels de l'anneau NeoPixel les uns après les autres avec de la couleur. void colorWipe (couleur NeoPixelColor, int wait) { int r, g, b; r = mesCouleurs[couleur][0]; g = mesCouleurs[couleur][1]; b = mesCouleurs[couleur][2]; pour (int i = 0; i < pixels.numPixels(); i++) { pixels.setPixelColor(i, r, g, b); pixels.show(); retarder(attendre); } } // Vérifie si la valeur reçue est dans la plage attendue bool inRange(float x, int low, int high) { return ((x - low) > 0 && (high - x) >= 0); }

5. Vérifiez votre code dans l'IDE Arduino. Pour ce faire, dans le coin supérieur gauche de notre IDE Arduino, vous verrez l'icône « Coche » ; sélectionnez-le pour vérifier votre code.

6. Téléchargez le code dans votre « NodeMCU 1.0 » . Pour ce faire, choisissez l' icône flèche droite » coche ».

7. Pour vérifier la connectivité de l'appareil et les données envoyées, ouvrez le moniteur série en sélectionnant l'icône « loupe » dans le coin supérieur droit de l'IDE Arduino pour voir les logs ainsi que les réponses du Ubidots .

8. Après quelques secondes d'initialisation, le code fourni créera automatiquement un nouvel appareil dans votre Ubidots . Rendez-vous dans la section appareils de votre compte Ubidots ; vous devriez voir de nouveaux appareils créés automatiquement :

Entrez le dispositif « Planter » et voyez les variables configurées pour transmettre les données :

9. Créez ensuite deux nouvelles variables brutes pour établir l'abonnement et contrôler les lumières à distance. Pour ce faire, cliquez sur "Ajouter une variable > Variable brute " et attribuez le label de variable défini dans le code. Pour l'exemple de code fourni, les étiquettes de variables à créer sont "light-1" et "light-2" .

Une fois les variables créées avec succès, vous devriez obtenir le résultat suivant :

5. Dashboard - Contrôle et surveillance

Avec tout déjà intégré, il est temps de présenter les données des appareils dans un Dashboard . De plus, le dashboard servira également à contrôler l'état des deux lampes.

1. Pour créer votre premier dashboard , rendez-vous sur le Dashboard onglet (Données → Dashboards ) . Ensuite, sélectionnez l'icône plus (+) en haut à droite, puis sélectionnez le type de widget souhaité. Vous devriez pouvoir créer dashboards comme celui ci-dessous :

En savoir plus sur Dashboards Ubidots : Branding de l'application : styles personnalisés pour vos dashboards et widgets

Ubidots est très intuitif pour tout utilisateur pour administrer ses données, permettant à chacun de les personnaliser autant qu'il le souhaite ; au cas où vous souhaiteriez en savoir plus, je vous recommande vraiment de consulter les guides suivants :

2. Ubidots prend en charge les événements déjà intégrés pour vous permettre d'envoyer des événements, des alertes et des notifications en fonction des données de vos capteurs et actionneurs.

Découvrez le type d'événements pris en charge et apprenez comment configurer chacun d'eux:

  1. Notifications par courrier électronique
  2. Notifications SMS
  3. Événements Webhook - en savoir plus
  4. Notifications de télégramme
  5. Notifications Slack – en savoir plus
  6. Notifications d'appels vocaux - en savoir plus
  7. Retour à la notification normale - en savoir plus
  8. Notifications de géolocalisation - en savoir plus

6. Résumé

Après quelques heures de création et de codage (et beaucoup de cafés), j'ai donné vie à ce Smart Planter :

Comme je l'ai mentionné au début, j'ai fait cela parce que je ne voulais pas seulement une nouvelle décoration de bureau, mais aussi parce que je sentais qu'il manquait quelque chose à Lana, je voulais inventer ma propre façon de communiquer avec elle via IoT et les données. Si vous souhaitez d'autres moyens de communiquer avec vos plantes, vous pouvez les écouter en utilisant le MIDI Sprout . C'est cool, non ? 🤩

Ce n'est que la V0 du Smart Planter et il y a quelques choses que je souhaite améliorer, comme la conception, l'organisation électronique avec un PCB personnalisé et l'intégration avec d'autres services tels que Google Assistance, Alexa et Twitter.

J'espère que vous avez apprécié cela comme moi. Si vous avez des commentaires ou des questions sur le projet, n'hésitez pas à nous contacter ! Je suis totalement ouvert aux retours constructifs pour valoriser ce type de projets et les partager avec vous. 😁💚

Projets IoT plus utiles :