Skip to main content

Génodique

II. Protocole de mise en œuvre du projet

Dans un premier temps, notre objectif est de bien comprendre la méthodologie utilisée dans les études existant sur la génodique. Pour cela, nous contacterons l’équipe de Génodics ainsi que les chercheurs ayant mené des études sur le sujet, afin d’obtenir des précisions sur leurs protocoles, leurs résultats et leurs outils d’analyse. Dans le même temps, nous chercherons un laboratoire disposé à nous accompagner dans cette démarche. 

Une fois le laboratoire trouvé, l’objectif est de répliquer expérimentalement l’étude sur les pois mais avec une culture de radis : Arabidopsis thaliana, homologue du radis et du colza de la famille des Brassicacées qui poussent très vite par rapport aux pois. Le génome d’Arabidopsis est entièrement connu donc la création des protéodies est possible. Nous reprendrons le même protocole de stress hydrique du pois vert mais en stimulant les protéines de type DHN propres à l’Arabidopsis. Ces protéines sont codées par les gènes LEA et ERD chez les végétaux. Nous en avons identifié une première, la protéine AtHIRD11 (code gène : At1g54410). Cela nous permettra de tester la théorie et de s’approprier le protocole expérimental de la génodique (création et diffusion de la protéodie) et de la culture de plantes.


Si ces expérimentations confirment les résultats observés dans l’étude initiale, l’objectif sera de l'appliquer à des cultures de colza, végétal très important dans la production mondial de légumes et aussi source de bio essence. Il suffira de retrouver les séquences homologues à celles de Arabidopsis. Dans une même famille, seulement quelques acides aminés changent dans le code génétique.

          Nous aimerions aussi observer sur un terrain agricole une installation de Genodics pour comprendre le protocole qu'ils utilisent à grande échelle. Cela passera notamment par l'évaluation des coûts et des infrastructures utilisés, notamment les hauts parleurs pour émettre les protéodies.

        Si nous avons le temps, nous aimerions continuer les expérimentations en laboratoire pour rédiger un nouvel article scientifique sur de nouvelles protéodies en lien avec un stress climatique : gel (hiver plus sec et froid en Europe), excès d'eau (moussons à l'équateur) ou un stress édaphique (propriété du sol) : carence en minéraux (sols labourés), acidité ou alcalinité du sol, pollution des sols par le plastique… Nous ne pouvons pas vous dire précisément quel stress nous allons étudier car il faut trouver et isoler, si elles existent, les protéines qui codent la résilience à chaque stress selon les plantes utilisées par l'agriculteur. Il faudra s'entourer d’experts pour répondre à ces questions techniques.


         Il est aussi possible de façon plus générale d’utiliser la génodique sur protéines en lien direct avec la production des hormones de croissances des plantes (auxine, gibbérelline, cytokinine) pour créer et tester leurs protéodies. Cependant, ces hormones agissent dans plusieurs voies métaboliques autres que la croissance de la plante donc il peut être compliqué d’observer les effets.


  1. Soudages 

Le soudage du système de diffusion et du haut parleur ont été faits au FabricoLab de Grigny avec l'aide du FabManger Florian Becker ayant réalisé les mêmes systèmes de diffusion qu'utilise l'entreprise Genodics dans son laboratoire expérimental à la MEN de Grigny. 

Grâce au budget accordé par le concours “??” Genodics ont pu acheter 4 petites chambres de cultures pour tester des hypothèses émises suite aux résultats expérimentaux de l'étude sur les petits poids à Cergy.


  1. Code Arduino 

Florian nous a également envoyé le code Arduino du microprocesseur. Pour modifier ce code il faut installer les librairies de diffusions sonores 

#include "Arduino.h"

#include "Audio.h"

#include "SD.h"

#include "FS.h"

et installer la carte ESP32 s3 de xiao dans le board manager avec cet URL https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json


