Ce code me rend fou... pilotage relais et CTN !

Bonjour à tous,
Je ne trouve pas l’erreur ou du moins ce qui cloche malgré avoir retourné le truc dans tous les sens. Un pilotage relais en fonction de la température mesurée par une CTN et d’un évènement jour ou nuit. Le relais jour/nuit fonctionne, pas de souci, mais le relais température ne fonctionne pas.
Un coup d’oeil extérieur me serait donc bien utile car j’y comprends plus rien.

Voici le code :

//----------Constantes climatiques---------- 
int topLight = 960;
int lowLight = 480;
int actifTempAmbiantJour = 26;
int actifTempAmbiantNuit = 23;
int reposTempAmbiantJour = 13;
int reposTempAmbiantNuit = 13;

//----------Pour ecran----------
#define sclk 13
#define mosi 11
#define cs   7 // attention pin10 a utiliser avec SD Card
#define dc   9
#define rst  8
//----------Pour relais----------
int RelaisTempAmbiant=4; // pin commande relais IN1
int RelaisPhotoperiode=5; // pin commande relais IN2
//----------Variables----------
int jourAnActuel;
int momentJournee;
int DsDay;
int DsMont;
int DsYear;
int DsHour;
int DsMin;
int DsSec;
float DureeJour;
float TempJourAmbiant;
float TempNuitAmbiant;
float steinhart;
char stringvalTmp[4];
char stringvalDureeJour[4];
char stringvalTmpJourAmbiant[4];
char stringvalTmpNuitAmbiant[4];
//-----------------------------

#include <Adafruit_GFX_AS.h>    // Core graphics library
#include <Adafruit_ST7735_AS.h> // Hardware-specific library
#include <SPI.h>
#include <stdlib.h>
#include <Wire.h>
#include <SD.h>
#include "RTClib.h"
Adafruit_ST7735_AS tft = Adafruit_ST7735_AS(cs, dc, rst);
const byte SDCARD_CS_PIN = 10; // attention pin 10 et ecran !
RTC_DS1307 RTC;

//----------SETUP--------------
void setup(void) {
    tft.initR(INITR_BLACKTAB);
    tft.setRotation(1);
  Serial.begin(9600);
  Wire.begin();
    RTC.begin();
    if (! RTC.isrunning()) {
      tft.print("Module RTC non initialise !");
      RTC.adjust(DateTime(__DATE__,  __TIME__));  
    }
    DateTime now = RTC.now();
 
  // tft.print("Initializing SD card...");
  pinMode (10,OUTPUT); //attention pin10 et ecran !
    
  pinMode (RelaisTempAmbiant, OUTPUT); // Initialisation Relais
  pinMode (RelaisPhotoperiode, OUTPUT);
  
  tft.fillScreen(ST7735_BLACK);  
}
//----------BOUCLE-----------
void loop() {
  GetTimeFromRTC();
    tft.setCursor(25,0);tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
    if (DsHour < 10) { tft.print("0"); }
    tft.print(DsHour, DEC); tft.print(":");
    if (DsMin < 10) { tft.print("0");} 
    tft.print(DsMin, DEC);
    tft.print("   ");
    if (DsDay < 10) { tft.print("0"); }
    tft.print(DsDay, DEC); tft.print("/");
    if (DsMont < 10) { tft.print("0"); }
    tft.print(DsMont, DEC); tft.print("/");
    tft.print(DsYear, DEC);
  
  jourAnActuel = ((DsMont -1)*31)+DsDay; // Definition du jour julien
    if ((jourAnActuel <= 31) || (jourAnActuel >= 305)) { // Novembre-Janvier _ Repos
      PeriodeRepos();
      }
    if ((jourAnActuel > 31) && (jourAnActuel < 60)) { // Fevrier _ Reprise activite
      PeriodeRActivite();
      }
    if ((jourAnActuel >= 60) && (jourAnActuel < 274)) { // Mars-Septembre _ Pleine activite
      PeriodeActivite();
      }
    if ((jourAnActuel >= 274) && (jourAnActuel < 305)) { // Octobre _ Prepa. repos
      PeriodePRepos();
      }
  
  delay (2000);
  }
//----------FONCTIONS--------

