Controle d'un éclairage fluorescent T5

Bonjour !

Suite à une panne de mon éclairage d'aquarium, je me lance dans la fabrication d'une nouvelle rampe d'éclairage à base de tube fluorescent T5.

Pour le montage de la rampe, c'est bon. Par contre, je souhaite contrôler l'allumage et l'extinction des tubes en coupant l'alimentation des ballasts à l'aide de relais (coupant la phase).
En plus, le système va gérer une ventilation afin de garder les tubes à une température proche de leur optimum (35°C).

Niveau matériel, j'ai opté pour une carte arduino UNO (copie Elegoo), un module contenant 4 relais avec optocoupleur, un module RTC DS3231 et un capteur de température DS18B20.

Mes connaissances en programmation arduino sont de niveau débutant, j'ai essayé de faire un programme simple et j'aimerai votre avis dessus. (Les heures et pin ne sont pas définitif encore)

Le code :

#include <Wire.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DallasTemperature.h>

RTC_DS3231 rtc;

const int RELAIS_ACTI = 1 ;
const int RELAIS_BLEU = 2 ;
const int RELAIS_BLANC  = 3 ;
const int RELAIS_VENTIL = 4 ;
#define ONE_WIRE_BUS 5 

OneWire oneWire( ONE_WIRE_BUS );
DallasTemperature sensors( &oneWire );


void setup() {
  /* put your setup code here, to run once:*/

Serial.begin(115200);


pinMode(RELAIS_ACTI, OUTPUT);     /*Configure la broche 1 (relais actinique) en sortie*/
pinMode(RELAIS_BLEU, OUTPUT);
pinMode(RELAIS_BLANC, OUTPUT);
pinMode(RELAIS_VENTIL, OUTPUT);
digitalWrite(RELAIS_ACTI,0);            /*On place le relais dans l'état off*/
digitalWrite(RELAIS_BLEU,0);
digitalWrite(RELAIS_BLANC,0);
digitalWrite(RELAIS_VENTIL,0);
Wire.begin();
sensors.begin();

}

void loop() {
  // put your main code here, to run repeatedly:
  
sensors.requestTemperatures();    /*demande de température de toutes les sondes*/
float Temp = sensors.getTempCbyIndex(0)   /*On garde l'index 0*/

DateTime now = rtc.now();                     /*On fait tourner la fonction heure de la RTC*/


if(now.hour >= 12 && now.minute >= 00 && now.hour <= 22 && now.minute <= 00) //On teste l'heure de la RTC
{
  digitalWrite(RELAIS_ACTI,1);   /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_ACTI,0); //sinon on eteint
}

if(now.hour >= 12 && now.minute >=00 && now.hour <= 22 && now.minute <= 00)
{
  digitalWrite(RELAIS_BLEU,1);    /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_BLEU,0);   /*sinon on eteint*/
}

if(now.hour >= 12 && now.minute >=00 && now.hour <= 22 && now.minute <= 00)
{
  digitalWrite(RELAIS_BLANC,1);      /*On allume si la condition d'heure est respectee*/
} 
else
{
  digitalWrite(RELAIS_BLANC,0);    /*sinon on eteint*/
}

if(Temp >= 40)
{
  digitalWrite(RELAIS_VENTIL,1);     /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_VENTIL,0);   /*sinon on eteint*/
}
}

Lorsque je vérifie le projet, j'obtient 2 erreurs :

programme_lampe_T5:55: error: 'now' was not declared in this scope

 if(now.hour >= 12 && now.minute >=00 && now.hour <= 22 && now.minute <= 00)

et

In function 'void loop()':

programme_lampe_T5:41: error: 'class DallasTemperature' has no member named 'getTempCbyIndex'

 float Temp = sensors.getTempCbyIndex(0)   /*On garde l'index 0*/

J'avoue, je séche... Les exemples qui m'ont servi de modéle n'ont rien de plus. Du coup, je séche...

Pouvez-vous m'aider à finaliser les programme pour qu'il compile correctement ?

Merci à vous !

Sanct

pour la seconde erreur, tu as fait une faute de frappe, c'est getTempCByIndex(0) (avec un B et pas un b ) le nom de la fonction dans la librairie

Et pour la première, je pense que tu dois ajouter
    rtc.begin(DateTime(F(__DATE__), F(__TIME__)));dans le setup