/*

  ESP32 SD I2S Music Player

  esp32-i2s-sd-player.ino


  Plays MP3/WAV file from microSD card

  Uses MAX98357 I2S Amplifier Module

  Uses ESP32-audioI2S Library - https://github.com/schreibfaul1/ESP32-audioI2S


  DroneBot Workshop 2022

  https://dronebotworkshop.com

*/


#include "Arduino.h"

#include "Audio.h"

#include "SD.h"

#include "FS.h"


// microSD Card Reader connections

#define SD_CS         21

#define SPI_MOSI      23

#define SPI_MISO      19

#define SPI_SCK       18


// I2S Connections

#define I2S_DOUT      4

#define I2S_BCLK      5

#define I2S_LRC       6


// Create Audio object

Audio audio;


// Boutons + pot

#define sensorPin A2   // potentiometer input

#define ledPin  D1

#define bouton D3

int sensorValue = 0;

int compteur = 0;


// Temps du morceau

float tempsMorceau = 0; 

float corr = 1.01; // facteur de correction de millis()

long setupTemps = 0;


RTC_DATA_ATTR int bootCount = 0;


// Deep sleep

unsigned long uS_TO_S_FACTOR = 1000000; /* Conversion us -> s */


// --------------------------- Print wakeup reason ---------------------------

void print_wakeup_reason() {

  esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason) {

    case ESP_SLEEP_WAKEUP_EXT0:     Serial.println("Wakeup caused by external signal using RTC_IO"); break;

    case ESP_SLEEP_WAKEUP_EXT1:     Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;

    case ESP_SLEEP_WAKEUP_TIMER:    Serial.println("Wakeup caused by timer"); break;

    case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("Wakeup caused by touchpad"); break;

    case ESP_SLEEP_WAKEUP_ULP:      Serial.println("Wakeup caused by ULP program"); break;

    default:                        Serial.printf("Wakeup not caused by deep sleep: %d\n", wakeup_reason); break;

  }

}


// --------------------------- Setup ---------------------------

void setup() {

    // Pins

    pinMode(SD_CS, OUTPUT);  

    pinMode(bouton, INPUT_PULLUP);

    pinMode(LED_BUILTIN, OUTPUT);  

    digitalWrite(SD_CS, HIGH);


    // SPI

    SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);


    // Serial

    Serial.begin(115200);

    delay(1000);


    // Boot count

    print_wakeup_reason();

    ++bootCount;

    Serial.println("Boot number: " + String(bootCount));

    Serial.println("Reset reason: " + String(esp_reset_reason()));


    // SD

    if(!SD.begin(SD_CS)) {

      Serial.println("Error accessing microSD card!");

      while(true); 

    }


    // I2S

    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);


    setupTemps = millis();

}


// --------------------------- Loop ---------------------------