void GetTimeFromRTC() {
  DateTime now = RTC.now();
  DsDay = now.day();
  DsMont = now.month();
  DsYear = now.year();
  DsHour = now.hour();
  DsMin = now.minute();
}

void PeriodeRepos() {
  tft.setTextColor(ST7735_BLACK,ST7735_YELLOW);
  tft.drawCentreString("       Periode Repos       ",0,100,2);
  DureeJour = lowLight;
    dtostrf((DureeJour/60),4,1,stringvalDureeJour); 
  TempJourAmbiant = reposTempAmbiantJour;
    dtostrf(TempJourAmbiant,4,1,stringvalTmpJourAmbiant);
  TempNuitAmbiant = reposTempAmbiantNuit;
    dtostrf(TempNuitAmbiant,4,1,stringvalTmpNuitAmbiant);
TempCTN();
}

void PeriodeRActivite() {
  tft.setTextColor(ST7735_BLACK,ST7735_YELLOW);
  tft.drawCentreString("  Periode RepriseActivite  ",0,100,2);
  DureeJour = lowLight + ((jourAnActuel - 31) * 17.142);
    dtostrf((DureeJour/60),4,1,stringvalDureeJour); 
  TempJourAmbiant = reposTempAmbiantJour + ((jourAnActuel - 31) * 0.464);
    dtostrf(TempJourAmbiant,4,1,stringvalTmpJourAmbiant);
  TempNuitAmbiant = reposTempAmbiantNuit + ((jourAnActuel - 31) * 0.357);
    dtostrf(TempNuitAmbiant,4,1,stringvalTmpNuitAmbiant);
TempCTN();
}

void PeriodeActivite() {
  tft.setTextColor(ST7735_BLACK,ST7735_YELLOW);
  tft.drawCentreString("      Pleine activite      ",0,110,2);
  DureeJour = topLight;
     dtostrf((DureeJour/60),4,1,stringvalDureeJour);  
  TempJourAmbiant = actifTempAmbiantJour;
     dtostrf(TempJourAmbiant,4,1,stringvalTmpJourAmbiant);
  TempNuitAmbiant = actifTempAmbiantNuit;
    dtostrf(TempNuitAmbiant,4,1,stringvalTmpNuitAmbiant);
TempCTN();
}

void PeriodePRepos() {
  tft.setTextColor(ST7735_BLACK,ST7735_YELLOW);
  tft.drawCentreString("     Periode Pre-Repos     ",0,110,2);
  DureeJour = topLight - ((jourAnActuel - 274) * 15.483);
    dtostrf((DureeJour/60),4,1,stringvalDureeJour); 
  TempJourAmbiant = actifTempAmbiantJour + ((jourAnActuel - 274) * 0.419);
    dtostrf(TempJourAmbiant,4,1,stringvalTmpJourAmbiant);
  TempNuitAmbiant = actifTempAmbiantNuit + ((jourAnActuel - 274) * 0.322);
    dtostrf(TempNuitAmbiant,4,1,stringvalTmpNuitAmbiant);
TempCTN();
}

void TempCTN() {
  int samples[5];
  int CTN = {A0};
  float steinhart;
  uint8_t i;

    float average;
    for (byte i=0; i<5; i++) {
      samples[i] = analogRead(CTN);
      delay(10);
    }
    average = 0;
    for (i=0; i<5; i++) {
      average += samples[i];
    }
    average/=5;
    average = (1023 / average)-1;
    average = 10000 / average;
    steinhart = average/10000;
    steinhart = log(steinhart);
    steinhart /= 3950;
    steinhart += 1.0 / (25 + 273.15);
    steinhart = 1.0 / steinhart;
    steinhart -= 273.15;
    // Affichage numeric de temperature
    dtostrf(steinhart,4,1,stringvalTmp); // Conversion valeur decimale en string dans le buffer stringvalTmp
    tft.setTextColor(ST7735_WHITE,ST7735_BLACK);tft.drawString(stringvalTmp,15,25,6);
  Photoperiodism();
}

