Robot-Plante

Durant la période de confinement, j'ai pu consacrer du temps à mes plantes. Entretenir des interactions avec ces créatures n'est pas une chose facile. Pourtant, je suis depuis longtemps fasciné par le poème de Richard Brautigan, "All watched over machines of loving grace", et je rêve, moi aussi, à une harmonie mutuelle entre plantes, machines et humains. Quoi qu'en dise Adam Curtis dans sa série documentaire nommée d'après le poème de Brautigan, je reste persuadé que la pensée systèmique et la création de machines, robots et autres objets électroniques peut permettre l'ouverture aussi bien des esprits que des shakra quant à notre approche de la "nature" (qui n'existe pas).
Pour explorer cette idée, je me suis attelé à la fabrication de robot-plante !

Évidement, la première chose à laquelle on pense lorsqu’on imagine une machine qui prend soin d’une plante, c’est l’arrosage. Une telle fonctionnalité constitue un projet trivial de makers et les tutoriels à ce sujet pullulent sur internet. Il me fallait agrémenter une telle machine de fonctionnalités plus évoluées capables de produire une perception de la plante. Intuitivement je me suis inspiré de ce que font les humains pour interagir avec les plantes : les regarder avec attention. Pour mon premier essai j’ai donc décidé de monter une pompe a eau 12v sur un relay-switch permettant de l’activer et de la désactiver, puis de me concentrer sur l’utilisation d’une caméra JeVois A33, elle même montée sur deux petits servomoteurs permettant de la diriger en avant, en arrière et de gauche à droite.

C’est un poireau qui fût candidat à l’expérience. Ce légume est étonnamment facile à faire pousser et il était aisé de s’en fournir en pleine période de confinement. La fonction d’arrosage était facile à mettre en place. Le capteur d’humidité renvoyait au contrôleur (un esp8266 modèle Lolin V3) une valeur changeante en fonction de la conductivité (et donc de la quantité d’eau) de la terre. Lorsque cette valeur atteint un certain seuil de sécheresse, le contrôleur activait la pompe à eau sur une durée déterminée de quelques secondes. La caméra JeVois A33 est un véritable ordinateur à elle seule. Elle embarque un CPU/GPU et de nombreux modules de vision par ordinateur y sont pré-installés. Je l’ai alors programmée de façon a ce qu’elle lance un module de classification d’objets : YoloV3. Régulièrement, elle était activée par le biais d’un second relay-switch et transmettait au contrôleur, par les pins séries (Tx / Rx) le nom des objets qu’elle détectait en observant la plante. Afin de visualiser tout ça, j’ai ensuite écrit une petite interface web qui stockait et affichait les résultats obtenus.

Ce premier robot-plante était un peu gros et trop sous-optimal à mon goût. La consommation électrique de l’ensemble était importante avec deux transformateurs 5v 2A et un transformateur 12v pour la pompe.

J’ai donc décidé de tout recommencer à zéro.

Dans le premier robot-plante, j’avais utilisé un capteur résistif d’humidité du sol. Les pattes de métal de ces capteurs sont exposées à l’eau et à la terre. Ils subissent rapidement la corrosion et deviennent inutilisables tout en libérant des substances toxiques dans la terre. Je me suis donc fourni un capteur capacitif, d’une bien meilleure durée de vie.

Je me suis également procuré une petite pompe à eau fonctionnelle à 3-5v, un relay et surtout un micro-contrôleur ESP32-CAM. Ce contrôleur ESP32 est équipé d’une petite caméra et permet des connectivité WiFi et Bluetooth. Pour alléger le système, j’ai imaginé ce nouveau robot-plante sans y intégrer l’unité de traitement de l’image (précédemment située dans la JeVois A33). Celle-ci sera, plus tard, déportée sur un raspberry-pi hébergeant un serveur. En séparant cet élément de l’ensemble du robot-plante, ce dernier devient plus flexible et on peut alors envisager d’y placer une batterie de façon à ce qu’il soit le plus autonome possible.