Merci à vous deux pour votre aide !

@bricofoy : en effet, je ne cherchais pas ce genre d'erreur. La casse a donc un importance primordiale. En tout cas, ça marche.

@lesept : je viens d'essayer, cela renvoie un erreur de fonction non-définie. Mais grâce à ça, j'ai trouvé la solution.

Dans ma ligne :

if(now.hour >= 12 && now.minute >=00 && now.hour <= 22 && now.minute <= 00)

Il faut rajouter des () après chaque now.hour et now.minute. Ce qui donne :

if(now.hour() >= 12 && now.minute() >=00 && now.hour() <= 22 && now.minute() <= 00)

Le code compile correctement maintenant. La suite demain avec la plaque prototype pour faire un montage d'essai. Je posterai le programme corrigé après test de bon fonctionnement.

Encore merci à vous deux !

Pour la première erreur il manquait le point virgule qui marque la fin de la ligne précédent la définition de now

float Temp = sensors.getTempCbyIndex(0);   /*On garde l'index 0*/

DateTime now = rtc.now();                     /*On fait tourner la fonction heure de la RTC*/

fdufnews:
Pour la première erreur il manquait le point virgule qui marque la fin de la ligne précédent la définition de now

float Temp = sensors.getTempCbyIndex(0);   /*On garde l'index 0*/

DateTime now = rtc.now();                    /On fait tourner la fonction heure de la RTC/

Ha oui, bien vu !

Hello, je reviens vers vous !

Premier point, merci pour vos corrections !

Deuxième, la mesure de température ne fonctionnait pas, la sonde renvoyait -127°C en permanence puis 0053. J'ai résolu le problème en utilisant l'exemple Single fournis avec la librairie Dallas thermometer. De ce que j'ai compris, il faut absolument lancer une recherche d'adresse du thermocouple (placée ensuite dans un tableua) et fixer sa résolution. Et là, ça marche.

Troisième point : Mon horloge est à la bonne heure mais mes relais restent toujours en position HIGH même aprés l'heure.

J'ai eu le problème avec le thermocouple, il m'a suffit de placer ma consigne en variable pour que cela fonctionne.

Est-ce que c'est pareil, on ne peut pas employer directement des chiffres dans les boucles if ?

Voilà le programme :

#include <Wire.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DallasTemperature.h>

RTC_DS3231 rtc;

const int RELAIS_ACTI = 6 ;
const int RELAIS_BLEU = 2 ;
const int RELAIS_BLANC  = 3 ;
const int RELAIS_VENTIL = 4 ;
const char TEMP_VENTIL = 40;
#define ONE_WIRE_BUS 5 

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress insideThermometer;

void setup() {
  /* put your setup code here, to run once:*/

Serial.begin(9600);


pinMode(RELAIS_ACTI, OUTPUT);     /*Configure la broche 1 (relais actinique) en sortie*/
pinMode(RELAIS_BLEU, OUTPUT);
pinMode(RELAIS_BLANC, OUTPUT);
pinMode(RELAIS_VENTIL, OUTPUT);
digitalWrite(RELAIS_ACTI,0);            /*On place le relais dans l'état off*/
digitalWrite(RELAIS_BLEU,0);
digitalWrite(RELAIS_BLANC,0);
digitalWrite(RELAIS_VENTIL,0);
Wire.begin();
sensors.begin();


 if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 

   sensors.setResolution(insideThermometer, 9);
 
 
}

void loop() {
  // put your main code here, to run repeatedly:

sensors.requestTemperatures();    /*demande de température de toutes les sondes*/

DateTime now = rtc.now();                     /*On fait tourner la fonction heure de la RTC*/


if(now.hour() <= 14 && now.minute() <= 30 && now.hour() >= 18 && now.minute() >= 30) //On teste l'heure de la RTC
{
  digitalWrite(RELAIS_ACTI,1);   /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_ACTI,0); //sinon on eteint
}

if(now.hour() >= 15 && now.minute() >=00 && now.hour() <= 19 && now.minute() <= 00)
{
  digitalWrite(RELAIS_BLEU,1);    /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_BLEU,0);   /*sinon on eteint*/
}

if(now.hour() >= 15 && now.minute() >=30 && now.hour() <= 19 && now.minute() <= 30)
{
  digitalWrite(RELAIS_BLANC,1);      /*On allume si la condition d'heure est respectee*/
} 
else
{
  digitalWrite(RELAIS_BLANC,0);    /*sinon on eteint*/
}

  float tempC = sensors.getTempC(insideThermometer);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  