void Photoperiodism() {
  momentJournee = (DsHour * 60) + DsMin;
  tft.setTextColor(ST7735_YELLOW,ST7735_BLACK);tft.drawString(stringvalTmpJourAmbiant,115,23,2);
  tft.setTextColor(ST7735_CYAN,ST7735_BLACK);tft.drawString(stringvalTmpNuitAmbiant,115,49,2);
  tft.setTextColor(ST7735_YELLOW,ST7735_BLACK);tft.drawString(" Duree jour : ",0,80,2);tft.drawString(stringvalDureeJour,85,80,2);
  
  if ((momentJournee >= 480) && (momentJournee < (480 + DureeJour))) { // >=8:00 et <8:00+DureeJour
    digitalWrite (RelaisPhotoperiode, LOW);    //on 
      if (steinhart < TempJourAmbiant - 0.2) {
      digitalWrite (RelaisTempAmbiant, LOW);
      tft.fillRect(15,67,93,5,ST7735_RED);
      } else if (steinhart >= TempJourAmbiant + 0.2) {
      digitalWrite (RelaisTempAmbiant, HIGH);
      tft.drawRect(15,67,93,5,ST7735_GREEN);
      }
    } else {
    digitalWrite (RelaisPhotoperiode, HIGH);  //off
      if (steinhart < (TempNuitAmbiant - 0.2)) {
      digitalWrite (RelaisTempAmbiant, LOW);
      tft.fillRect(15,67,93,5,ST7735_RED);
      } else if (steinhart > TempNuitAmbiant + 0.2){
      digitalWrite (RelaisTempAmbiant, HIGH);
      tft.fillRect(15,67,93,5,ST7735_GREEN);
      }
    }
}

/*void AnalyseTempJour() {
  if (steinhart < TempJourAmbiant - 0.2) {
    digitalWrite (RelaisTempAmbiant, LOW);
    tft.fillRect(15,67,93,5,ST7735_RED);
  } else if (steinhart >= TempJourAmbiant + 0.2) {
    digitalWrite (RelaisTempAmbiant, HIGH);
    tft.drawRect(15,67,93,5,ST7735_GREEN);
  }
}
 
void AnalyseTempNuit() {
  if (steinhart < (TempNuitAmbiant - 0.2)) {
    digitalWrite (RelaisTempAmbiant, LOW);
    tft.fillRect(15,67,93,5,ST7735_RED);
  } else if (steinhart > TempNuitAmbiant + 0.2){
    digitalWrite (RelaisTempAmbiant, HIGH);
    tft.fillRect(15,67,93,5,ST7735_GREEN);
  }
}*/

les fonctions AnalyseTempJour() et AnalyseTempNuit() étaient appelées dans la fonction Photoperiodism() à la place des lignes destinées à piloter le relais (d’ailleurs ce sont les mêmes lignes ici ; j’ai simplement remplacé l’appel à fonctions par leurs contenus dans un ultime essai et passé les fonctions en commentaire pour qu’elles ne soient pas prises en compte du coup). La partie de prise en compte de la carte SD n’est pas encore développée, d’ailleurs si je mets une carte dans le support, l’affichage déconne complètement à ce moment là uniquement.
Mais ça ne fonctionne toujours pas… et je ne vois plus rien à force d’avoir les yeux dessus et de retourner le truc dans tous les sens.

Help donc sioux-plait avant de scalper le montage !!!
Merci et bon WE

Est ce que

      tft.fillRect(15,67,93,5,ST7735_RED);
.....
      tft.drawRect(15,67,93,5,ST7735_GREEN);

Fonctionne?

Salut ,

Le relais jour/nuit fonctionne, pas de souci, mais le relais température ne fonctionne pas

ca veut dire quoi exactement ? le code n ' enclenche pas le relais ?

vous avez fait un simple test de code pour verifier que le relais fonctionne dans votre montage pour commencer ?

Es-tu sûr de ça

 int CTN = {A0};

Pourquoi pas simplement

 int CTN = 0;

de plus cette condition me parait toujours fausse quelquesoit la valeur ( positive ) de dureejour :

if ((momentJournee >= 480) && (momentJournee < (480 + DureeJour)))

