Deutsch English Español Français Italiano

CELLULE DE VIE : ECLAIRAGE CIRCADIEN

Pour valider le Clinostat nous allons utiliser des cultures de Ver de Roscoff.

Beaucoup d'organismes comme S. Roscoffensis sont sensibles à la lumière.

Nous avons développé un système d'éclairage embarqué permettant de simuler le rythme circadien. La durée du jour et l'intensité lumineuse dépendent de la latitude du lieu, du jour de l'année et de l'heure. Ce système comprend une carte Arduino, un circuit imprimé d'interface avec les bandes de LEDs RGBW et UV.

EVOLUTION DE LA LUMIERE DU JOUR

La luminosité journalière est évaluable par les équations suivantes :

Equations luminosité journalière

Voici le code Arduino correspondant :

#include <math.h>
// Eclairage de milieu de culture d'organisme vivant conforme à la course journalière du soleil  : CHRONOSLIGHT - Lite  1.0 
// Auteurs : Jean-Philippe BLANCHARD & Xavier BAILLY pour le laboratoire M3 CNRS Université Sorbonne - Station Biologique de Roscoff
// Licence : Open Source GPL 

void setup() {
  Serial.begin(9600);
  // ****************** Phase d'initialisation des parametres *****************
  // coordonnées du lieu en radians
  float latitude = 0.8501848 ;
  float longitude = -0.0699004 ;
  
  // Durée de la simulation jours
  int dureeSimul = 90;
  // jourde Débutde Simulation 
  int jourDebutSimul = 171;
  //heure de démarrage en fraction de 24h (midi = 0.5)
  float startSimul = 12.00/24;

  // Parametrage des LEDs par rapport à leur intensité maximale : Red, Green,Blue, White, UltraViolet 
  int redLED = 1 ;
  int greenLED = 1 ;
  int blueLED = 1 ;
  int whiteLED = 1 ;
  int uvLED = 1 ;
  // Affectation des LEDs aux Pins de l'arduino 
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);

  //inclinaison du capteur, par exemple la plage (on va la supposer horizontale) et son altitude z = 0
  float oCapteur = 0;
  float iCapteur = 0;
  float zCapteur = 0;
  // Pression atmosphérique au niveau de la mer (Pa)
  long pression = 101325 ;
  // Coefficient de trouble atmosphérique du lieu (0.02 montagne / 0.05 rural / 0.1 urbain / 0.2 industrie) 
  float coeffTroubleAtmos = 0.05;

  // Modèle simplifie : temperature et humidite relative constante
  float temperature = 4.5;
  float humidite = 0.87 ;

// initialisation 
  int jourCourant = jourDebutSimul -1;
  float heureCourante = startSimul ;
  float deltaTime = millis();

  float lux =0.0;
  int maxJour = 171;
 float rdir = rayDirectJour(maxJour,0.5,pression,latitude,temperature,humidite,coeffTroubleAtmos,longitude);
 float rdif = rayDiffusJour(maxJour,0.5,iCapteur,latitude,longitude);
 float ci = coeffIncidence(oCapteur,iCapteur,hauteurSol(maxJour,0.5,latitude,longitude),azimutSol(maxJour,0.5,latitude,longitude));
 //Serial.println("**********  direct/diffus :"+String(rdir)+"/"+String(rdif)+ "coeff incidence :"+String(ci));
  int maxLux = rdif+rdir*ci;
  Serial.println("**********  maxLux :"+String(maxLux));
