Control heater automatic open source ( régulation hystérésis de température radiateur) réparable, simulation

Le nombre de radiateur électrique inferieur à 1500W (150 à 200€) qui vont à la poubelle juste à cause d’un relais défectueux (interrupteur qui bouge) ou triac (relais statique), voir le capteur de température CTN de régulation ou de sécurité défectueux…

un article a été realisé sur les radiateurs electriques et la programmation des thermostat sur ce lien bien connu de l'enseignement

Il faut savoir que la durée de vie d’un relais est de X milliers de manœuvres (contact charbonné, ressort défectueux).

L’obsolescence d’un triac est de plus de 15 ans, comme celui du micro.

Comme il n’y a pas les schémas électriques de radiateur, c’est difficile à réparer pourtant tous ces composant valent moins de 1€

Étant donner que le seuil cognitif du cout d’un dépannage est de 30% du prix d’achat, la réparation n’est pas viable de ces radiateurs pas cher.

En 2024, toujours pas de radiateur open source commercialiser pour minimiser l’impact sur la planète et sur le pouvoir d’achat

Parfois, c’est la résistance électrique qui est défectueuse mais qui peut être remplacé

Remarque : Il vaut mieux prendre des radiateurs sans eau qui sont plus facile à réparer car sans joint.
Ici, c’est le relais qui était en disfonctionnement, il a été changé par un module. mais il a fallu trouvé l'alimentation qui manque un peu de puissance pour alimenter le relais

Les normes demandent de faire un zéro crossing pour minimiser les perturbations électriques sur le réseau et limité les étincelles sur le contact du relais.

Mais il y a des optocoupleurs tel que le MOC3041 qui font automatiquement la commutation au zero crossing mais leur courant max est de 1A

Donc, il faudra utiliser un triac externe en TO220 avec un petit radiateur tel que le BT139 ou BTA 16 qui peut supporter 16A RMS donc 3000W sous 220V RMS
Attention : il ne faut pas prendre de module gradateur variable dimmer….
mais un module comme celui-ci (bizarre que cela coute aussi cher)

pour bien comprendre la régulation par hysteresis, il est possible de simuler le radiateur sous proteus pour connaitre son influence ainsi que de trouver le modèle automatique thermique du système pour savoir si le radiateur est bien dimensionné ou pas et de quantifier les pertes thermiques.

Mais, les informations du model spice sont toujours difficile à trouver donc un petit essai sur le heater de proteus :

HP correspond aux pourcentage

TPTC correspond à la constante de temps thermique : on choisira 10s pour simuler rapidement

La tension du heater image de la température correspond à l’équation suivante sachant qu’il consomme 50W sous 220V, il n’est pas possible de changer cette puissance

Temperature finale = HP (%).power.sensor (V/°C)+Tamb

Temperature finale = pourcentage(%).50W .1°C/W . 1Volt/°C + 10°CTamb=105°C au bout de 30s correspondant à 95% de la temperature finale à 3 fois la constante de temps

Dans un premier temps, nous allons simuler la régulation de température un relais et une consigne de 20° fait un potentiomètre, une hystérésis de 1°C, une inertie thermique de 50s.

Le coefficient du capteur du heater sera de 0.01V/°C comme pour un LM35.

Il faut 2 capteurs de température, l’un pour la sécurité de ne pas se bruler, l’autre pour mesurer la température de ce qui chauffe.

On peut observer que la température oscille autour de la consigne avec une période de 20s.

Plus la constante de temps est grande et plus l’oscillation sera faible.

Plus la température finale est grande par rapport à la température désirée et plus il y aura de commutation du relais.

Donc, plus il y a de puissance par rapport aux pertes thermiques et plus il y aura de commutation

Voici le schema de simulation electrique avec la courbe dynamique de temperature

Voici le code,

void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  Serial.begin(57600);
}
void loop() 
{
  int Theater=analogRead(A0);            //temperature de securité sur le metal du radiateur   
  int Theater1=analogRead(A0)/2;
  
  int Sensor = analogRead(A1);  //temperature en bas du radiateur mesurant l'atmospfere  
  int Temp = Sensor/2;          // Storing value in Degree Celsius      0.18V*(1023/5V)*(500/1023)=18°C
  
  int consigne1=analogRead(A2);   // temperature desirée potentiometre
  int consigne=(consigne1*4)/102;  //50%=>2.5V=>20°C

  
  if(Temp < consigne)   {digitalWrite(13,HIGH);  }  //Turn ON the Heater
  if (Temp >(consigne+1))   {digitalWrite(13,LOW);  }  //Turn OFF the Heater

  if (Theater1 >(55))   {digitalWrite(13,LOW);  }  //erreur
//  delay(1000);    //  un delai de 5minutes pour minimiser les commutations du triac ou relais  mais pour la simulation 1s

Serial.print(Temp);Serial.print(";");Serial.print(consigne);Serial.print(";");
Serial.println(";");
}

LE LM35 qui mesure la temperature de la pièce est en boitier plastique, il faut le placer tout en bas du radiateur loin des parties metalliques qui chauffent.
le LM35 en securité est un boitier TO220 et peut etre facilement fixé sur le metal du radiateur.
Normalement, il faut rajouter aussi par securité un disjoncteur thermique mecanique sunomé "clixon"

Voici le schéma avec un triac à la place du relais qui est une source d’obsolescence

Évidemment, il aurait été possible de mettre des float avec une hysteresis de 0.1°C mais la période de commutation aurait été encore plus petite.

Étant numérique, il serait possible de mettre un afficheur LCD pour afficher la température, ou HC06 Bluetooth pour la température sur un smartphone via une application.

La connaissance de l’évolution de la température permet d’avoir le modèle thermique du système, exemple de quantifier l'isolation de la pièce qui est chauffée….

Mais, le modèle thermique en automatique sont d’autres histoires,
l'objectif ici est de faire la maintenance du control du radiateur car les composants ne coutent pas grand choses

6 Likes

Sachant que l’on peut représenter la thermie par des résistances et des capacités comme en électricité

Comment simuler thermiquement une pièce ?

donc comment remplacer le heater de proteus qui est fixe par un modèle plus représentatif de son système

Pourquoi il existe des radiateurs inertiels ?

Les modèles de radiateur dit « inertiels » (eau, céramique, brique) existe pour minimiser la variation de température des radiateurs électriques,

Certains radiateurs ont une inertie avec une durée de plus de 12heures pour chauffer en heure creuse (électricité est un peu moins cher car moins utilisé la nuit car on ne peut pas arrêter les centrales nucléaires) et restituer la chaleur toute la journée (heure pleine).

Par contre, ces radiateurs pèsent très lourd et ils sont très cher.

Donc c’est un peu idiot.

L’électricité est 2 fois plus cher que le gaz ou fioul donc chauffer à l’électricité est un peu idiot mais les radiateurs sèchent serviette électrique sont bien pratique ainsi que les radiateurs pulsés pour faire un coup de chauffe rapide.

Mais à ce jour, l’installation d’une chaudière à gaz est de 7000€ avec une obsolescence de 10 ans, avant c’était 20 ans.
Il faut un 4 fois moins de trésorerie pour une installation électrique que le gaz qui est facile à faire.

Bref, il existe aussi des radiateurs électriques rayonnant lorsqu’ils ne sont pas mis en dessous d’une fenêtre car la convection thermique naturelle ne sera pas bonne.

Ce poser la question pourquoi les radiateurs sont toujours sous les fenêtres !

Normalement, la puissance des radiateurs est prévue pour une température la plus basse extérieure pour atteindre la température désirée ou pour avoir une augmentation rapide de la température.

C’est pour cela que le radiateur électrique doit être régulé le reste du temps….

Je n’y connais pas grand-chose de la thermie des bâtiments

Mais voici un lien sur le modèle des bâtiments biens vulgarisés.

un autre lien sur les modèles des moteurs qui se ressemble.

Donc, effectivement, il est possible de simuler la thermie avec des résistances ou la tension est image de la température, la puissance thermique image d’une source de courant.
Sur la figure suivante, la capacité Joule/°C du radiateur donne la constante de temps du radiateur celle-ci a une faible valeur par rapport à la capacité de la pièce avec ces murs.
La résistance R5 correspond à la convection du radiateur

La résistance thermique R6 représente les pertes dans les murs, elle devrait être bien plus faible mais cela permet d’observer la diminution rapide de la température du radiateur vers la température de la pièce.

Dans cette simulation, la puissance est de 1000W avec un rapport cyclique de 25% et une période de 100 secondes.

La source de tension DC du modèle donne la température ambiante fixe de 10°C. Mais, il est possible de remplacer cette température ambiante par une oscillation avec l’amplitude de la température journalière externe.

La température du radiateur en régime final est comme le montre la figure suivante ou il n’y a pas de régulation

Theater=P*(R5+R6)+TAmb=1000*(0.1+0.1)+10=210°C
Tpiece=P*(R6)+TAmb=1000*(0.1+0.1)+10=110°C

En théorie, un relais ne coupe pas une source de courant et Proteus n’aime pas ça donc il faut tricher un peu pour imposer 1000W et 0W.

Évidement avec le programme, la dynamique de la régulation de température de la pièce est différente avec celle d’un rapport cyclique constant.
Il a fallu faire un diviseur par 100 de la température pour avoir la même sensibilité que le LM35.

Dans la simulation précédente, la température du radiateur est bien trop important et passe le seuil critique de sécurité.

Mais la valeur de la convection thermique du radiateur n’est pas du tout adaptée dans la simulation précédente, une valeur de 0.01°C/W est plus pertinente.

4 Likes

Il y a du travail pour que l’open source soit propagé par rapport aux cartes propriétaires….

De plus, l’ingénierie ne prend pas en compte pour que la réparation soit facile.