void loop() {

    // ------------------ Premier boot : coucou.wav ------------------

    if (bootCount == 1) {

        if (compteur == 0){

            // Volume + fichier

            audio.setVolume(20);

            audio.connecttoFS(SD,"coucou.wav");

            Serial.println("coucou.wav opened");


            // Lire en-tête WAV pour durée

            File file = SD.open("/coucou.wav");

            if (file) {

                uint8_t wavHeader[44];

                file.read(wavHeader, 44);


                uint32_t fileSize = *(uint32_t*)&wavHeader[4] + 8;

                uint32_t sampleRate = *(uint32_t*)&wavHeader[24];

                uint16_t numChannels = *(uint16_t*)&wavHeader[22];

                uint16_t bitsPerSample = *(uint16_t*)&wavHeader[34];


                uint32_t dataSize = fileSize - 44;

                tempsMorceau = (float)dataSize / (sampleRate * numChannels * (bitsPerSample / 8));


                Serial.println("==== Infos coucou.wav ====");

                Serial.print("Taille : "); Serial.println(fileSize);

                Serial.print("SampleRate : "); Serial.println(sampleRate);

                Serial.print("Canaux : "); Serial.println(numChannels);

                Serial.print("Bits : "); Serial.println(bitsPerSample);

                Serial.print("Durée estimée : "); Serial.println(tempsMorceau);

                file.close();

            }

            compteur++;

        }


        audio.loop();


        // Attendre fin du morceau + 5 minutes

        if (millis() > tempsMorceau*1000*corr + 5*60*1000) {

            compteur = 0;

            modeVeille(86400); // 24h jusqu'au prochain son01.wav

        }

    }

    // ------------------ Boots suivants : son01.wav ------------------

    else if (bootCount >= 2) {

        if (compteur == 0){

            audio.setVolume(11);

            audio.connecttoFS(SD,"son01.wav");

            Serial.println("son01.wav opened");


            // Lire en-tête WAV

            File file = SD.open("/son01.wav");

            if (file) {

                uint8_t wavHeader[44];

                file.read(wavHeader, 44);


                uint32_t fileSize = *(uint32_t*)&wavHeader[4] + 8;

                uint32_t sampleRate = *(uint32_t*)&wavHeader[24];

                uint16_t numChannels = *(uint16_t*)&wavHeader[22];

                uint16_t bitsPerSample = *(uint16_t*)&wavHeader[34];


                uint32_t dataSize = fileSize - 44;

                tempsMorceau = (float)dataSize / (sampleRate * numChannels * (bitsPerSample / 8));


                Serial.println("==== Infos son01.wav ====");

                Serial.print("Taille : "); Serial.println(fileSize);

                Serial.print("SampleRate : "); Serial.println(sampleRate);

                Serial.print("Canaux : "); Serial.println(numChannels);

                Serial.print("Bits : "); Serial.println(bitsPerSample);

                Serial.print("Durée estimée : "); Serial.println(tempsMorceau);

                file.close();

            }

            compteur++;

        }


        audio.loop();


        // Attendre fin du morceau avant deep sleep 24h

        if (millis() > tempsMorceau*1000*corr){

            compteur = 0;

            modeVeille(86400); // 24h

        }

    }

}


// --------------------------- Deep Sleep ---------------------------

void modeVeille(int TIME_TO_SLEEP){

    esp_sleep_enable_timer_wakeup((uint64_t)TIME_TO_SLEEP * 1000000ULL);

    Serial.println("Going to sleep for " + String(TIME_TO_SLEEP) + " seconds");

    Serial.flush();

    delay(100);

    esp_deep_sleep_start();

}


Ce code est la propriété de l'entreprise Genodics


Fonctionnement général :

Le micro contrôleur ESP32 devient un lecteur audio autonome. Dès que le boîtier est branché, le haut parleur dans la chambre de culture émet le son “coucou”, un bruit d'oiseau, permettant de contrôler que tout est fonctionnel. Après 5 minutes, il joue le fichier “son01” qui contient la protéodie de 40 secondes jouée pendant 5 minutes et se met en veille. Il se rallume 24 heures après pour rejouer chaque jour là protéodie. 


Paramètres de code :

Le code commence par définir quelles broches servent pour lire la carte SD où sont stockés les fichiers audio, et quelles broches servent à envoyer les informations sonores à la l'amplificateur pour avoir un son audible sur le haut parleur de 5 ohms. La variable bootCount permet de donner un ordre. Le code distingue deux cas : la valeur 1 (au premier démarrage) joue le son coucou et la valeur 2 joue le son01 qui est la protéodie (à la fin de la diffusion de coucou puis chaque 24 heures). Les “time set” sont exprimées en secondes.


Pendant que le son joue, le programme vérifie en permanence combien de temps s’est écoulé grâce à une fonction qui lit le temps depuis le démarrage. Une fois que le son est terminé et que cinq minutes se sont écoulées, le code déclenche le deep sleep, c’est-à-dire que l’ESP32 se met en veille totale pour économiser de l’énergie, et il programmera de se réveiller automatiquement 24 heures plus tard. Pour tous les démarrages suivants (bootCount ≥ 2), le code ouvre le fichier son01.wav, lit sa durée de la même manière et le joue entièrement. Une fois le morceau terminé, il se remet en veille pour 24 heures, et ainsi de suite, tous les jours.