// boucle journalière
  for (int j = 1 ; j<=dureeSimul ; j++)
  { jourCourant++ ;
  
    while (heureCourante <1) {
      // pour traiter l'overflow de millis au bout d'une cinquantaine de jours on remet à 0 deltaTime lorsque cela se produit
      if (deltaTime> millis()) {deltaTime=0;}
      heureCourante =heureCourante+(millis()-deltaTime)/86400000;
      deltaTime=millis();
      Serial.println("leverJour :"+String(leverJour(jourCourant,latitude))+" coucherJour :"+String(coucherJour(jourCourant,latitude)));
      Serial.println(((heureCourante>leverJour(jourCourant,latitude)) && (heureCourante < coucherJour(jourCourant,latitude))));
      if ((heureCourante>leverJour(jourCourant,latitude)) && (heureCourante < coucherJour(jourCourant,latitude)))
      {
        Serial.println("################");
        rdir = rayDirectJour(jourCourant,heureCourante,pression,latitude,temperature,humidite,coeffTroubleAtmos,longitude);
        rdif = rayDiffusJour(jourCourant,heureCourante,iCapteur,latitude,longitude);
        ci = coeffIncidence(oCapteur,iCapteur,hauteurSol(jourCourant,heureCourante,latitude,longitude),azimutSol(jourCourant,heureCourante,latitude,longitude));
        Serial.println("**********  direct/diffus :"+String(rdir)+"/"+String(rdif)+ "coeff incidence :"+String(ci));
        float lux = 255*(rdif+rdir*ci)/maxLux;
        Serial.println(lux);
        fiatLux(redLED, greenLED, blueLED,  whiteLED,uvLED, lux);
      }
      else
      {
        fiatLux(redLED, greenLED, blueLED,  whiteLED, uvLED,0);
      }
    Serial.println("jourCourant : "+String(jourCourant)+" heureCourante :"+String(heureCourante)); 
    delay(30000); 
    }
  }

  heureCourante = 0.0; 
}


// **************** programme principal *************************
void loop() 
{
 
}


// *************************  Déclaration des sous-programmes ***************************************
// ******************* fonction Fiatlux ********************

void fiatLux(float r,float g, float b, float w, float u,float lux)
{
        int lum ;
        analogWrite(8, min(255,floor(r*lux)));
        analogWrite(9, min(255,floor(g*lux)));
        analogWrite(10, min(255,floor(b*lux)));
        analogWrite(11, min(255,floor(w*lux)));
        analogWrite(12, min(255,floor(u*lux)));
        Serial.println("%%%% lux :"+String(lux));
    return ;
}
// ************** fonctions astronomiques *************
// Equation du temps en minutes
float equationTemps (int j)

    float annee = 365.242;
    float p1 = 7.363710322;
    float p2 = -0.071081264;
    float p3 = 9.91730258;
    double p4 = 0.356852721;
    float p5 = 0.304565355;
    float p6 = 0.256165383;
    float e = p1*sin(p2+2*PI*j/annee)+p3*sin(p4+4*PI*j/annee)+p5*sin(p6+6*PI*j/annee);
    // Serial.println("equation temps :"+String(e/1440));
    return e;
}

// Déclinaison en degres
float declinaisonSol(int j)
{
  float k=PI*j/365.24 ;
  float d=0.38+23.26*sin(2*k-1.395)+0.375*sin(4*k-1.47);
  // Serial.println("jour :"+String(j)+"declinaison :"+String(d));
  return d ;
}

// temps solaire en fraction de 24h
float tempsSolaireVrai(int j,float h,float lo)
{
  float t = h+ (equationTemps(j)+4*degrees(lo))/(24*60);
  // Serial.println("temps solaire vrai :"+String(t));
  return t ;
}

// angle horaire en degres
float angleHoraire(int j,float h, float lo)
{
  float a = 24*(tempsSolaireVrai(j,h,lo)-0.5);
  // Serial.println("angle horaire :"+String(a));
  return a;
}

//Hauteur solaire en degrees
double hauteurSol(int j,float h, float l, float lo)
{
    float dec = radians(declinaisonSol(j));
    float ah = radians (angleHoraire(j,h,lo));
    float hs = max(0,degrees(asin(sin(dec)*sin(l)+cos(dec)*cos(l)*cos(ah))));
    //Serial.println("hauteur solaire :"+String(hs));
    return hs;
}

   // azimut solaire en degrees
float  azimutSol(int j,float h, float l,float lo)
{
    float dec = radians(declinaisonSol(j));
    float hs = radians (hauteurSol(j,h,l,lo));
    float ah = radians (angleHoraire(j,h,l));
    float a = degrees(cos(dec)*sin(ah)/cos(hs)); 
    //Serial.println("azimut solaire :"+String(a));
    return  a; 
}

// durée du jour en heure
float dureeJour(int j, float l)
{
    float d =(24/PI)*acos(-tan(radians(declinaisonSol(j)))*tan(l));
    //Serial.println("durée du jour :"+String(d));
    return d;
}

