[PROG] gestion éclairage et chauffage aquarium

Bonjour à tous et merci à tous ceux qui m'ont aidé pour la programmation de mon Arduino destiné à la gestion de l'éclairage et du chauffage de mon aquarium.
Le but du programme est de créer un allumage et une extinction progressive de ma rampe Leds fabrication maison.

Alors tout d'abord il s'agit d'un bac de 250 litre mesurant 1m10 x 0m45 x 0m50.
C'est un bac destiné à accueillir des cichlidés du lac malawi.
Il n'y a aucune plante, juste un décor à base de bloc de granit d'où l'absence de LEDs bleu et rouge.

Je suis parti sur des LEDs 10mm - 100mA.
Il y a donc 58 LEDs blanches et 18 LEDs blanches chaudes, toutes groupées par trois avec une résistance de 22 Ohm en série.
Il y a également un éclairage lunaire composé de 12 LEDs bleues de 5mm - 20mA également groupées par trois mais avec une résistance en série de 100 Ohm.
Le tout est alimenté en 12 Volts par une alimentation de PC.

Je vous mets juste deux photos de la construction de la rampe car le sujet n'est pas celui là et qu'il y a autant de rampe que de bricoleurs.

Voici les caractéristiques du montage :

  1. allumage et extinction automatique du chauffage sur la plage 24 - 26 °C (possibilité de forcer l'allumage avec un switch)
  2. Rampe à LEDs Jour avec possibilité d'allumage manuel avec un switch à n'importe quelle heure (pour nettoyage par exemple)
  • allumage progressif de la rampe LED de 15h00 à 16h00
  • allumage max de 16h00 à 20h00
  • extinction progressive de 20h00 à 21h00
  1. Rampe à LEDs Lunaire
  • allumage à 20h15
  • extinction à 23h00
  1. Afficheur LCD 2 lignes / 16 caractères : allumage du rétro-éclairage avec un switch
  • affichage heure
  • affichage température
  • affichage de l'état du chauffage ( ON - OFF )

L'allumage et l'extinction progressif utilisent une des sorties PWM de l'Arduino et un Mosfet à choisir en fonction de la puissance de la rampe à commander.
La rampe lunaire utilise un relais commander par un ULN2803. Il s'agit d'un octuple driver d'amplification de puissance ON/OFF : donc 8 relais possible.
J'aurais très bien pu utiliser un autre mosfet pour la rampe lunaire à la place du relais.
Par contre je n'aurais pas pu utiliser un relais pour la rampe jour car avec un relais c'est tout ou rien donc pas de progressif.

Voilà la liste des composants utilisés :

1 arduino Duemilanove
1 mini carte DS1307
1 capteur de température LM35
1 écran LCD de 2 lignes et 16 caractères
1 ULN2803 (pour commander les relais)
2 diodes 1N4007
1 résistance 10KOhm
1 mosfet (j'ai pris un BUZ11)
2 relais 12V dont un supportant le 230V en sortie pour le chauffage
des connecteurs (j'ai pris des prises XLR que j'avais en stock)
des interrupteurs
du câbles de différentes sections

Toutes les cartes et l'alimentation dans le coffret

Vu des connecteurs et de l'écran sur la face externe du boitier

Et voici le programme

#include <Time.h>
#include <LiquidCrystal.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

/*
Arduino Masterbalby Controller
 Analog Pin 0 = Température Sensor
 Analog Pin 4 = SDA pour ds1307
 Analog Pin 5 = SCL pour ds1307
 Digital Pin 2 = LCD
 Digital Pin 3 = LCD
 Digital Pin 4 = LCD
 Digital Pin 5 = LCD
 Digital Pin 6 = LCD
 Digital Pin 7 = LCD
 8 = chauffage
 10 = moon_light
 Digital Pin 11 = PWM day_light
 Digital Pin 16 = Bouton poussoir 1 day light
 Digital Pin 15 = Bouton poussoir 2 chauffage
 */

//LiquidCrystal lcd(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int sensorPin = 0;
int chauffage = 8;
int moon_light = 10;
int pwm = 11;
int heater_on_temp = 24;  //allume chauffage à cette température
int heater_off_temp = 26; //éteint le chauffage à cette température
int moon_on_time = 2015;  //allume les  moon lights à cette heure (en temps_perso)
int moon_off_time = 2300;  //éteint les moon lights à cette heure (en temps_perso)
int minut;
int heure; 
int seconde;
int date;
int mois;
int annee; 
int temps_perso;
int BP1=16; //interrupteur Day_light 
int BP2=15; //interrupteur Chauffage

void setup() {
/*  RTC.stop();
  RTC.set(DS1307_SEC,00);        //réglage secondes
  RTC.set(DS1307_MIN,59);        //réglage minutes
  RTC.set(DS1307_HR,15);         //réglage heures
  RTC.set(DS1307_DOW,6);         //réglage jour de la semaine
  RTC.set(DS1307_DATE,11);       //réglage date
  RTC.set(DS1307_MTH,12);         //réglage mois
  RTC.set(DS1307_YR,10);          //réglage année
  RTC.start();
*/
  lcd.begin(16, 2);
  delay(10);
  pinMode(chauffage, OUTPUT);  // digital pin pour chauffage en sortie
  pinMode(moon_light, OUTPUT);  // digital pin pour moon light en sortie
  lcd.print("MasterBalby 2.1");
  lcd.setCursor(0, 1) ;
  lcd.print("Gestion Aqua");
  delay(4000);
  lcd.clear();
  delay(10);
  pinMode(BP1, INPUT); //met la broche en entree 
  digitalWrite(BP1, HIGH) ; // activation du pullup de la broche en entrée
  pinMode(BP2, INPUT); //met la broche en entree 
  digitalWrite(BP2, HIGH) ; // activation du pullup de la broche en entrée
}

void loop(){

  //Récupérer l'heure du DS1307**********************************************************************************************

  heure = RTC.get(DS1307_HR,true);  
  minut = RTC.get(DS1307_MIN,false);
  seconde = RTC.get(DS1307_SEC,false);
  date = RTC.get(DS1307_DATE,false);
  mois = RTC.get(DS1307_MTH,false);
  annee = RTC.get(DS1307_YR,false);
  temps_perso = (heure * 100) + minut;  //creation temps_perso

  //Récupérer la température du LM35 ***************************************************************************************

  int reading = analogRead(sensorPin);  
  float voltage = reading * 5.0 / 1024; 
  int temp = voltage * 100 ; 

  //Affichage température*****************************************************************************

  lcd.setCursor(6,0);
  lcd.print("Temp : ");
  delay(10);
  lcd.print(temp); 
  lcd.println("C");  

  //Affichage heure******************************************************************************************

  lcd.setCursor(0,0);
  if (heure < 10)
  {
    lcd.print("0");
  } 
  lcd.print(RTC.get(DS1307_HR,true)); 
  lcd.print("H");
  if (minut < 10)
  {
    lcd.print("0");
  }
  lcd.print(RTC.get(DS1307_MIN,false));
  lcd.print(" ");
  delay(1000);

  //Controles des sorties ***************************************************************************************

  //****************Chauffage

  if((temp < heater_on_temp) || (digitalRead(BP2)==LOW)) {     
    digitalWrite(chauffage, HIGH);
  }  
  else if (temp > heater_off_temp)
  {  
    digitalWrite(chauffage, LOW);
  }

  //****************Day Lights**********************************************************************************

  if (heure == 15) { // entre 15:00 et 15:59:59
    analogWrite (pwm, (1 << map (minute() * 60 + second(), 0, 3600, 0, 10)) -1); // allumage progressif exponentiel
//    analogWrite (pwm, map (minute() * 60 + second(), 0, 3600, 0, 1024));  // allumage progressif linéaire
  }
  else if (heure == 20) { // entre 20:00 et 20:59:59
    analogWrite (pwm, (1 << map (minute() * 60 + second(), 0, 3600, 10, 0)) -1); // extinction progressif exponentiel
//    analogWrite (pwm, map (minute() * 60 + second(), 0, 3600, 1024, 0));  // extinction progressif linéaire
  }   
  else if ((heure > 15 ) && (heure < 20)) {
    analogWrite(pwm, 255);
  }
  else if (((heure > 0  && heure < 15)) && (digitalRead(BP1)==LOW)) {
    analogWrite(pwm, 255);  
  }
  else if (((heure > 20  && heure < 24)) && (digitalRead(BP1)==LOW)) {
    analogWrite(pwm, 255);  
  }
  else if ((heure == 0) && (digitalRead(BP1)==LOW)) {
    analogWrite(pwm, 255);  
  }
  else if (((heure > 0  && heure < 15)) && (digitalRead(BP1)==HIGH)) {
    analogWrite(pwm, 0);  
  }
  else if (((heure > 20  && heure < 24)) && (digitalRead(BP1)==HIGH)) {
    analogWrite(pwm, 0);  
  }
  else if ((heure == 0) && (digitalRead(BP1)==HIGH)) {
    analogWrite(pwm, 0);  
  }

  //****************Moon Lights****************************************************************************

  if(moon_on_time > temps_perso  || moon_off_time <= temps_perso){
    digitalWrite(moon_light, LOW);
  }
  else{
    digitalWrite(moon_light, HIGH);
  }

  //Affichage chauffage allumé********************************************************

  lcd.setCursor(0,1);
  if(digitalRead(chauffage) == HIGH)
  {
    lcd.println("Chauffage ON    ");
  }
  else
  {
    lcd.println("Chauffage OFF   ");
  }
}

Si vous avez des commentaires n'hésitez surtout pas...

En fin de compte, quelle était la raison d'utiliser l'allumage exponentiel et non linéaire?

Et la seconde question, as-tu un cite avec des images du reste de la construction et - si tout est terminé - avec les bestioles?

Korman

pour l'allumage exponentiel je trouve l'allumage plus progressif.

Je n'ai pas encore mis toutes mes photos sur un site, il y en a sur trois site différents.
Voila les liens :
~~Aquaohm :: Montage électronique pour gestion allumage , extinction, chauffage
~~Aquaohm :: Eclairage Malawi 250L brut sans plante
~~Et un 250L de plus avec éclairage LEDS

L'aquarium n'est pas encore en eau.
Je pense le faire cette semaine.
Après il faut attendre un bon mois pour que le pic des nitrates soit passé et après enfin l'introduction des poissons.

[EDIT]
je viens de créer un blog ou tout est recensé.
Voici le lien

[EDIT]

J'ai besoin une fois de plus de votre aide.
Je viens de trouver un problème dans mon montage qui n'existait pas en phase de test.

Il s'agit d'un problème avec l'allumage progressif de ma rampe.

Voila les symptômes.

Lors de l'enclenchement de l'allumage progressif l'affichage de l'heure sur l'écran affiche la bonne heure puis quelques secondes plus tard une heure éronnée.

La rampe Leds s'éteint puis se rallume constamment.
De plus la rampe n'atteint jamais son éclaraige max.

Ce problème n'est jamais arrivé en phase de test avec uniquement trois Leds de 20mA.

Par contre lors de la deuxième phase d'éclairage , c'est à dire éclairage max sur une période de 4 heures, il n'y a pas de problème avec le LCD ou avec la rampe.

Pour faire des essais j'ai diminué de moitié la quantité de leds sur ma rampe.
Là le problème ne se pose pas.

Je pense donc que le problème est plus matériel que logiciel.

Mais quoi ??

L'alimentation ??? je ne pense pas car lors de la période d'eclairage max il n'y a pas de problème.

Peut-être le Mosfet utilisé. Ici un BUZ11 .
D'après son datashheet il peut dissiper 90Watts. Or mon montage ne dépasse pas les 40 Watts.

Un problème avec le code utilisé ??
Je ne pense pas non plus.

Faut-il changer de Mosfet ??

Merci pour votre aide.

Je viens de vérifier, le phénomène est identique en phase d'extinction progressive.

Pour résumer :

ça sa fonctionne

analogWrite(pwm, 255);

ça sa ne fonctionne pas

analogWrite (pwm, (1 << map (minute() * 60 + second(), 0, 3600, 0, 10)) -1);

et sa non plus

analogWrite (pwm, map (minute() * 60 + second(), 0, 3600, 0, 1024));

Question intéressant est si analogWrite(pwn, 32) ou similaire fonctionne.

Korman

j'y ai pensé cette nuit aussi.
je testerai ce soir

alors voici les résultats des tests.
toutes les valeurs de 1 à 254 posent le même problème.

Je pense que ça doit venir du mosfet qui n'arrive pas à analyser les données PWM envoyées par l'arduino.
Il doit comprendre le min 0 et le max 255 pas les valeurs intermédiaires.

C'est pourquoi je vais changer de mosfet...
J'espère que c'est ça

Le mosfet ...
C'est peut être l'étage de commande du mosfet, peux tu mettre le schéma.

A+ Teiva


www.Zartronic.fr : Votre source Arduino en France

voila le schéma demandé
pour précision je n'utilise pas le deuxième mosfet

[/URL]

Me voila de retour

j'ai résolu mon problème en rajoutant un mosfet cablé de la même façon que le premier.
J'ai donc un mosfet par demi rampe.

Et là je n'ai plus de problème.
Je peux allumer progressivement les deux rampes en même temps et tout fonctionne.

Je pense donc à un mauvais choix au niveau du mosfet.

J'ai aussi un peu modifié le programme pour que cela fonctionne.
J'ai rajouté une sortie PWM.
J'ai donc deux sorties PWM pour ma rampe de jour.

Je suis pas électronicien, mais il me semble que le pilotage du mosfet est réduit à son minimum.
Je penses que ça va bien pour une utilisation en remplacement d'un relais, mais pour le pwm c'est peut être pas top.
Voir :
http://www.sullivan-county.com/ele/basic_power_supplies.htm
( ta version en fait parti ).
Le "coté obscur" du Mosfet est sa capacité parasite sur la Gate, il faut un bon driver pour la charger et décharger, dans le cas du pwm c'est encore plus sensible. Dans certains montage on utilise un driver de mosfet pour justement faire cette opération en quelques ns.

Il n'y a pas un électronicien sur la liste ?

A+ Teiva


www.Zartronic.fr : Votre source Arduino en France

Alors j'ai de nouveau les mêmes problèmes.

En cherchant des infos sur les drivers de mos je suis tombé sur un site qui parle de mosfet Logic Level , c'est à dire de mosfet commande compatible avec circuits logiques 5V.

De cette façon on évite l'emploi d'un driver.

Je compte en commander cet après midi.

Merci de m'alerter si je me trompe.

Voila les deux mosfets recus.
Ce sont des IRLZ34N.

Pour ce qui est du code il a complétement était revu.

En effet j'avais deux librairies qui rentraient en conflit.

J'ai donc crée un premier programme uniquement pour entrer et modifier l'heure pour le réglage heure d'été heure d'hiver ou pour récupérer un éventuel décalage.

Le deuxième programme est le programme qui gère l'eclairage de jour et de nuit, le chauffage et l'affichage de l'heure.

Le programme pour paramétrer l'heure

#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

void setup() {
  RTC.stop();
  RTC.set(DS1307_SEC,00);        //reglage secondes
  RTC.set(DS1307_MIN,59);        //reglage minutes
  RTC.set(DS1307_HR,19);         //reglage heures
  RTC.set(DS1307_DOW,4);         //reglage jour de la semaine
  RTC.set(DS1307_DATE,13);       //reglage date
  RTC.set(DS1307_MTH,01);         //reglage mois
  RTC.set(DS1307_YR,11);          //reglage annee
  RTC.start();
}

void loop(){
}

Le programme principal

#include <LiquidCrystal.h>
#include <WProgram.h>
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  

/*
Arduino Masterbalby Controller
 Analog Pin 0 = Temperature Sensor
 Analog Pin 4 = SDA pour ds1307
 Analog Pin 5 = SCL pour ds1307
 Digital Pin 2 = LCD
 Digital Pin 3 = LCD
 Digital Pin 4 = LCD
 Digital Pin 5 = LCD
 Digital Pin 6 = LCD
 Digital Pin 7 = LCD
 Digital Pin 8 = Relais Chauffage
 Digital Pin 9 = PWM moon_light
 Digital Pin 11 = PWM day_light
 Digital Pin 16 = Bouton poussoir 1 day light
 Digital Pin 15 = Bouton poussoir 2 chauffage
 */

//LiquidCrystal lcd(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int sensorPin = 0;
int chauffage = 8;
int pwm1 = 11;
int pwm2 = 9;
int time;
int BP1=16; //interrupteur Day_light 
int BP2=15; //interrupteur Chauffage
int val_up=0;
int val_down=0;
long last_time1 = 0;
long last_time2 = 0;


void setup()  {
  Serial.begin(9600);
  pinMode(chauffage, OUTPUT);  // digital pin pour chauffage en sortie
  pinMode(BP1, INPUT); //met la broche en entree 
  digitalWrite(BP1, HIGH) ; // activation du pullup de la broche en entree
  pinMode(BP2, INPUT); //met la broche en entree 
  digitalWrite(BP2, HIGH) ; // activation du pullup de la broche en entree
  analogWrite(pwm1,0);
  analogWrite(pwm2,0);
  lcd.begin(16, 2);
  delay(10);
  lcd.print("MasterBalby 3.4");
  lcd.setCursor(0, 1) ;
  lcd.print("Gestion Aqua");
  delay(2000);
  lcd.clear();
  setSyncProvider(RTC.get);  
  if(timeStatus()!= timeSet) 
    lcd.println("Unable to sync");
  else
    lcd.println("RTC system time ");   
  delay(2000);   
  lcd.clear();
  delay(10);
}

void loop() {
  val_up = (map (minute(), 0, 59, 0, 150));
  val_down = (map (minute(), 0, 59, 150, 0));
  time = ((hour() * 100) + minute());  
  //Recuperer la temperature du LM35 ***************************************************************************************
  int reading = analogRead(sensorPin);  
  float voltage = reading * 5.0 / 1024; 
  int temp = voltage * 100 ; 
  //Chauffage******************************************************************************
  if((temp < 24) || (digitalRead(BP2)==LOW)) {     
    digitalWrite(chauffage, HIGH);
  }  
  else if (temp > 26)
  {  
    digitalWrite(chauffage, LOW);
  }
  //****************Day Lights**********************************************************************************
  if (hour() == 15)  { // entre 15:00:00 et 15:59:59
    analogWrite (pwm1, val_up); // allumage progressif
  }
  else if (hour() == 20)  { // entre 20:00:00 et 20:59:59
    analogWrite (pwm1, val_down); // extinction progressive
  }   
  else if ((hour() > 15 ) && (hour() < 20)) { // entre 16:00:00 et 19:59:59
    analogWrite(pwm1, 150);
  }
  else if ((((hour() > 0  && hour() < 15)) && (digitalRead(BP1)==LOW)) || (((hour() > 20  && hour() < 24)) && (digitalRead(BP1)==LOW)) || ((hour() == 0) && (digitalRead(BP1)==LOW))){
    analogWrite(pwm1, 150);  
  }
  else if ((((hour() > 0  && hour() < 15)) && (digitalRead(BP1)==HIGH)) || (((hour() > 20  && hour() < 24)) && (digitalRead(BP1)==HIGH)) || ((hour() == 0) && (digitalRead(BP1)==HIGH))){
    analogWrite(pwm1, 0);  
  }
  //****************Moon Lights****************************************************************************
  if ((hour() > 19) &&  (hour() < 24)) {   // de 20:00:00 à 23:59:59
    analogWrite(pwm2, 255);
  }
  else{
    analogWrite(pwm2, 0);
  }
  //Affichage chauffage allumé********************************************************
  lcd.setCursor(0,1);
  if(digitalRead(chauffage) == HIGH)
  {
    lcd.println("Chauffage ON    ");
  }
  else
  {
    lcd.println("Chauffage OFF   ");
  }
  //Affichage heure***************************************************************************************
  if ( millis() >=(last_time1 + 1000))
  {
    lcd.setCursor(0, 0) ;
    lcd.print(hour());
    printDigits(minute());
    printDigits(second());
    last_time1 = millis();  
  }
  //Affichage temperature*****************************************************************************
  if ( millis() >=(last_time2 + 5000))
  {
    lcd.setCursor(9,0);
    lcd.print("T:");
    lcd.print(temp); 
    lcd.println("C  ");  
    last_time2 = millis();
  }
  //Serial.print(hour()),Serial.print(":"),Serial.print(minute()),Serial.print(":"),Serial.print(second()),Serial.print(" "),Serial.pri
  //Serial.print(temps_perso),Serial.println();
  //Serial.print(time),Serial.println();
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  lcd.print(":");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}

J'espère avec cela pouvoir aider quelqu'un...