Il faudrait imposer que les fabricants mettre leurs schémas électriques libre de droit

Le plus dur est de trouver la bonne pièce

Depuis, plusieurs années, les grands constructeurs vendent des pièces sur leur site mais elles sont 10 fois plus cher que celle que l’on peut avoir sur amazon ou aliexpress en prétextant que le magasinage des pièces coute cher ?

Bienvenu dans le monde de la réparabilité…. :skull_and_crossbones: :worried:

Au-delà de la réparabilité, connaitre le modèle de sa maison ou d’une pièce est intéressant pour connaitre la viabilité de travaux à faire.
C’est mieux que l’étude de diagnostique globale.

En générale, en thermie, on utilise le modèle basique R3C2 avec 3 résistances et 2 capacités

Rien trouver sur le net, en exemple de valeur, ni en essai sur ce modéle

Sur ce lien, il y a quelqu’un qui a instrumentalisé toute sa maison et indique une méthode pour testé

Sur un document, l’évolution de la température avec l’hystérésis de la régulation est démontrée mais on ne connait pas le contexte de cette maison EDF

Je pense qu’il faudrait filtrer la mesure de la température de l’air dans le programme,
Le programme devrait faire une détection de fenêtre ouverte pour ne plus chauffer
Nombreux radiateur a un interrupteur horaire journalier programmable pour la semaine pour sa mise en fonction ou extinction
Je ne sais pas si c’est très économique de couper le chauffage la nuit car lorsqu’il va se remettre en route, la puissance va être à fond,
Est que votre simulation pourrait le prouver ?

2 Likes

Est-ce que pour la maison instrumentée EDF, le thermostat du radiateur est mécanique pour avoir autant de fluctuation de température ???????

Effectivement avec le modèle R3C2, la résistance de la VMC mouvement de l’air sera pris en compte.
mais, le modèle R4C3 prend en compte la température du radiateur, c’est mieux.

Si l’on prend des vrais valeurs thermiques d’une pièce, la simulation de Proteus numérique et analogique va être bien trop long.
Déjà pour faire la simulation précédente de 1000s, il faut attendre 5 minutes.
Il n’est pas possible comme dans Matlab de paramétrer « le pas » de calcul.

Par contre simuler seulement le modèle thermique analogique, cela prend quelques secondes.

Les ordres de grandeurs des modèles thermique d’une pièce sont inexistantes sur le net ??????

Exemple, pour une pièce de 16m^2 au sol avec une hauteur plafond de 2.1m avec un lien externe de 24m^2 de surface donnera tout isolé avec 0.14m de laine de roche donnera une résistance 0.12 °C/W
Une fenêtre double vitrage de 1.5m^2 va provoquer une résistance de 1.5°C/W qui sera en parallèle avec la précédente
En général, il y a un renouvèlement d’air de 2°C/W par la VMC.

Sachant que toutes les résistances thermiques d’un mur multicouche sont en série mais les autres sont en parallèles donc, la puissance moyenne aura alors la valeur suivante

Pmoy(W)=(Rmur//Rfenetre//RVMC).(temperature desirée-Texterne)
576W=(1/0.12+1/0.1+1/0.1+1/2).(20°C-0°C)=(8.3+10+10+0.5)(20-0)

La capacité thermique de l’air est de 1000J/°C.kg donc pour la pièce précédente 32000J/°C mais il y a la capacité thermique des murs qui augmente cette valeur diminuer très fortement cette valeur.

La conduction, la convection, le rayonnement sont 3 résistances en parallèles.
Dans l’air, c’est la conduction qui est négligeable par rapport à la convection.
Dans un mur, c'est la convection qui est négligeable.

La convection de l’air vers le placo et la fenêtre est de 10 W/m^2*°C avec une surface de 48m^2, cela donne une résistance de 0.2°C/W. mais avec le rayonnement en plus, cette valeur sera divisée par 2.

Puis chaque matière rajoute un RC, exemple le BA13 pèse 10kg/m^2 pour la pièce de 16m^2 donne une surface de 48m^2 donc une masse de 480kg donc une capacité d’environ C=48m^210kg/m^21000 J/kg.°C=480 000J/°C avec une résistance thermique de l’isolation de 0.12°C/W déterminée précédemment

Bref, pas si facile de déterminer le modèle thermique simplifié d’une pièce,

Avec une puissance de 1000W, un rapport cyclique de 50%, une période de 600s (10minutes), il faut un temps de 10heures (36000secondes) pour observer la dynamique de la température des murs pour passer de 0°C à 25°C et de minimiser l’humidité sur les murs.
Par contre, la température de l’air fluctue énormément, ainsi que celle du radiateur qu’il faudra réguler

Par conséquent, on va négliger la résistance de la VMC , ainsi que la capacité thermique des murs comme ce qui a été fait précédemment.
On reprendra une température externe de 10°C.

Avec un puissance moyenne de 500W et une période de 60s, la température de la pièce va atteindre en régime établie 101°C comme on peut l’observer sur la figure suivante

Pmoy=500W=(1/0.22).(T air room-10°C)=4.5*(101-10)
la temperature du radiateur va atteindre 100° de plus que la temperature ce qui n’est pas acceptable
Pmax=1000W=(1/0.1).(T heater- T air room)=10*(100- T air room)

La puissance moyenne du radiateur n’est pas très utile

Dans la simulation, il faut rajouter la deuxième régulation

  • Celle de la température du radiateur qui est limité à 60°C par sécurité mais cette deuxième régulation va limiter la puissance moyenne donné à la pièce. Pour minimiser la température max du radiateur, il faudrait diminuer la résistance thermique en augmentant sa surface de convection ou en mettant une ventilation forcée. Mais les ventilations font du bruit en générale.
    Lors de la régulation de la température, le relais mécanique commute énormément presque toutes les secondes à causes de la routine d’interruption utilisée ce qui n’entraine une fluctuation faible.

Le mode on/off de la commande est fait juste par l’interrupteur qui coupe l’alimentation 5V du micro suffit

Effectivement, un arrêt de chauffe avec une fenêtre ouverte serait intéressant à faire.
Mais comment le programmer ?
« Si la température est en dessous de 12°C et n’augmente pas et que le radiateur chauffe pendant plus de 10 minutes alors arrêt de chauffe pendant 1 heure »

Effectivement, un programme avec un interrupteur journalier serait intéressant à faire mais il faudra un afficheur LCD. Donc autant prendre un TTGO qui a un afficheur intégré avec 2 boutons poussoirs pour faire défiler le menu.

Il est vrai que le programme Arduino pourrait faire l’identification du modelé thermique d’une pièce.
En donnant, la puissance moyenne de l’heure précédente via une moyenne mobile pondérée, pour avoir la résistance thermique de la pièce, il faudra utiliser sa calculatrice

Donc voici le nouveau code

#include <TimerOne.h>

int unsigned temps=0;
int seconde=0;
int Theater;
int Theater1;

int Temp;
int Sensor; 

int consigne1;
int consigne;
int Pmoy;
int Pmoy1;
int Pmoy2;
int Pmoy3;
int Energy=0;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  Theater=analogRead(A0);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A0)/2;
  
  Sensor = analogRead(A1);  //temperature en bas du radiateur mesurant l'atmospfere  
  Temp = Sensor/2;          // Storing value in Degree Celsius      0.18V*(1023/5V)*(500/1023)=18°C
  
  consigne1=analogRead(A2);   // temperature desirée potentiometre
  consigne=(consigne1*4)/102;  //50%=>2.5V=>20°C

  
  if(Temp < consigne)   {digitalWrite(13,1);}  //Turn ON the Heater  regulation room
  if(Temp>(consigne+1)) {digitalWrite(13,0);}   //

  if (Theater1 >60)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<7) {digitalWrite(13,1);}  

 if ( digitalRead(13)== 1) {Energy=Energy+1;}  

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  Serial.begin(57600);

  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt
}


void loop() 
{
if (seconde>=1) {  
Pmoy=(Energy*1000)/temps;
if (temps<3600) {Pmoy1=Pmoy;}  //puissance moyenne pour la heure
if (temps==3600) {Energy=0;}                
if (temps>3600 && temps<7200) {Pmoy2=Pmoy;}
if (temps==7200) {Energy=0;}  
if (temps>7200 && temps<10800) {Pmoy3=Pmoy;}
if (temps==10800) {Energy=0;temps=0;} 
  Serial.print(Temp);Serial.print(";");Serial.print(Pmoy);Serial.print(";");Serial.print(Pmoy1);Serial.print(";");
Serial.println(";");
seconde=0;
            }
}//fin loop

Pour le filtrage passe bas du second ordre, avec une fréquence de coupure de 5s à 10s grâce à la période d’échantillonnage fixe 1s pourrait se faire facilement.
Sachant qu’une période d’échantillonnage trop lente entrainera un retard et que la fréquence de coupure entrainera un retard de la commande et des oscillations.

5 Likes

Génial, cette programmation et même le modèle de la thermie d’une pièce pour connaitre la valeur d’isolation.

L’alimentation de l’électronique de certains radiateurs est une vrai galéré, ainsi que leurs réparabilité….
moi, j'ai le radiateur suivant

il n'y a pas de capteur de temperature sur la partie metalique

Le prix du SAV chez leroy merlin est à 300€,
Le prix d'un thermostat pièce correspond à 50% du prix du radiateur, cela ne vaut pas le cout de réparer.

Perdre du temps de changer tous les condos et que l’on et pas sûrs à la fin que ce soit cela, c’est un peu déroutant.

D’ailleurs, Il faut mesurer la résistance du radiateur avant de faire la maintenance pour savoir si c’est le thermoplongeur
Pour 1000W, c’est 48 ohms que l'on peut determiner
R=220^2/Puissance