// lever du soleil en heure en fraction de 24h
float leverJour(int j, float l)
{
    return 0.5-dureeJour(j,l)/48 ;
}

// coucher du soleil
float  coucherJour(int j,float l)
{
  return 0.5+dureeJour(j,l)/48 ;
}

// ****************** Fonctions rayonnement solaire ************
// Calcul énergie solaire à partir de la constante solaire et du jour j en Watt/m2 ou Joules/m2
float energieSol(int j)
{
    int cteSol = 1367 ;
    float c = cteSol*(1-0.034*sin(2*PI*(j-94)/365));
    //Serial.println("constante solaire :"+String(c));
    return c;
}
    
// Pression atmospherique en Pa
double pressionAtmo(int p0,int z)
{
    return p0*pow(1-2.26*z/100000,5.26);
}
    
// Pression saturante 
float pressionVapeurSaturante(float t)
{
    return 2.165*pow((1.098+t/100),8.02);
}
    
// pression partielle de vapeur d'eau

float pressionPartielleVapeurEau(float pvs,float hr)
 {
    return pvs*hr ;
 }
    
//épaisseur de Rayleigh
float epaisRayleigh(float m)
{
    return 1/(0.9*m+9.4);
}
  
// coefficient de trouble de Linke
float coeffTroubleLinke(float pv,float tr)
{
  return 2.4+14.6*tr+0.4*(1+2*tr)*log(pv);
}
    
// masse optique relative d'air traversé
float masseOptiqueAir(long p,float hs)
{
    float hh = radians(hs);
    return p/(101325*sin(hh)+15198.75*pow(3.885+hs,-1.253));
}

// Rayonnement global 
float rayGlobal (float rdir,float rdif,float ci)
{
    return rdif+rdir*ci;
}

// coefficient d'incidence du plan du récepteur
float coeffIncidence(float o,float i,float hs,float az)
{
    float oo = radians(o);
    float ii = radians(i);
    float hh = radians(hs);
    float aa = radians(az);
    float ci=sin(ii)*cos(hh)*cos(oo-aa)+cos(ii)*sin(hh);
    //Serial.println(String(o)+String(i)+String(hs)+String(az)+"coeff incidence"+ci);
    return ci;
}

// Rayonnement direct au jour j et heure h
float rayDirectJour(int j,float h, long p, float l, float t,float th, float ct,float lo)

    float es = energieSol(j);
    float mo = masseOptiqueAir(p,hauteurSol(j,h,l,lo));
    float er = epaisRayleigh(mo);
    float tl = coeffTroubleLinke(pressionPartielleVapeurEau(pressionVapeurSaturante(t),th),ct);
    //Serial.println("energie sol :"+String(es)+" masse optique :"+String(mo)+"epaisseur :"+String(er)+" trouble :"+String(tl));
    return es*exp(-er*mo*tl);
}

// Rayonnement diffus 
float rayDiffusJour(int j,float h,float i,float l, float lo)
{
    float hh = radians(hauteurSol(j,h,l,lo));
    float ii = radians(i);
    return 125*pow(sin(hh),0.4)+0.5*(1-cos(ii))+211.86*pow(sin(hh),1.22)*0.5*(1-cos(ii));
}

CONCEPTION DU CIRCUIT IMPRIME

le principe consiste à piloter chaque type de LED en y appriquant une tension variable générée par l'application d'une valeur digitale comprise entre [0,255] à partir d'une pin Digital de l'Arduino sur la gate d'un amplificateur opérationnel type IFR540.

Afin de limiter le scintillement des LEDs aux tensions basses on rajoute un condensateur de 2200µF.

Vous pouvez télécharger le typon pour l'imprimer à l'échelle ci-dessous :

Typon

FABRICATION DU CIRCUIT IMPRIME

Il vous faut une imprimante laser.

Petit matériel :

  • 1 Plaque de circuit imprimé cuivré recto
  • 1 feuille de papier glacé spécial transfert
  • 1 flacon de Chlorure ferrique
  • 1 flacon d'etain liquide
  • 1 flacon d'alcool à bruler
  • 1 flacon d'acétone
  • 1 mini meuleuse avec son disque pour découpe
  • 1 éponge grattante
  • 1 plat en verre de taille suffisante pour accueillir le circuit
  • 1 rouleau de papier absorbant
  • 1 paire de gants de ménage
  • 1 fer à repasser