Pendant la lecture du son, une fonction appelée audio.loop() s’assure que les données audio arrivent correctement au petit amplificateur, ce qui permet au son d’être continu et fluide. Le code utilise également des petits calculs pour ajuster la durée réelle du son et compenser de petites imprécisions dans le temps de l’ESP32. Enfin, la fonction modeVeille() est responsable de mettre la carte en sommeil profond et de définir combien de temps elle doit rester en veille avant de se réveiller automatiquement. Ainsi, le boîtier peut fonctionner toute une année avec un minimum d’énergie, en jouant un son chaque jour sans intervention humaine.


En résumé, ce code Arduino transféré par câble USB dans le micro contrôleur permet  la lecture de deux fichiers audios “coucou” et “son01” au format”.wav” d'une carte SD. L'amplificateur rouge permet de gérer les paramètres sonores et de garder en mémoire combien de fois l’appareil a été utilisé tout en mettant en veille le dispositif une fois la diffusion journalière de 5 minutes terminée. Tout cela se fait automatiquement dès que l'on branche le boîtier au secteur et la carte SD.


  1. Modèle 3D pour protéger le système de diffusion 

Les boitiers pour protéger le micro contrôleur et le haut parleur ont également été envoyé par Florian et imprimés à la Sorbonne sur les imprimantes Prusa MK4S


  1. Modèle 3D des Godets

Pour avoir nos propres godets sur-mesure et solidaires, nous avons choisi de les imprimer en 3D.

Les dimensions d'une grille de la chambre de culture sont de 55*54*7cm. Un pot plastique pour faire germer des graines est traditionnellement de taille 6*6*6cm.

Les imprimantes 3D disponibles au FabLab prototypage sont des Raise3D Pro2 et des Prusa MK4S avec un plateau de 30*30cm. Nous choisissons d'utiliser les Prusa car elles sont plus rapides et bien plus fiables. Il faudra imprimer plusieurs morceaux pour ne pas dépasser du plateau d'impression.

Pour répondre à ces différents critères de taille, le plus simple a été d’imprimer quatres morceaux cubiques de 4*4 godets chacun. Un godet a pour dimensions 5*5*6cm avec des parois séparatrices de 1,2mm et un fond de 2,4mm. Ces parois pleines sont assez rigides pour résister aux contraintes exercées par la vermiculite humide.

Il y a donc au total 64 godets en réunissant les quatres quarts pour chaque semaine de germination.


Code du modèle 3D

À l'aide de Gemini nous avons codé sur OpenSCAD le modèle 3D pour un quart de plaque. Ce modèle a été exporté au format STL. Nous avons ajouté cinq petits trous au fond des godets pour mieux répartir l’humidité tout en permettant un apport maximum d'oxygène aux racines.


// --- PARAMÈTRES GÉOMÉTRIQUES ---

$fn = 60; // résolution des trous

nb_X = 4; 

nb_Y = 4;

cote_interieur = 55.0; // 5.5cm x 5.5cm

ep_mur = 1.2;           // équivalent à 3 passages de buse de 0.4mm

ep_fond = 2.4;         // Fond robuste pour supporter la vermiculite humide 

h_utile = 60.0;        // 6cm de profondeur

d_trou_fond = 3;   // diamètre des trous de drainage


// --- CALCULS DE STRUCTURE ---

largeur_totale = (nb_X * cote_interieur) + ((nb_X + 1) * ep_mur);

longueur_totale = (nb_Y * cote_interieur) + ((nb_Y + 1) * ep_mur);

hauteur_totale = h_utile + ep_fond;


// --- CONSTRUCTION ---