Effectivement, si on avait les schémas électriques avec les tensions que l’on doit avoir pour connaitre les défauts ce serait bien.

Mais il est possible d’acheter une électronique indépendante sur prise. Normalement les radiateurs ne se met pas sur une prise qui ne supporte que 2000Watt. Sur aliexpress, c’est 3 fois moins chères.

2 Likes

Hello,

Si la sonde est débranchée ou défectueuse et retourne une température basse ou négative, si rien n'est prévu, il y aura un emballement thermique !!! jusqu'à ~85°C dans votre exemple si vous utilisez ce thermostat/klixon.

Il faut surveiller la température et mettre en place des systèmes d'alerte en cas d'anomalie : température hors plage, température trop élevée ou trop base par rapport à consigne par exemple.

Sauf erreur de ma part, le thermostat / klixon se monte en série sur la phase du chauffage pour couper le chauffage sans contrôle logiciel (en cas de défaillance du contrôleur par ex.).

J'ai un doute car dans votre code, vous déclarez une variable d'entier que vous n'utilisez pas (avez-vous prévu ça pour surveiller le thermostat/klixon ?) :
int Theater=analogRead(A0); //temperature de securité sur le metal du radiateur

Pour l'hystérésis, vous arrêtez la chauffage à consigne +1°C.. dans une logique de chauffage je fais plutôt l'inverse, c'est-à dire que pour cet exemple, je redémarrerais le chauffage à consigne moins 1°C et je l'arrête précisément à la consigne, car je veux que ma consigne soit respectée et que le chauffage ne redémarre pas intempestivement.

Dans la pièce de ~30m² que je chauffe de temps en temps avec un 'bain d'huile' de 2000w, j'utilise un hystérésis de 0.2°C, la pièce est bien isolé, donc le chauffage ne redémarre pas souvent et c'est agréable (température constante).

Il faudrait aussi surveiller le potentiomètre de consigne, car un fil débranché et une broche en l'air ne retourne généralement pas une valeur nulle.. on est pas non plus à l'abri d'un potard qui rend l'âme..

J'ai testé votre code avec un potentiomètre, la consigne peut varier de 0 à 40°C, mais si je débranche le fil du curseur, l'arduino uno me retourne une consigne de 3°C..

Dans ce cas particulier, la défaillance du potentiomètre ou un fil débranché n'aura pas de graves conséquences, si ce n'est de désactiver le relais. Il faut quand même informer "l'opérateur" d'une manière ou d'une autre.

On peut ajouter une résistance pul down (10k par ex) entre la broche de lecture du curseur du potentiomètre et GND, la consigne retournée sera de 0° et là on peut une gérer une erreur ou une indication visuelle d'état (led, écran ..).

Je conseille aussi de surveiller le GND du potentiomètre.. On peut utiliser une broche libre, ça ne coûte rien, suffit de relier le GND du potentiomètre à une broche de l'arduino, d'ajouter une résistance de pull up entre la broche de surveillance et +5v, et de surveiller son état.

De cette manière, la plus grande partie des cas de figure sont envisagés.. défaillance du potentiomètre, défaillance de la sonde, relais collé / fondu, emballement thermique..

Pour le relais, le zéro crossing, je m'embête pas, j'utilise un relais SSR qui a déjà tout (https://fr.aliexpress.com/item/1005005837105164.html), grâce à l'optocoupleur je peux le piloter directement avec l'arduino.

Je vais quand même ajouter un "snubber" et une TVS car pendant mes tests, j'ai vu qu'en surveillant le GND du potentiomètre avec une broche digitale, il y a du bruit, assez pour faire flotter la broche d'un état à l'autre.

Au final, et pour toutes ces raisons, je suis passé sur un système un peu plus complexe avec un codeur rotatif où j'enregistre la consigne dans l'eprom en cas de coupure ou de redémarrage.

Voilà voilà

Bonne continuation !

3 Likes

SSR solid state relay, c’est la même chose que le triac avec son optocoupleur.
Il est vraiment pas cher sur votre lien….

Vous avez raison, le klixon est câblé en série, c’est une sécurité en plus du capteur de température LM 35 TO220 qui est sur le radiateur. Il est autour de 90°C suivant des essais que j’ai pu faire.

La régulation de température à 60°C est fait par un LM35 boitier TO220 sur l’entrée de l’ancienne simulation A0.

Ce n’est pas idiot, d’afficher des alarmes….

La consigne peut etre faite aussi via 2 boutons poussoirs et dans l’eprom c’est intelligent en cas de coupure d’electricité.

La simulation de la thermie n’est pas si viable avec Proteus car ce soft ne supporte pas de couper des alimentations de courant. D’ailleurs I2 devrait être à 0W mais il a fallu tricher et le mettre à -625Watt avec une mesure de courant AC alors qu’il devrait entre en DC. En trichant, la régulation de la simulation fonctionne ainsi qu’en pratique

Si vous avez des courbes de l’évolution de la température avec votre micro, ce serait intéressant….

On m’a donné aussi un radiateur de la marque Thomson avec la même l’alimentation défectueuse que julien à présenter
Merci pour vos liens,
Sur ce radiateur dès que le triac est alimenté, l’alimentation du micro chute avec un reset.

Voici le PCB du relais static, pour les personnes qui veulent souder


j’ai commandé des TTGO, mais en attendant j’ai fait des essais avec 1 uno et un afficher LCD keypad que je vais mettre sur ce radiateur Thomson.
On peut observer que la puissance moyenne de l’afficheur LCD est identique à la puissance dans la resistance thermique de la convection du radiateur lorsque la regulation est à 60°C.

Voici la courbe de la simulation avec la puissance moyenne qui diminue lorsque la temperature de la piece est à 20°C pour converger vers la valeur suivante 45W=P=(1/0.22) (20-10)

Pour rechauffer la piece simuler, il faut l’énergie suivante
Energy (W.h)=Cth(J/°C).(Delta Temp)/(3600)=32000.(20°C-10°C)/3600=88W.h=
Pour mettre en chauffe le radiateur
Energy (W.h)=Cth.(DT)/3600=200.(60-10)/3600=3.8W.h

Voici le nouveau code

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int Theater;
int Theater1;

int Temp;
int Sensor; 

int consigne1;
int consigne=20;
int unsigned long Pmoy;
int unsigned long Pmoy1;
int unsigned long Pmoy2;
int unsigned long Pmoy3;
int unsigned long Energy=0;


void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;
  
  Sensor = analogRead(A2);  //temperature en bas du radiateur mesurant l'atmospfere  
  Temp = Sensor/2;          // Storing value in Degree Celsius      0.18V*(1023/5V)*(500/1023)=18°C
  
  
  if(Temp < consigne)   {digitalWrite(13,1);}  //Turn ON the Heater  regulation room
  if(Temp>(consigne+1)) {digitalWrite(13,0);}   //

  if (Theater1 >60)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<7) {digitalWrite(13,1);}  

 if (digitalRead(13)== 1) {Energy=Energy+1;}  

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

EEPROM.get(5, consigne);
}




void loop() 
{

  int buttonValue = analogRead(A0);  //antirebond et vibration switch
  
  if (buttonValue==0  && buttonValue==0) {  //right
   consigne1=analogRead(A3);   // temperature desirée potentiometre
  consigne=(consigne1*4)/102;  //50%=>2.5V=>20°C
 EEPROM.put(5, consigne);
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down
  } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
}   
   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
      
    lcd.setCursor(0, 0);
    lcd.print("T:");    
    lcd.print(Temp);
    lcd.print("   ");  
    lcd.setCursor(6, 0);
    lcd.print("Cons");    
    lcd.print(consigne);
    lcd.print("   "); 
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print("   ");  
    lcd.setCursor(6, 1);  
    lcd.print("P:"); 
    lcd.print(Pmoy);
    lcd.print("   ");   

    Pmoy=(Energy*1000)/temps;
if (temps<3600) {Pmoy1=Pmoy;}  //puissance moyenne pour la heure
if (temps==3600) {Energy=0;}                
if (temps>3600 && temps<7200) {Pmoy2=Pmoy;}
if (temps==7200) {Energy=0;}  
if (temps>7200 && temps<10800) {Pmoy3=Pmoy;}
if (temps==10800) {Energy=0;temps=0;} 
Serial.print(Theater1);Serial.print(";");Serial.print(Temp);Serial.print(";");Serial.print(Pmoy);Serial.print(";");Serial.print(Energy);
Serial.println(";");
seconde=0;
            }
}//fin loop

En pratique, c’est un peu pénible de laisser le PC allumé, pour lire les dynamiques thermiques venant de l’arduino

Mais avec un HC06 bluetooth, il est possible de commander le radiateur et de voir les dynamiques du radiateur via l’application suivante qui est une supervision
https://www.keuwl.com/apps/bluetoothelectronics/
Mais il faut laisser le telephone à moins de 5 m du radiateur.

5 Likes

Au sujet de l’hystérésis,

  • 1°C pour la régulation du radiateur à 60°C, l’écart est négligeable. Sachant qu’il n’y a pas de régulation mais plutôt une limite qui est fait dans le programme. Mais il aurait été possible de faire une régulation. La fluctuation autour de 60°C est très faible dans notre cas et va dépendre de la puissance max et inertie du radiateur…
  • Par contre, 1°C d’hystérésis pour une consigne de 20°C donne une précision faible.
    Si on diminue la valeur de l’hystérésis à 0.1V,
    Est-ce que la température du radiateur va moins fluctuer ?
    La simulation dit que NON