if(tempC < TEMP_VENTIL)
{
  digitalWrite(RELAIS_VENTIL,1);     /*On allume si la condition d'heure est respectee*/
}
else
{
  digitalWrite(RELAIS_VENTIL,0);   /*sinon on eteint*/
}
}

Nota : j'ai été surpris par le fonctionnement des > et <. Pour le thermocouple, si je laisse le code "TempC > TEMP-VENTIL", mon relais se déclenche si TempC est inférieur à TEMP-VENTIL. Je suis boligé de fonctionner en logique inverse en plaçant un sigle inférieur à < pour que mon relais commute si ma température est supérieure à la consigne. C'est normal ?

Merci de votre aide !

Sanct:
la mesure de température ne fonctionnait pas, la sonde renvoyait -127°C en permanence puis 0053.

Pauvres poissons ! Je préviens la SPA tout de suite !

lesept:
Pauvres poissons ! Je préviens la SPA tout de suite !

Fort heureusement pour eux, cette sonde n'est pas pour le bac. Elle va mesurer la température de la rampe pour garder les tubes à leur température de fonctionnement optimal (environ 35°C).

D'ailleurs, je me pose une question, comment puis-je faire en sorte que le relais associé au ventilateur reste allumés un certains temps après que la consigne soit atteinte sans utiliser de delay qui bloque complétement le programme ?

Genre, on est à 34.5°C, là, là mon ventilateur s'arrête d'office. J'aimerai bien le laisser tourner 5 minutes supplémentaires par exemple mais sans bloquer le programme avec un delay.

Tu crées un "chrono" qui compte le temps à partir du début de tes 5 minutes et à la fin tu arrêtes le ventilateur.
Pour ça tu utilises la fonction millis() qui te donne le temps coulé en ms depuis le lancement du programme.

Lorsque tu veux lancer le décompte :
unsigned long chrono = millis();Puis tu surveilles le chronoif (millis()-chrono > 5*60*1000) { instructions pour arrêter le ventilo }

Sanct:
Hello, je reviens vers vous !

Premier point, merci pour vos corrections !

Deuxième, la mesure de température ne fonctionnait pas, la sonde renvoyait -127°C en permanence puis 0053. J'ai résolu le problème en utilisant l'exemple Single fournis avec la librairie Dallas thermometer. De ce que j'ai compris, il faut absolument lancer une recherche d'adresse du thermocouple (placée ensuite dans un tableua) et fixer sa résolution. Et là, ça marche.

Attention,les ds18b20 n'ont rien à voir avec des thermocouples. Ça n'a pas d'importance ici,mais soyons précis sinon on ne sait plus de quoi on parle !

Troisième point : Mon horloge est à la bonne heure mais mes relais restent toujours en position HIGH même aprés l'heure.

J'ai eu le problème avec le thermocouple, il m'a suffit de placer ma consigne en variable pour que cela fonctionne.

Est-ce que c'est pareil, on ne peut pas employer directement des chiffres dans les boucles if ?

Bien sur que si, ça devrait fonctionner en mettant directement la valeur.
Attention toutefois à comparer deux valeurs de même type de données. Si tu compares un float avec un int ça peut donner des résultats surprenants, par exemple. Donc par exemple si tu veux faire if(temp>35), comme temp est un float, ilfaut écrire if(temp>35.0) pour être sûr de comparer deux floats

Nota : j'ai été surpris par le fonctionnement des > et <. Pour le thermocouple, si je laisse le code "TempC > TEMP-VENTIL", mon relais se déclenche si TempC est inférieur à TEMP-VENTIL. Je suis boligé de fonctionner en logique inverse en plaçant un sigle inférieur à < pour que mon relais commute si ma température est supérieure à la consigne. C'est normal ?

Merci de votre aide !

Non, pas du tout

Tu es sûr de ne pas avoir fait une erreur sur la commande du relais ? Je ne sais pas ce que tu utilises comme relais,mais la plupart des platines chinoises ont une commande inversée : le relais est actif quand l'entrée de commande est au niveau logique 0. Ce qui expliquerait que tu sois obligé d'inverser la condition pour que ça fonctionne dans le bon sens.