difference() {

    // Bloc plein principal

    cube([largeur_totale, longueur_totale, hauteur_totale]);


    for (x = [0 : nb_X - 1]) {

        for (y = [0 : nb_Y - 1]) {

            // Positionnement précis de chaque godet

            px = ep_mur + x * (cote_interieur + ep_mur);

            py = ep_mur + y * (cote_interieur + ep_mur);


            // Évidement du godet

            translate([px, py, ep_fond])

                cube([cote_interieur, cote_interieur, h_utile + 1]);


            // 5 Trous au fond pour le drainage

            translate([px + cote_interieur*0.25, py + cote_interieur*0.25, -1])

                cylinder(h=ep_fond+2, d=d_trou_fond);

            translate([px + cote_interieur*0.5, py + cote_interieur*0.5, -1])

                cylinder(h=ep_fond+2, d=d_trou_fond);

            translate([px + cote_interieur*0.75, py + cote_interieur*0.75, -1])

                cylinder(h=ep_fond+2, d=d_trou_fond);

            

            }

        }

    }

}


Pour le premier prototype nous avons renseigné nbX=1 et nbY=1 pour imprimer 1 godet test.


Les raccourcis F5 permettent de prévisualisation du modèle, F6 permet d'avoir le rendu avec calcul des arrondis et enfin F7 pour exprimer le code en format STL compatible avec un slicer.


  1. Prusa slicer

Le modèle doit ensuite être envoyé dans le “slicer” compatible avec l’imprimante utilisée, le prusa slicer dans notre cas. Ce logiciel permet de spécifier tous les réglages que l'imprimante doit utiliser lors de l'impression.

De ce que nous avons compris :

sachant que la buse de l'imprimante fait 0,4mm il faut renseigner 3 dans “périmètres” pour que les parois de 1,2mm soient pleines. L'imprimante passera 3 largeur de buse.

Pour le fond de 2,4mm avec 3 périmètres il reste 1mm vide qui est comblé par le “remplissage” choisi a 20% et en mode “Gyroid” qui crée des nervures aléatoires pour solidifier sans combler totalement le vide.


Vient ensuite le choix crucial des vitesses d'impression. Il faut choisir le bon compromis entre une impression rapide, solide, nette et sans effondrement selon l'objet imprimé et les caractéristiques de l'imprimante. La Prusa est optimisée pour être précise malgré les vibrations engendrées par la vitesse. Nous avons donc choisi ??? 

100 périmètres, 80 périmètres externes …

Nous avons aussi diminué l'accélération de déplacement de 4000 à 2000mm/s^2 pour ne pas q


Enfin le troisième type de réglage important est la température d'impression qui dépend surtout du type de filaments utilisé. Le filament basique est le PLA, bioplastique issu d'amidon de maïs ou de canne à sucre. Il est poreux et rigide, parfois cassant et déformable au-dessus de 50 degrés celsius. Il y a ensuite le PLA+ plus solide et étanche grâce à des additifs (élastomères ou minéraux) c'est celui ci que nous avons choisi pour maximiser les chances de réussite de l'impression.

Il faut vérifier que les paramètres de température par défaut sont bien à 60 degrés pour le plateau et 220 degrés pour la base afin que le PLA+ ne soit ni trop solide ni trop liquide lors de l'impression et qu'il ne crée pas trop de tension quand il refroidit..


  1. Impression 

Pour débuter l'impression, il faut exporter le modèle avec ses paramètres d'impression au format bgcode puis mettre le fichier dans une clé USB et la brancher à l'imprimante.

Enfin, il faut lancer le préchauffage de l'imprimante puis sélectionner le bgcode de la clé avec la molette ou l'écran tactile. 

Pour un tel objet d'une durée d'impression autour de 20 heures, il est nécessaire de contrôler la première heure d'impression pour s'assurer que les couches de la base soient bien imprimées et collées au plateau sinon la suite de l'impression sera forcément un échec. 


La moitié du temps correspond au remplissage des parois externes pleines. Chaque quart consomme autour de 250g de PLA+