Pour une hystérésis à virgule, il faut aussi améliorer la précision du capteur LM35 est à 0.5°C près avec l’analogreference à 5V du convertisseur analogique numérique. Mais avec la référence à 1.1V, la précision de la mesure passe à 0.1V.
Le LM35 est un capteur donnant une tension de 10mV/°C donc avec un voltmètre, il est possible de connaitre la température. Par contre, cette tension peut être bruité avec une précision à 0.1V. Donc la température de l’air a été filtré par un moyenneur.

Voici le nouveau code avec les boutons poussoirs pour augmenter la consigne avec les boutons poussoirs

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
float Theater;
float Theater1;

float Temp;
float Sensor; 
float Sensor1=21;
float Sensor2=21;
float Sensor3=21;
float Sensor4=21;

float consigne1;
float consigne=20;
int unsigned long Pmoy;
int unsigned long Pmoy1;
int unsigned long Pmoy2;
int unsigned long Pmoy3;
int unsigned long Energy=0;


void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/9.3;
  
  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  
  Sensor4=Sensor3;
  Sensor3=Sensor2;
  Sensor2=Sensor1;
  Sensor1 = Sensor/9.3;          // Storing value in Degree Celsius      0.2V*(1023/1.1V)/(9.3)=18°C
  Temp=(Sensor1+Sensor2+Sensor3+Sensor4)/4;
  
  if(Temp <consigne)   {digitalWrite(13,1);}  //Turn ON the Heater  regulation room
  if(Temp>(consigne+0.2)) {digitalWrite(13,0);}   //

  if (Theater1 >45)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}  

 if (digitalRead(13)== 1) {Energy=Energy+1;}  

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt


 analogReference(INTERNAL);
EEPROM.get(5, consigne);

}




void loop() 
{

// analogReference( DEFAULT );
int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue==0) {  //right
//   consigne1=analogRead(A3);   // temperature desirée potentiometre
//  consigne=(consigne1*4)/102;  //50%=>2.5V=>20°C
  consigne=consigne-0.1;
  if (consigne<=5) {consigne=5;}
     delay(100);
 EEPROM.put(5, consigne);
} 
  
  if (buttonValue > 450 && buttonValue < 680) {       // UP:   454   681    100  150
   consigne=consigne+0.1;
   if (consigne>=30) {consigne=30;}
   delay(100);
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
}   
   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
      
    lcd.setCursor(0, 0);
    lcd.print("T:");    
    lcd.print(Temp,2);
    lcd.print("   ");  
    lcd.setCursor(7, 0);
    lcd.print("Cons");    
    lcd.print(consigne,1);
    lcd.print("   "); 
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1,0);
    lcd.print("   ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy);
    lcd.print("    ");   

    Pmoy=(Energy*1000)/temps;
if (temps<3600) {Pmoy1=Pmoy;}  //puissance moyenne pour la heure
if (temps==3600) {Energy=0;}                
if (temps>3600 && temps<7200) {Pmoy2=Pmoy;}
if (temps==7200) {Energy=0;}  
if (temps>7200 && temps<10800) {Pmoy3=Pmoy;}
if (temps==10800) {Energy=0;temps=0;} 
Serial.print(Theater1,0);Serial.print(";");Serial.print(Temp);Serial.print(";");Serial.print(Pmoy);Serial.print(";");Serial.print(Energy);
Serial.println(";");
seconde=0;
            }
}//fin loop

La dynamique du radiateur inertiel Thomson de 1000W est de 1800 secondes qui a été testé sans les régulations dans un premier temps.


Étant donné que le capteur LM35 est sur une de ces ailettes et pas à l'intérrieur, il y a un retard important de la mesure de 150secondes.
Il y a aussi une différence de température de 15°C entre les parties les plus chaudes et la température de l’ailette du radiateur.

Donc, la valeur de la température max de la mesure du radiateur a été descendu à 45°C.

On peut observer la régulation de température du radiateur à 1°C près et toujours avec une hystérésis de 0.2°C de la temperature de l'air, avec sa fluctuation du au retard avec une base de temps de 1seconde. La puissance moyenne fluctue aussi, c’est pour cela qu’elle a été fixée sur une heure mais on pourrait aussi la filtrer
Par conséquent entre le modèle pratique et le modèle théorique, il y a des petites différences.

Sur la courbe d’essai précédente malgré analog refecence interne de 1.1V, on peut observer que lorsqu’il y a une commutation du chauffage (relais) , il y a une fluctuation des temperatures du à la baisse de tension de l’alimentation USB qui n’est pas bien régulé.
cette devrait disparaitre avec le relais statique.

La puissance moyenne autour de 45°C est de 500Watt, donc la puissance du radiateur de 1000W est loin d’être utilisé pleinement. Il faudrait un mode boost pour réchauffer plus rapidement la pièce sans réguler à 45°C mais à 65°C pour une sécurité faible mais toujours là.
La résistance thermique du radiateur inertiel peut être déterminé
RTHheateur (°C/W)=(Temp_heater-Temp_air)/Pmoy(W)=(45°C-16°C)/500W=0.058

Étant donné que la température de la mesure de l’air n’a pas trop bougé et fluctue la résistance thermique de la pièce pour connaitre son isolation ne peut pas etre determinée.

En conclusion : le programme entre un radiateur séche serviette pas inertiel, un radiateur fluide inertiel, un radiateur rayonnant sera différent.

5 Likes

Pour bien comprendre la régulation de température, il est possible de simuler sous Scilab ou Simulink, les dynamique de la température de l’air et du radiateur avec et sans le retard de la mesure de température.

Étant donné que l’échantillonnage de la mesure du programme Arduino est de 1 seconde donc très faible par rapport aux constantes de temps thermique, ce n’est pas la peine de faire une simulation discrétisée.

Sur la figure suivante, il y a seulement la régulation de température de l’air à 20°C.
La courbe verte correspond à la puissance de 1000W mais avec un rapport de 20 commander par l’hystérésis de 0.2°C, la courbe en jaune est la température métallique du radiateur, la courbe rouge est la température de l’air, la courbe noir est celle de l’energy
La température externe est de 10°C.

Avec les constantes de temps choisies, on peut observer que la température du radiateur n’atteint une temperature importante, donc avec la deuxième régulation à 60°C prioritaire permet de limiter la temperature du radiateur

Par contre avec un retard de la mesure de la température du radiateur de 20 secondes, il y a évidemment une fluctuation de la température du radiateur très importante, comme on peut l’observer sur la figure suivante mais avec moins de commutation.

De plus, si l’on ajoute un retard de la mesure de l’air de 5s, les dynamiques changent aussi.
Il faut savoir qu’un LM 35 a une constante de temps de 5s en boitier To 92.
Plus un capteur de température est petit et plus et plus sa constante de temps est faible.
Dans les radiateurs que j’ai ouvert, il y a beaucoup de très petites thermistances CTN de 10kohms non linéaire qui sont utilisées avec de la gaine thermo dessus et sur leurs broches avec une constante de temps faibles.

Avec une hystérésis de 1°C à la place de 0.2°C et toujours les temps retard mais avec une valeur maximale paramétrer à 45°C de la température du radiateur, dans ce cas, le temps est évidement légèrement plus long pour que l’air atteigne 20°C mas la température max du radiateur est bien plus faible comme on peut l’observer sur la figure suivante

Voici un nouveau code avec le temps qui se déroule, avec 4 menus d’affichages ou l’on peut régler le temps de fonctionnement, avec toutes les horloges réglables via les boutons up et down.
En prenant, l’horloge peut avoir des dérives dans le temps donc il faut la régler tous les 6 mois ou a chaque arret d’alimentation.

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

int unsigned Temp;
int unsigned Sensor; 
int unsigned Sensor1=21;
int unsigned Sensor2=21;
int unsigned Sensor3=21;
int unsigned Sensor4=21;

int unsigned consigne1;
int unsigned consigne=20;

int unsigned long Pmoy;
int unsigned long Pmoy1;
int unsigned long Pmoy2;
int unsigned long Pmoy3;
int unsigned long Energy=0;

byte menu;
byte seconde1;
int signed  minute1=0, minute2=0, minute3=30;
int signed heure1=0, heure2=0, heure3=1;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;
  
  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  
  Sensor4=Sensor3;
  Sensor3=Sensor2;
  Sensor2=Sensor1;
  Sensor1 = Sensor/2;          // Storing value in Degree Celsius      0.2V*(1023/1.1V)/(9.3)=18°C
  Temp=(Sensor1+Sensor2+Sensor3+Sensor4)/4;

  if ((heure1>=heure2)  && (minute1>=minute2))    {    //regulation temperature radiateur ON
  if(Temp <consigne)   {digitalWrite(13,1);}  //Turn ON the Heater  regulation room
  if(Temp>(consigne+1)) {digitalWrite(13,0);}   //

  if (Theater1 >45)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}     //hors gel

 if (digitalRead(13)==1) {Energy=Energy+1;}    }  //fin de regulation

  if ((heure1>=heure3)  && (minute1>=minute3))   {  //radiateur OFF
  digitalWrite(13,0);  }

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
EEPROM.put(5, consigne);

EEPROM.get(5, consigne);

}




void loop() 
{


int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //right

} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=4) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T:");    
    lcd.print(Temp);
    lcd.print("   ");  
    lcd.setCursor(7, 0);
    lcd.print("Cons");    
    lcd.print(consigne);
    lcd.print("   "); 
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print("   ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy);
    lcd.print("    ");
    lcd.setCursor(13, 1);  
if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s     ");     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;} 
                  
    Pmoy=(Energy*1000)/temps;
if (temps<3600) {Pmoy1=Pmoy;}  //puissance moyenne pour la heure
if (temps==3600) {Energy=0;}                
if (temps>3600 && temps<7200) {Pmoy2=Pmoy;}
if (temps==7200) {Energy=0;}  
if (temps>7200 && temps<10800) {Pmoy3=Pmoy;}
if (temps==10800) {Energy=0;temps=0;} 
Serial.print(Theater1);Serial.print(";");Serial.print(Temp);Serial.print(";");Serial.print(Pmoy);Serial.print(";");Serial.print(Energy);
Serial.println(";");
seconde=0;
            }
}//fin loop