Etape 1 : impression du typon

  1. Ouvrir le fichier TYPON.pdf. Comme vous pouver le constater c'est une image miroir à cause du mécanisme de transfert de la feuille de papier vers la plaque de cuivre.
  2. Introduire la feuille de papier glacé face brillante vers les rouleaux d'impression.
  3. Régler l'impression "sur papier glacé" et avec la définition maximale (par exemple 2400 points par pouce).
  4. Imprimer la feuille et découper soigneusement le dessin.

Etape 2 : préparation de la plaque de cuivre.

  1. Reporter les dimension de ce découpage sur la plaque en cuivre.
  2. Découper à l'aide de la mini meuleuse.
  3. Dépolir le cuivre avec l'éponge grattante
  4. Nettoyer la surface avec de l'alcool a brûler et une feuille de papier absorbant et renouveler tant
  5. que ce n'est pas propre.
  6. Laisser sécher.

Etape 3 : transfert de l'image

  1. Faire chauffer le fer à température maximale (Coton). Ne pas utiliser de vapeur !
  2. Poser le typon face imprimée contre la plaque de cuivre
  3. Appliquer le fer sur toute la surface de la plaque pendant quelques minutes en remuant très doucement pour ne pas risquer de déplacer la feuille. Bien insister sur les bords. L'opération dure environ 5 minutes. Eviter que la feuille brunisse.
  4. Laisser reposer la plaque en cuivre jusqu'à ce que sa température soit celle de l'air ambiant
  5. Retirer très soigneusement la feuille de papier glacé. Si au cours de cette opération vous voyez une zone d'impression qui ne se transfère pas il est parfois possible en rabattant la feuille et en repassant un coup de fer de récupérer l'erreur, mais il faut impérativement que la feuille retrouve sa position initiale.
  6. Si l'impression est ratée on peut récupérer la plaque de cuivre en nettoyant l'impression avec de l'acétone puis en reprenant l'étape 2 phase 3

Etape 4 : Gravure

  • Mettre une paire de lunette protectrice et de gants
  • Verser du chlorure ferrique dans le récipient en verre.
  • Plonger la plaque de cuivre et remuer quelques instants pour qu'elle soit bien couverte
  • Pendant une demi-heure (ou plus) remuer régulièrement toutes les 10 minutes et vérifier le degré de dissolution du cuivre. Comme le liquide devient turbide, vous pouvez sortir de temps en temps la plaque et la rincer à l'eau pour voir où en est le processus.
  • Quand tout le cuivre a disparu rincer soigneusement et essuyer au papier absorbant

Etape 5 : Finition

  1. Nettoyer l'impression avec de l'acétone et un papier absorbant.
  2. Nettoyer le récipient en verre et y verser de l'étain liquide
  3. Plonger la plaque dans le bain, la couleur du cuivre disparait au profit de l'étain.
  4. Rincer la plaque.

PERCAGE DU CIRCUIT IMPRIME

Matériel 

1 foret de 1mm

1 mini colonne de perçage

L'usage d'une colonne de perçage n'est pas obligatoire mais très recommandée !

 

Exemple de mise en oeuvre

La première mise en oeuvre a eu lieu à Roscoff avec

  • des bandes LEDs BFT 12Volts, 60 LEDS/m modèle de LEDs 5050 qui ont la particularité dans chaque composant de disposer de trois couleurs (Rouge Vert et Bleu et de la couleur Blanc froid) 
  • des bandes UV avec la même densité de LEDs /m

toutes ces couleurs pouvant être pilotées indépendemment les unes des autres.

Sur la photo suivante on voit le montage réalisé sur plaque de plexiglass se disposant comme une étagère dans une enceinte thermostatée du laboratoire M3 de la Station biologique de Roscoff. Dans les coupelles sont disposer des petites colonies du Ver de Roscoff.

Ci dessous la version prototype wrappée du circuit électronique :

 

 

 

 

 

haut