merci pour vos remarques, comme quoi il y a un moment l'oeil extérieur est nécessaire ne serait-ce que pour apporter qques corrections. Alors pour répondre à chacun :

  • tft.fillRect et tftdrawRect fonctionnent : les deux commandes fonctionnent pour les avoir testées, mais je reste en rouge sur l'affichage en fait donc pas de lien entre la référence et la mesure de température effectuée pour piloter le relais d'un autre coté,
  • le code n'enclenche effectivement pas le relais dédié à la régulation de la température (les relais sont fonctionnels pourtant),
  • pour le int CTN, effectivement j'ai corrigé mais ça n'a rien changé (en fait dans un autre code j'avais plusieurs CTN et quand j'ai adapté du coup je n'ai pas fait gaffe),
  • pour la valeur DureeJour, la valeur n'est pas fausse puisqu'elle varie de 480 à supérieur pour le moment jour et elle est inférieure à 480 pour la nuit ; de plus pour le relais dédié qui est piloté, tout fonctionne bien.

Merci

Je pense que vous risquez un dépassement mémoire dans vos dtostrf() les stringvalDureeJour stringvalTmpJourAmbiant etc sont sans doute trop petites pour le caractère null final - essayez juste en les dimensionnant à 10 ou 20 pour être tranquille.

Ça rime à quoi ces maths ?

 average = (1023 / average)-1;
    average = 10000 / average;
    steinhart = average/10000;
    steinhart = log(steinhart);

(Et si la moyenne valait 1023 vous avez une division par 0)

Je découvre.
Cela me parait bien compliqué.

Un pilotage relais en fonction de la température mesurée par une CTN

J'en déduit qu'il n'y a qu'une température ou peu de températures.
Dans ce cas pourquoi allez s'emmer*er avec la relation de Steinhart dont de toute façon les coefficients ne sont connus que très approximativement. Perso j'aurai déterminé la valeur de la résistance de la thermistance à la température donnée. Le matériel chinois manque de tableau de donnée mais si tu as trouvé des coefficients de Steinhart il doit y avoir associé un tableau de valeurs ohmiques en fonction de la température.
La thermistance placée dans un pont je testerai sur la valeur de la tension lue.
Quand on utilise une thermistance gérer des ohms ou des degrés c'est la même chose, autant aller au plus simple.
Cà c'est mon coté développeur électronicien.

Mon coté "petit programmeur amateur" m'aurait fait décomposer les actions et j'aurai testé action par action avant de tout assembler.
Moins il y a de lignes de code à gérer plus c'est facile de trouver les erreurs.
Dans ton code on ne voit pas de Serial.print pour afficher des messages de débogage dans le moniteur de l'IDE.
Afficher le résultat des tests est très utile pour comprendre où cela ne va pas et évite que le code rende fou.

tft.fillRect et tftdrawRect fonctionnent : les deux commandes fonctionnent pour les avoir testées, mais je reste en rouge sur l’affichage en fait donc pas de lien entre la référence et la mesure de température effectuée pour piloter le relais d’un autre coté,

Donc if (steinhart < TempJourAmbiant - 0.2) {
est toujours vrai.

Je viens de voir ca!!

void TempCTN() {
  int samples[5];
  int CTN = {A0};
  float steinhart;  /// ici variable locale 
  uint8_t i;

tu utilise pour calculer steinhart une variable locale mais ta variables globale steinhart reste a 0!

Et c'est l'exemple parfait de l'utilité d'envoyer des messages de débogages : tu aurais vu par toi même que la valeur de cette variable était perdue dès que tu sors de la fonction.

Je rajoute que le tuto d'Eskiimon est un trésor pour éviter tous ces pièges et que la lecture d'un tuto "très généraliste" de C ou Cpp est aussi très utile.

Bonjour,
Je prends note de vos obs merci à vous et bien vu Savoriano, en fait j'avais une redite avec la ligne que tu indique quant à la variable locale et celle qui était déjà déclaré en tête de code donc globale. C'est ça qui fichait le caca. Après correction, ça fonctionne nickel !
Merci à vous tous pour ces conseils et le coup d'oeil extérieur :wink:
Un bon dimanche, merci encore
Frk

Vérifiez quand même la taille des buffers. C’est sournois ces trucs là...

char stringvalTmpJourAmbiant[4]; 
...
dtostrf(TempJourAmbiant,4,1,stringvalTmpJourAmbiant);

Dans stringvalTmpJourAmbiant vous n’avez la place que pour 2 chiffres et le point décimal. Le 4ème octet est pour le caractère nul de fin de chaîne.

Idem pour les autres