Seulement 17% de la mémoire de l’atmel 328 est utilisée, donc il est possible de faire un code avec un horodateur de fonctionnement de la semaine

5 Likes

Merci pour l'aide.

Sur la courbe suivante, l’hystérésis de 1°C, avec 65°C de température max, alors que la température de l’air est à 18°C,
Il a fallu rajouter 3°C aux mesures de températures suite à l’interaction de l’alimentation sur les capteurs LM35.
Sachant que la tension USB est variée avec les valeurs suivantes :

  • 5.11V pour un courant de 0.11A lorsque le relais est à l’état off
  • 5.04V pour un courant de 0.19A lorsque le relais est à l’état on

Un mode boost a été ajouté via le bouton right pour avec une température de sécurité de 65°C à la place de 45°C.
Sachant que la température max du radiateur inertiel atteindra aux maximum 87°C juste sur le dessus

Voici la courbe de la dynamique de la température avec le radiateur inertiel qui est stable maintenant par rapport à la commutation sans le filtrage moyen de la température de l’air. La fluctuation de la mesure est de 19°C à 21°C.

Dans la salle ou il y a les essais, il n’y a pas qu’un seul radiateur donc l’influence de la température de l’air peut varier aussi par rapport à la puissance des autres radiateurs.

Avec juste le filtre moyenner sur 4 seconde, la température de l’air est légèrement plus constante mais pas encore assez filtré.

Avec une fréquence d’échantillonnage de 1seconde et un choix de fréquence de coupure de 0.03s donc une constante de 33s, avec un filtre du deuxième ordre numérique dont les coefficients sont déterminés ici.

Avec ce filtre, la température de l’air varie maintenant de 1.28°C à la place de 3°C comme avant ce qui est honorable.

Voici le nouveau code avec le mode boost et ce filtrage du deuxième ordre

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

 float Temp;
 float Sensor;
 float Sensor1=40;  //20°C*2
 float Sensor2=40;

 float sortie=5300;
 float sortie1=5320;  //40*133
 float sortie2=5320;
 float out;
           
       const float a1 =-1.73;
       const float a2 =0.76;
       const float Gain =133;


int unsigned consigneSecu=45;
int unsigned consigne=22;

int unsigned long Pmoy;
int unsigned long Pmoy1;
int unsigned long Pmoy2;
int unsigned long Pmoy3;
int unsigned long Energy=0;

byte menu;
byte seconde1;
int signed  minute1=0, minute2=0, minute3=30;
int signed heure1=0, heure2=0, heure3=6;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;
  if (digitalRead(13)==1) {Theater1=Theater1+3 ;}    //correction alimentation  
  
  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  
  if (digitalRead(13)==1) {Sensor=Sensor+6;}   //conpensation
  Sensor2=Sensor1;      //entree(n-2)
  Sensor1=Sensor;       //entree(n-1)

  sortie2=sortie1;      //sortie(n-2)
  sortie1=sortie;       //sortie(n-1)

  sortie=(Sensor+Sensor1*2+Sensor2-sortie1*a1-sortie2*a2) ;    //filtre passe pas recursif ordre 2
  out=(sortie/Gain);    //gain du filtre
  Temp=out/2;           //pour avoir la temperatuere

  if ((heure1>=heure2)  && (minute1>=minute2))    {    //regulation temperature radiateur ON
  if(Temp <consigne)   {digitalWrite(13,1);}  //Turn ON the Heater  regulation room
  if(Temp>(consigne+1)) {digitalWrite(13,0);}   //conpensation

  if (Theater1>consigneSecu)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}     //hors gel

 if (digitalRead(13)==1) {Energy=Energy+1;}    }  //fin de regulation

  if ((heure1>=heure3)  && (minute1>=minute3))   {  //radiateur OFF
  digitalWrite(13,0);  }

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
//EEPROM.put(5, consigne);

//EEPROM.get(5, consigne);

}




void loop() 
{


int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //button right
  if (consigneSecu==45) {consigneSecu=65;delay(300);}
  if (consigneSecu==65) {consigneSecu=45;delay(300);}
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=4) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T:");    
    lcd.print(Temp,1);
    lcd.print(" ");  
    lcd.print("C:");    
    lcd.print(consigne);
    lcd.print(" ");
    lcd.print("CS:");    
    lcd.print(consigneSecu);
    lcd.print("  ");    
    
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print(" ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy);
    lcd.print(" ");
    lcd.setCursor(13, 1);  
if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
    lcd.print("  ");
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s     ");     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;} 
                  
    Pmoy=(Energy*1000)/temps;
if (temps<7200) {Pmoy1=Pmoy;}  //puissance moyenne pour 2 heures
if (temps==7200) {Energy=0;}                
if (temps>7200 && temps<10800) {Pmoy2=Pmoy;}   //puissance moyenne pour 1 heures
if (temps==10800) {Energy=0;}  
if (temps>10800 && temps<18000) {Pmoy3=Pmoy;}  //puissance moyenne pour 2 heures
if (temps==18000) {Energy=0;temps=0;} 
Serial.print(Theater1);Serial.print(";");Serial.print(Temp,1);Serial.print(";");Serial.print(Pmoy);
Serial.println(";");
seconde=0;
            }
}//fin loop

il faudrait quand meme essayer un filtre du troisieme ordre, pour faire une comparaison

4 Likes

On a essayé de faire un troisième ordre mais le calcul du filtre diverge…à cause des 7 chiffres significatifs du compilateur.
En effet, plus le gain sera important et plus il faudra de chiffres significatifs aux coefficients.
On a essayé des valeurs de fréquence de coupure plus faible que dans le post précèdent pour savoir si les fluctuations de température de l’air sont plus atténuer

On peut observer que si les valeurs initiales du filtre ne sont pas correctes, il faudra un certain temps pour que la valeur de la mesure de l’air soit correcte. Donc, on a modifié le programme pour que les valeurs initiales soit au plus proche de la valeur réelle.


Lorsque la température de l'air est proche de la consigne (ici 20°C), on peut observer que c’est la fluctuation de la mesure de cette température de l’air qui provoque le fonctionnement tout ou rien de la chauffe. Donc, la valeur de l’hystérésis ne sert à rien, elle peut etre nulle.
La puissance moyenne tourne autour de 200Watt au bout de 2 heures seulement.
La valeur puissance moyenne devrait être calculer seulement lorsque la température a atteint sa consigne sinon il y a le calcul de la puissance pour charger les capacités thermiques de la pièce qui va biaiser le calcul de l'isolation de la résistance thermique.

Voici le nouveau code avec différents filtrages du second ordre, hystérésis nul et puissance moyenne

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

 float Temp;
 float Sensor;
 float Sensor1=40;  //20°C*2
 float Sensor2=40;
 float Sensor3=40;

 float sortie=40000;
 float sortie1=40000;     //    20°C*2*133=5320
 float sortie2=40000;
 float sortie3=40000;
 float out;
           
/*     const float a1 =-1.73;   //2eme ordre   Fc=0.03Hz   33s
     const float a2 =0.76;     //init 5320
     const float Gain =133;   */

/*    const float a1 =-1.911;   //2eme ordre  Fc=0.01Hz   100s
     const float a2 =0.915;     //init 40 000
     const float Gain =1000;   */    //convergence

     const float a1 =-1.928;   //2eme ordre  Fc=0.008Hz   125s
     const float a2 =0.931;     //init 40 000
     const float Gain =1333;    
     

 /*   const float a1 =-1.9378;   //2eme ordre  Fc=0.007Hz   142s
     const float a2 =0.9369;   // init 170 000 
     const float Gain =4444;   //divergence     
*/
     
  
/*       const float a1 =-0.278;   //3eme ordre
       const float a2 =1.18;
       const float a3 =-1.76;
       const float Gain =55;   */


int unsigned consigneSecu=45;
 float consigne=20;

int unsigned long Pmoy;
int unsigned long Pmoy1;
int unsigned long Pmoy2;
int unsigned long Pmoy3;
int unsigned long Energy=0;

byte menu;
byte seconde1;
int signed  minute1=0, minute2=0, minute3=30;
int signed heure1=0, heure2=0, heure3=6;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;
  if (digitalRead(13)==1) {Theater1=Theater1+3 ;}    //correction alimentation  
  
  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  
  if (digitalRead(13)==1) {Sensor=Sensor+6;}   //conpensation
  Sensor3=Sensor2;      //entree(n-3)
  Sensor2=Sensor1;      //entree(n-2)
  Sensor1=Sensor;       //entree(n-1)

  sortie3=sortie2;      //sortie(n-3)
  sortie2=sortie1;      //sortie(n-2)
  sortie1=sortie;       //sortie(n-1)


//sortie=Sensor+Sensor1*3+Sensor2*3+Sensor3-sortie1*a1-sortie2*a2-sortie3*a3 ;   //filtre passe pas recursif ordre 3
  sortie=(Sensor+Sensor1*2+Sensor2-sortie1*a1-sortie2*a2) ;                      //filtre passe pas recursif ordre 2
  out=(sortie/Gain);    //gain du filtre
  Temp=out/2;           //pour avoir la temperatuere

  if ((heure1>=heure2)  && (minute1>=minute2))    {    //regulation temperature radiateur ON
  if(Temp<consigne)     {digitalWrite(13,1);}     //Turn ON the Heater  regulation  air room
  if(Temp>(consigne+0)) {digitalWrite(13,0);}   //hysteresis   Turn off

  if (Theater1>consigneSecu)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}     //hors gel

 if (digitalRead(13)==1) {Energy=Energy+1;} 