D'un point de vue programmation, l’esp32-CAM n’est pas un micro-contrôleur très documenté. J’ai du me dépatouiller avec quelques problèmes techniques tels que la lecture de valeurs analogiques sur une pin ADC2 tout en utilisant le WiFi. Néanmoins je suis parvenu à régler ce soucis particulier. Après avoir réussi à recevoir des valeurs du capteur d'humidité sur la broche GPIO14, je me suis assuré que le relay-switch pouvait être activé via la broche GPIO02, puis je me suis rendu compte que la broche GPIO04 permettait de contrôler une éblouissante diode electro-luminescente. Inclue sur la carte ESP32-Cam, cette DEL est destinée à être utilisée comme un flash d'appareil photo.

Fort de ces petites expériences, je me suis attelé à la programmation du système d'irrigation et de photographie de la plante. L'image enregistrée à chaque arrosage doit être transmise, par l'ESP32-Cam, à un serveur connecté sur le réseau WiFi local. Pour arroser la plante, j'ai décidé de programmer un cycle dont les valeurs peuvent être modifiées plus tard. L'objectif est de faire en sorte que le serveur distant puisse ajuster les valeurs pour créer une forme d'auto-stabilisation entre la pousse de la plante et le comportement de la machine.

La procédure d'arrosage est écrite ainsi :

// Arrosage
void watering() {
 for(int i=0; i<NB_CYCLE_WATERING; ++i) {
   Serial.print(" -> Cycle numero ");
   Serial.println(i);

   relay_state = HIGH;
   digitalWrite(relay_pin, relay_state); // On arrose !

   delay(WATERING_TIME);
   relay_state = !relay_state;
   digitalWrite(relay_pin, relay_state); // On éteint l'arrosage

   delay(TIME_BTWN_WATERING); // On attend un peu que l'eau pénetre dans la terre
 }
}
              

Trois valeurs sont destinées à être ajustées par le serveur distant :

  • WATERING_TIME correspond au temps durant lequel l'eau est acheminée jusqu'a la terre, le temps durant lequel la pompe est activée
  • TIME_BTWN_WATERING correspond au temps d'attente entre deux activation de la pompe, essentiellement pour laisser à l'eau le temps de pénétrer la terre.
  • NB_CYCLE_WATERING correspond au nombre de fois ou l'on active la pompe durant une session d'arrosage
  • Pour envoyer l'image au serveur, je me suis basé sur la librairie esp_http_client. Lorsque l'on capture une image avec l'ESP32-Cam, l'image est encodée dans la mémoire vive et accessible par l'objet "buf". Pour transmettre l'image et l'enregistrer sur le serveur distant, il suffit de forger une requête POST à destination d'un script php.

    void send_a_picture() {
     esp_http_client_config_t config = {
       .url = "http://192.168.1.254/plantbot/reception_image.php"
     };
    
     esp_http_client_handle_t client = esp_http_client_init(&config);
     esp_http_client_set_post_field(client, (const char *)fb->buf, fb->len);
     esp_http_client_set_method(client, HTTP_METHOD_POST);
     esp_http_client_set_header(client, "Content-type", "image/jpg");
     esp_err_t err = esp_http_client_perform(client);
     if (err == ESP_OK)
       Serial.println("Image envoyée");
     else
       Serial.printf("erreur %d lors de l'envoi de l'image\r\n", err);
    
     esp_http_client_cleanup(client);
    
     esp_camera_fb_return(fb);
    }
                  

    Le script PHP, lui, est extremement simple :

    
    <?php
    $received 
    file_get_contents('php://input');
    $fileToWrite "upload - ".time().".jpg";
    file_put_contents($fileToWrite$received);
    ?>

    Chaque donnée reçu par ce script sera enregistrée sous la forme d'un JPEG. Si je visite la page avec mon navigateur, il va créer un fichier jpeg vide. Mais notre ESP32-Cam, grâce au code ci-dessus, lui enverra les données de l'image qu'il va enregistrer.
    Le code complet, dans son état actuel d'avancement, est disponible ici . Pour l'instant, le serveur ne fait qu'enregistrer les images et la boucle de stabilisation n'est pas encore écrite.