// if ((Temp<consigne-1) && (Temp>consigne+1) {Energy=0;}  //ne prend pas en compte l'energie des capactiés
 
 }  //fin de regulation

  if ((heure1>=heure3)  && (minute1>=minute3))   {digitalWrite(13,0);}   //radiateur OFF

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
//EEPROM.put(5, consigne);

//EEPROM.get(5, consigne);

//initilisation du filtre
Sensor = analogRead(A3);
Sensor1=Sensor;
Sensor2=Sensor;
Sensor3=Sensor;

sortie=Sensor*Gain;
sortie1=sortie; 
sortie2=sortie;
sortie3=sortie; 
}




void loop() 
{


int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //button right
  if (consigneSecu==45) {consigneSecu=65;delay(300);}
  if (consigneSecu==65) {consigneSecu=45;delay(300);}
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+0.1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-0.1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=4) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T:");    
    lcd.print(Temp,1);
    lcd.print(" ");  
    lcd.print("C:");    
    lcd.print(consigne,0);
    lcd.print(" ");
    lcd.print("CS");    
    lcd.print(consigneSecu);
    lcd.print("  ");    
    
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print(" ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy);
    lcd.print(" ");
    lcd.setCursor(13, 1);  
if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
    lcd.print("  ");
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s     ");     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;} 
                  
    Pmoy=(Energy*1000)/temps;     
if (temps<7200) {Pmoy1=Pmoy;}  //puissance moyenne pour 2 heures
if (temps==7200) {Energy=0;}                
if (temps>7200 && temps<14400) {Pmoy2=Pmoy;}   //puissance moyenne pour 2 heures
if (temps==144000) {Energy=0;temps=0;} 

Serial.print(Theater1);Serial.print(";");Serial.print(Temp,2);Serial.print(";");Serial.print(Pmoy);
Serial.println(";");
seconde=0;
            }
}//fin loop
4 Likes

On a déporté de 10cm le capteur de température de la mesure de l’air par rapport au radiateur mais cela n’a pas changé grand-chose comme on peut l’observer sur la figure suivante ou l’on a grossi la fluctuation de la température de l’air filtré en retirant la valeur de la consigne mois 2°C. donc la consigne était de 19.1°C. sur la courbe suivante, on peut observer l’influence de l’alimentation qui provoque une temps de retard entre la température du radiateur sur la température de l’air qui est de l’ordre de 500s à partir de 45°C
Par contre dès que l’alimentation se coupe, la température du radiateur dimimue jusque 35°C et la température de l’air chute brutalement de 0.5°C.

Sur la figure précédente, on peut observer que la valeur de la puissance moyenne fluctue avec une amplitude de 50W.
De plus, lorsque la consigne de température est atteinte, cette fluctuation peut être plus importante.

Donc, pour avoir une puissance moyenne plus précise et moins fluctuante, celle-ci est filtré avec un temps d’échantillonnage de 10s avec une constante de temps d’un filtre du second ordre de 1250s comme on peut le voir sur la figure suivante

Remarque : le filtre de la puissance moyenne provoque un léger retard, puis lorsque la puissance moyenne est identique à la valeur de la puissance moyenne filtrée on peut considérer que celle-ci est viable pour avoir la consigne désirée de l’air ou du radiateur.
Évidement la courbe permet de mieux évaluer la valeur de la puissance moyenne ainsi que si c’est l’asservissement de l’air ou de la température du radiateur qui est pris en compte.

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

 float Temp;
 float Sensor;
 float Sensor1=40;  //20°C*2
 float Sensor2=40;


 float sortie=40000;
 float sortie1=40000;     //    20°C*2*133=5320
 float sortie2=40000;
 float out;
           
     const float a1 =-1.928;   //2eme ordre  Fc=0.008Hz   125s
     const float a2 =0.931;     //mesure temperature Air
     const float Gain =1333;    

int unsigned consigneSecu=45;
    float consigne=20;

 float Pmoy;
 float Pmoy1;
 float Pmoy2;
 float power;
 float power1;
 float power2;
 float powerA;

 float Energy=0;


     const float a11 =-1.73;   //2eme ordre   Fc=0.03Hz   33s
     const float a21 =0.76;     //filtrage de la puissance moyenne
     const float Gain1 =133;   

byte menu;
byte seconde1;
byte seconde10;
int signed  minute1=0, minute2=0, minute3=30;
int signed heure1=0, heure2=0, heure3=6;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;
  if (digitalRead(13)==1) {Theater1=Theater1+3 ;}    //correction alimentation  
  
  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  
  if (digitalRead(13)==1) {Sensor=Sensor+6;}   //conpensation
  Sensor2=Sensor1;      //entree(n-2)
  Sensor1=Sensor;       //entree(n-1)

  sortie2=sortie1;      //sortie(n-2)
  sortie1=sortie;       //sortie(n-1)

  sortie=(Sensor+Sensor1*2+Sensor2-sortie1*a1-sortie2*a2) ;                      //filtre passe pas recursif ordre 2
  out=(sortie/Gain);    //gain du filtre
  Temp=out/2;           //pour avoir la temperature sensibilité du LM35

  if ((heure1>=heure2)  && (minute1>=minute2))    {    //regulation temperature radiateur ON
  if(Temp<consigne)     {digitalWrite(13,1);}     //Turn ON the Heater  regulation  air room
  if(Temp>(consigne+0)) {digitalWrite(13,0);}   //hysteresis   Turn off

  if (Theater1>consigneSecu)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}     //hors gel

 if (digitalRead(13)==1) {Energy=Energy+1;} 
// if ((Temp<consigne-1) && (Temp>consigne+1) {Energy=0;}  //ne prend pas en compte l'energie des capactiés
 
 }  //fin de regulation

  if ((heure1>=heure3)  && (minute1>=minute3))   {digitalWrite(13,0);}   //radiateur OFF

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
//EEPROM.put(5, consigne);

//EEPROM.get(5, consigne);

//initilisation du filtre
Sensor = analogRead(A3);
Sensor1=Sensor;
Sensor2=Sensor;

sortie=Sensor*Gain;
sortie1=sortie; 
sortie2=sortie;
 
}




void loop() 
{


int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //button right
  if (consigneSecu==45) {consigneSecu=65;delay(300);}
  if (consigneSecu==65) {consigneSecu=45;delay(300);}
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+0.1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-0.1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=4) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T");    
    lcd.print(Temp,1);
    lcd.print(" ");  
    lcd.print("C");    
    lcd.print(consigne,1);
    lcd.print(" ");
    lcd.print("S");    
    lcd.print(consigneSecu);
    if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
    lcd.print("  ");    
       
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print(" ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy,0);
    lcd.print(" ");
    lcd.print(powerA,0);
    lcd.print("  ");

    lcd.print("  ");
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s     ");     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;} 
                  
    Pmoy=(Energy*1000)/temps; 
      
 seconde10++;
 if (seconde10>=10) {
      Pmoy2=Pmoy1;      
      Pmoy1=Pmoy;  
      power2=power1;     
      power1=power;      

      power=(Pmoy+Pmoy1*2+Pmoy2-power1*a1-power2*a2) ;   //filtrage pour avoir une puissance moyenne fe=0.1s avec une frequece de coupure fc=1/1250hz
      powerA=power/Gain;  
      seconde10=0;    }  

Serial.print(Theater1);Serial.print(";");Serial.print(Temp,2);Serial.print(";");Serial.print(Pmoy,0);Serial.print(";");Serial.print(powerA,0);
Serial.println(";");
seconde=0;
            }
}//fin loop
4 Likes

Si je peux me permettre un commentaire, j'ai l'impression que tu utilises la librairie plot de Python ?
Si c'est le cas la fonction scatter, permet de définir la taille du point.
Ce qui rendrait tes graphiques plus lisible, je pense.

1 Like

Le plot vient de Excel en prenant les valeurs du moniteur du compilateur, via un fichier .CSV
Effectivement, avec 1 chiffre après la virgule, il est possible d’avoir des courbes plus affinées.
Mais pas avec la courbe de la mesure de température du radiateur ou l’on n’a pas besoin de précision et qui n’a pas à virgule avec une précision de la mesure du LM35 à 0.5°C , il y aura
toujours des fluctuations


Mais, il est possible d’utiliser une NTC (Negative Temperature Coefficient) de de 10kohms à 25°C, via une résistance de pull up pour mesurer l’air qui devrait avoir moins de variation dû à une fluctuation de la tension d’alimentation car la tension de référence est identique à l’alimentation.

Le choix de la NTC à 25°C de 10kohms consommera un petit courant de l’alimentation. Pour avoir la meilleure sensibilité à la température désirer, il faut que la résistance de pull up est la même valeur que la NTC, on choisira arbitrairement la température à 25°C.

Il n’y a pas besoin de pont Wheatstone pour retirer l’offset de la mesure pour augmenter la précision et avoir un amplificateur pour augmenter la sensibilité.

Avec un ohmmètre, il est très facile de tester le bon fonctionnement de la NTC si la régulation ne fonctionne plus.

Une petite permet d’être monter sur le PCB et d’avoir une constante de

Les équations d’une CTN par l’équation de beta sont présentées ici.


Il y a des liens pour déterminer beta et la programmation de la température

Il n’est pas utile de passer par l’équation inverse de la température avec le log népérien comme sur lien suivant car il est possible de linéariser l’équation sur une plage de température comme on peut l’observer sur la figure suivante.

Dans Proteus, la valeur de la température ainsi que beta pour la NTC ne peuvent être changé pendant la simulation. Il faut le faire avant.
Donc, la régulation de la temperature ne peut se faire avec la NTC
Il est juste possible de vérifier la mesure de la température par le programme, puis de passer à la pratique pour la regulation


Voici le nouveau code

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

 float Temp;
 float Sensor;
 float Sensor1=40;  //20°C*2
 float Sensor2=40;


 float sortie=40000;
 float sortie1=40000;     //    20°C*2*133=5320
 float sortie2=40000;
 float out;
           
     const float a1 =-1.928;   //2eme ordre  Fc=0.008Hz   125s
     const float a2 =0.931;     //mesure temperature Air
     const float Gain =1333;    

int unsigned consigneSecu=45;
    float consigne=20;

 float Pmoy;
 float Pmoy1;
 float Pmoy2;
 float power;
 float power1;
 float power2;
 float powerA;

 float Energy=0;


     const float a11 =-1.73;   //2eme ordre   Fc=0.03Hz   33s
     const float a21 =0.76;     //filtrage de la puissance moyenne
     const float Gain1 =133;   

byte menu;
byte seconde1;
byte seconde10;
int signed  minute1=0, minute2=0, minute3=30;
int signed heure1=0, heure2=0, heure3=6;



void callback()  {    //interruption toutes les secondes
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;   //LM35
  if (digitalRead(13)==1) {Theater1=Theater1+3 ;}    //correction alimentation  
 
//  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  LM35
//  if (digitalRead(13)==1) {Sensor=Sensor+6;}   //conpensation

  Sensor = analogRead(A2);  //temperature en bas du radiateur mesurant Air  NTC
  Temp=-0.096*Sensor+75.5-1.7;

/*  Sensor2=Sensor1;      //entree(n-2)
  Sensor1=Sensor;       //entree(n-1)

  sortie2=sortie1;      //sortie(n-2)
  sortie1=sortie;       //sortie(n-1)

  sortie=(Sensor+Sensor1*2+Sensor2-sortie1*a1-sortie2*a2) ;                      //filtre passe pas recursif ordre 2
  out=(sortie/Gain);    //gain du filtre
  Temp=out/2;           //pour avoir la temperature sensibilité du LM35
*/

  if ((heure1>=heure2)  && (minute1>=minute2))    {    //regulation temperature radiateur ON
  if(Temp<consigne)     {digitalWrite(13,1);}     //Turn ON the Heater  regulation  air room
  if(Temp>(consigne+0)) {digitalWrite(13,0);}   //hysteresis   Turn off

  if (Theater1>consigneSecu)   {digitalWrite(13,0);  }  //regulation du radiateur

  if(Temp<5) {digitalWrite(13,1);}     //hors gel

 if (digitalRead(13)==1) {Energy=Energy+1;} 
// if ((Temp<consigne-1) && (Temp>consigne+1) {Energy=0;}  //ne prend pas en compte l'energie des capactiés
 
 }  //fin de regulation

  if ((heure1>=heure3)  && (minute1>=minute3))   {digitalWrite(13,0);}   //radiateur OFF

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
//EEPROM.put(5, consigne);

//EEPROM.get(5, consigne);

//initilisation du filtre
Sensor = analogRead(A3);
Sensor1=Sensor;
Sensor2=Sensor;

sortie=Sensor*Gain;
sortie1=sortie; 
sortie2=sortie;
 
}




void loop() 
{


int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //button right
  if (consigneSecu==45) {consigneSecu=65;delay(300);}
  if (consigneSecu==65) {consigneSecu=45;delay(300);}
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+0.1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-0.1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=4) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
Energy=0;Pmoy=0;
} 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T");    
    lcd.print(Temp,1);
    lcd.print(" ");  
    lcd.print("C");    
    lcd.print(consigne,1);
    lcd.print(" ");
    lcd.print("S");    
    lcd.print(consigneSecu);
    if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
    lcd.print("  ");    
       
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print(" ");  
    lcd.setCursor(6, 1);  
    lcd.print("P"); 
    lcd.print(Pmoy,0);
    lcd.print(" ");
    lcd.print(powerA,0);
    lcd.print("  ");

    lcd.print("  ");
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s     ");     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;} 
                  
    Pmoy=(Energy*1000)/temps; 
      
 seconde10++;
 if (seconde10>=10) {
      Pmoy2=Pmoy1;      
      Pmoy1=Pmoy;  
      power2=power1;     
      power1=power;      

      power=(Pmoy+Pmoy1*2+Pmoy2-power1*a1-power2*a2) ;   //filtrage pour avoir une puissance moyenne fe=0.1s avec une frequece de coupure fc=1/1250hz
      powerA=power/Gain;  
      seconde10=0;    }  

Serial.print(Theater1);Serial.print(";");Serial.print(Temp,2);Serial.print(";");Serial.print(Pmoy,0);Serial.print(";");Serial.print(powerA,0);
Serial.println(";");
seconde=0;
            }
}//fin loop

Un thermistor tel que kty81 PTC (positive Température Coefficient) qui est un capteur bon marché. Mais, l’erreur de mesure est de 5 à 6°C donc demande un étalonnage ce qui n’est pas judicieux industriellement.
Dans Proteus, il est possible de simuler une kty81, mais le capteur n’aura pas d’interaction avec le modèle thermique pour simuler l'asservissement

4 Likes

De mémoire dans Excel aussi, il est possible d'agir sur la taille des points et des lignes.

Oui, mais maintenant, la finesse des courbes sont correctes sans rien devoir changer.

Dans Excel, il est aussi possible d’avoir différents pointillé long, court…
D’ailleurs voici les courbes avec la CTN, sans hystérésis.
On peut observer que la température de l’air est bien plus constante qu’avec le LM35 qui était de 0.75°C alors que maintenant la fluctuation est de 0.25°C.
De plus, on peut observer que la courbe de la température de l’air suit plus la courbe de la puissance mais que les commutations sont plus rapprochés et nombreuses.
On peut observer qu’il y a aussi des fluctuations de températures d’airs du au mouvement près du radiateur. Donc, on a utilisé le filtre du deuxième ordre.
Voici les courbes de la régulation de la tempera rature en réel qui ne sont pas impactés par la fluctuation de la tension d’alimentation.


Pour minimiser les commutations, une hystérésis a donc été rajouté de 0.1°C, pour voir les différences.
la période de commutation est de 275 secondes ce qui est honorable sans nuire à la fluctuation de la temperarure de l'air autour de la consigne

si l'on veut garder le capteur de temperature qui est deja installé, il faut faire une mesure à l'ohmetre en interne et à l'exterrieur pour identifier ce qui a été installé

4 Likes

La programmation du radiateur (on, off) hebdomadaire est relativement facile mais elle demande de nombreux menu et de ligne de code et de variable

Voici la programmation que pour lundi et mardi pour ceux que cela intéresse et qu’il sera facile

La rom de l’atmel n’est que à 30% et la Ram à 23%

La routine d’interruption de 1 seconde dure 0.4ms donc sans soucis.

De même, le programme principale dure 0.112ms sauf quand il faut tout afficher et envoyer des données sur le port USB qui dure 14ms.

#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <EEPROM.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int unsigned temps=0;
int seconde=0;
int unsigned Theater;
int unsigned Theater1;

 float Temp;
 float Sensor;
 float Sensor1=40;  //20°C*2
 float Sensor2=40;


 float sortie=40000;
 float sortie1=40000;     //    20°C*2*133=5320
 float sortie2=40000;
 float out;
           
     const float a1 =-1.928;   //2eme ordre  Fc=0.008Hz   125s
     const float a2 =0.931;     //mesure temperature Air
     const float Gain =1333;    

int unsigned consigneSecu=45;
    float consigne=20;

 float Pmoy;
 float Pmoy1;
 float Pmoy2;
 float power;
 float power1;
 float power2;
 float powerA;

 float Energy=0;


     const float a11 =-1.73;   //2eme ordre   Fc=0.03Hz   33s
     const float a21 =0.76;     //filtrage de la puissance moyenne
     const float Gain1 =133;   

byte menu;
byte seconde1;
byte seconde10;
byte jour=0;
int signed  minute1=0, minute2=0, minute3=30,minute4=0,minute5=35,minute6=35,minute7=35;  //minute4  pour lundi  on et minute 5 lundi off
int signed heure1=0, heure2=0, heure3=6,heure4=0, heure5=2,heure6=0,heure7=2;;                               //minute6 pour mardi on on et minute 7 Mardi off

bool regule=0;




void callback()  {    //interruption toutes les secondes
  
  temps++;
  seconde++;
  seconde1++;
  Theater=analogRead(A1);      //temperature de securité sur le metal du radiateur TO220  
  Theater1=analogRead(A1)/2;   //LM35
  if (digitalRead(13)==1) {Theater1=Theater1+3 ;}    //correction alimentation  
 
//  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant l'atmospfere  LM35
//  if (digitalRead(13)==1) {Sensor=Sensor+6;}   //conpensation

  Sensor = analogRead(A3);  //temperature en bas du radiateur mesurant Air  NTC
  Sensor=-0.096*Sensor+100;

  Sensor2=Sensor1;      //entree(n-2)
  Sensor1=Sensor;       //entree(n-1)

  sortie2=sortie1;      //sortie(n-2)
  sortie1=sortie;       //sortie(n-1)

  sortie=(Sensor+Sensor1*2+Sensor2-sortie1*a1-sortie2*a2) ;                      //filtre passe pas recursif ordre 2
  out=(sortie/Gain);    //gain du filtre
//  Temp=out/2;           //pour avoir la temperature sensibilité du LM35
  Temp=out;

 if ((jour==0) &&  (heure1>=heure2)  && (minute1>=minute2))   {regule=1; }
 if ((jour==0) && (heure1>=heure3)  && (minute1>=minute3))   {regule=0;digitalWrite(13,0);}   //radiateur OFF
 if ((jour==1) &&  (heure1>=heure4)  && (minute1>=minute4))   {regule=1; }                           //lundi
 if ((jour==1) &&  (heure1>=heure5)  && (minute1>=minute5))   {regule=0;digitalWrite(13,0); }        //lundi
 if ((jour==2) &&  (heure1>=heure6)  && (minute1>=minute6))   {regule=1; }                          //mardi
 if ((jour==2) &&  (heure1>=heure7)  && (minute1>=minute7))   {regule=0;digitalWrite(13,0); }       //mardi

  if (regule==1)    {    //regulation temperature radiateur ON
    if(Temp<consigne)     {digitalWrite(13,1);}     //Turn ON the Heater  regulation  air room
    if(Temp>(consigne+0.1)) {digitalWrite(13,0);}   //hysteresis   Turn off

    if (Theater1>consigneSecu)   {digitalWrite(13,0);  }  //regulation du radiateur

    if(Temp<5) {digitalWrite(13,1);}     //hors gel

    if (digitalRead(13)==1) {Energy=Energy+1;} 
// if ((Temp<consigne-1) && (Temp>consigne+1) {Energy=0;}  //ne prend pas en compte l'energie des capactiés
 
 }  //fin de regulation

 
}  //fin callback




void setup() 
{
  pinMode(13,OUTPUT); //Set the Heater/Relay Pin as OUTPUT
  pinMode(10,OUTPUT); 
  digitalWrite(13,0);
  Serial.begin(57600);
  lcd.begin(16, 2);    // Initialisation du LCD
  
 Timer1.initialize(1000000);           // initialize timer1 1seconde, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(callback);   // attaches callback() as a timer overflow interrupt

// analogReference( DEFAULT );
//EEPROM.put(5, consigne);

EEPROM.get(5, consigne);

//initilisation du filtre
Sensor = analogRead(A3);
Sensor=-0.096*Sensor+100;
Sensor1=Sensor;
Sensor2=Sensor;

sortie=Sensor*Gain;
sortie1=sortie; 
sortie2=sortie;
}




void loop() 
{
if ( digitalRead(10)== 1 ) {digitalWrite(10,LOW);}  else {digitalWrite(10,HIGH);}

int buttonValue = analogRead(A0);  
 
  if (buttonValue==0  && buttonValue<=10 ) {  //button right
  if (consigneSecu==45) {consigneSecu=65;delay(300);}
  if (consigneSecu==65) {consigneSecu=45;delay(300);}
} 
  
  if (buttonValue > 100 && buttonValue < 150) {       // UP:  
  if (menu==0)   {consigne=consigne+0.1;delay(300); if (consigne>=30) {consigne=30;};EEPROM.put(5, consigne);}
  if (menu==1)   {minute1++;delay(200);if(minute1 >= 60){minute1 = 00; heure1++;} if(heure1>=24){heure1 =0;}  }   //reglage de l'heure
  if (menu==2)   {minute2++;delay(200); if(minute2 >= 60){minute2 = 00; heure2++;} if(heure2>=24){heure2 =0;} }   //reglage de l'heure  radiateur ON
  if (menu==3)   {minute3++;delay(200); if(minute3 >= 60){minute3 = 00; heure2++;} if(heure3>=24){heure2 =0;} }   // regalage heure radiateur off
  if (menu==4)  {minute4++;delay(100); if(minute4 >= 60){minute4 = 00; heure4++;} if(heure4>=24){heure4 =0;} }   //ON lundi
  if (menu==5)  {minute5++;delay(100); if(minute5 >= 60){minute5 = 00; heure5++;} if(heure5>=24){heure5 =0;} }  //off lundi
  if (menu==6)  {minute6++;delay(100); if(minute6 >= 60){minute6 = 00; heure6++;} if(heure6>=24){heure6 =0;} }   //ON mardi
  if (menu==7)  {minute7++;delay(100); if(minute7 >= 60){minute7 = 00; heure7++;} if(heure7>=24){heure7 =0;} }  //off mardi
 } 
  
   if (buttonValue > 290 && buttonValue < 320) {    //1.51=>310 Down    290   320
  if (menu==0)   {consigne=consigne-0.1;delay(300);   if (consigne<=5) {consigne=5;} EEPROM.put(5, consigne);}
  if (menu==1)   {minute1--;delay(200);if(minute1<0){minute1=60; heure1--;} if(heure1<0){heure1 =23;}}   //reglage de l'heure
  if (menu==2)   {minute2--;delay(200); if(minute2<0){minute2=60; heure2--;} if(heure2<0){heure2=23;} }
  if (menu==3)   {minute3--;delay(200); if(minute3<0){minute3=60; heure2--;} if(heure2<0){heure2 =23;} }
  if (menu==4)   {minute4--;delay(100); if(minute4<0){minute4=60; heure4--;} if(heure4<0){heure4=23;} }        //on lundi
  if (menu==5)   {minute5--;delay(100); if(minute5<0){minute5=60; heure4--;} if(heure5<0){heure5 =23;} }       //off lundi
  if (menu==6)   {minute6--;delay(100); if(minute6<0){minute6=60; heure6--;} if(heure6<0){heure6=23;} }        //on mardi
  if (menu==7)   {minute7--;delay(100); if(minute7<0){minute7=60; heure7--;} if(heure7<0){heure7 =23;} }       //off mardi

    } 
   
  if (buttonValue > 450 && buttonValue < 500) {      //2.35V=>481 left
  menu++;
  delay(600);
  if  (menu>=6) {menu=0;}                    } 
                                                

   if (buttonValue > 700 &&  buttonValue < 750) {    //721   select
     if (menu==0)   {Energy=0;Pmoy=0;}
     if (menu==1)   {jour++; if (jour>7) {jour=0;} }     //jour1  lundi
          } 

if (seconde>=1) { 
   if (menu==0)  { 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T");    
    lcd.print(Temp,1);
    lcd.print(" ");  
    lcd.print("C");    
    lcd.print(consigne,1);
    lcd.print(" ");
    lcd.print("S");    
    lcd.print(consigneSecu);
    if (digitalRead(13)== 1) {lcd.print("H");} else {lcd.print("C");}   //hot or cold
    lcd.print("  ");    
       
    lcd.setCursor(0, 1);    
    lcd.print("TH:"); 
    lcd.print(Theater1);
    lcd.print(" ");  
    lcd.setCursor(6, 1);  
    lcd.print(powerA,0);
    lcd.print(" ");
    if (regule==1) {lcd.print("ON");}
    if (regule==0) {lcd.print("OFF");}
    lcd.print("      ");
                  }  //fin menu==0

   if (menu==1)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("time:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure1);
    lcd.print("h");    
    lcd.print(minute1);
    lcd.print("m");
    lcd.print(seconde1);
    lcd.print("s ");  
    if (jour==1) {lcd.print("lundi  ");}
    if (jour==2) {lcd.print("Mardi  ");}
    if (jour==3) {lcd.print("Mercr  ");}
    if (jour==4) {lcd.print("jeudi  ");} if (jour==5) {lcd.print("vendr  ");}
    if (jour==6) {lcd.print("samed  ");} if (jour==7) {lcd.print("diman  ");}     
   }

   if (menu==2)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure2);
    lcd.print("h");    
    lcd.print(minute2);
    lcd.print("m   ");   
   }

   if (menu==3)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("menu temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure3);
    lcd.print("h");    
    lcd.print(minute3);
    lcd.print("m   ");   
   }

  if (menu==4)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("lundi temps ON:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure4);
    lcd.print("h");    
    lcd.print(minute4);
    lcd.print("m   ");   
   }

      if (menu==5)  {
    lcd.clear();  
    lcd.setCursor(0, 0);
    lcd.print("lundi temps OFF:"); 
    lcd.print(menu); 
    lcd.setCursor(0, 1); 
    lcd.print(heure5);
    lcd.print("h");    
    lcd.print(minute6);
    lcd.print("m   ");   
   }
   

    if(seconde1 >= 60){seconde1 = 00;   minute1++;}
    if(minute1 >= 60){minute1 = 00;      heure1++;}      
    if(heure1 >=24)  { heure1 = 00;jour++;} 
    if(jour>8)  {jour=1;} 
                  
    Pmoy=(Energy*1000)/temps; 
      
 seconde10++;
 if (seconde10>=10) {
      Pmoy2=Pmoy1;      
      Pmoy1=Pmoy;  
      power2=power1;     
      power1=power;      

      power=(Pmoy+Pmoy1*2+Pmoy2-power1*a1-power2*a2) ;   //filtrage pour avoir une puissance moyenne fe=0.1s avec une frequece de coupure fc=1/1250hz
      powerA=power/Gain;  
      seconde10=0;    }  

Serial.print(Theater1);Serial.print(";");Serial.print(Temp,2);Serial.print(";");Serial.print(Pmoy,0);Serial.print(";");Serial.print(powerA,0);
Serial.println(";");
seconde=0;
            }
}//fin loop
4 Likes

Si on a pas besoin de programmation hebdomadaire, il n’y a pas besoin d’afficheur, donc un arduino mini suffit.
Voici le schema electrique et le PCB
Si on a pas besoin de programmation hebdomadaire, il n’y a pas besoin d’afficheur, donc un arduino mini suffit.
Voici le schema electrique et le PCB

je pensais que l'on pouvait attaché des fichiers mais je n'ai rien trouvé !!!!!!!!!!!

Une petite alimentation 5V suffira pour l’alimenter ou un vieux chargeur de telephone USB

Pour le TTGO, c’est long de les recevoir, donc il faut encore attendre

4 Likes