[Arduino] Régulation pac
#1
Allez histoire d'arrêter de flood le Blabla, petit sujet régul à base d'arduino Uno,
du coup j'ai mis tout ça au propre sur une planche de mdf en attendant un truc définitif.

Comme je voyais pas ce qui ce passait j'ai rajouté un écran LCD, donc là le détendeur électronique
sera régulé à partir de la pression d'évaporation et une sonde 1-Wire pour la surchauffe.

   

Comme j'ai remarqué que les régulateurs 5 et 12V chauffaient ( plus le 5V ) j'ai fabriqué un petit rad en alu
avec de la patte thermique, ça aide mais ça picoque toujours les doigts, à voir.

   
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#2
t'as déjà une batterie 12v , pk un régul 7812?
Répondre
#3
Pour éviter d'envoyer une tension trop élevée dans la bobine du détendeur, et accessoirement j'en ai
besoin pour l'ampli aussi car je vais en profiter pour réguler le compresseur Smile
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#4
Passer de 12 à 12.5 V ne va pas détruire la bobine tu sais Wink
Répondre
#5
T'arrête pas à la première ligne Redface


Bon par contre le programme est relou là ... il arrive pas à me calculer un truc qui me donne le bon résultat
quand je le fais moi même sur la calculatrice.

Capteur_HP = 1023

(Capteur_HP - 102) * (100 - -25) / (1023 - 102) + -25;


C'est censé me renvoyer 100 mais ça me renvoi -42 ... Wtf lol


Edit : Hum, en rajoutant des .0 à la fin des nombres ça marche ... lol²
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#6
Crame l'ampli Redface
Répondre
#7
Il manque des parenthèses, l'ordre du calcul n'est pas forcément celui que tu pense ni celui de ta calculatrice. Il faut toujours forcer la précédence avec des parenthèses quand c'est important.

Ton faux résultat est probablement dû à ça ou à un overflow (d'où le comportement correct quand tu passes en flottant).

Et c'est quoi ce calcul ? c'est le bordel, si je devais deviner je dirais que t'as mélangé du scaling, de la calibration et de l'ampli. Tu devrais vraiment séparer et commenter les constantes (genre 102 c'est quoi ?) parce que le jour où tu voudras modifier un paramètre tu vas plus rien comprendre et tu vas passer des heures à reverse-engineerer ton propre code...

Et un 78xx c'est pourri comme référence de tension, perso je baserais pas ma régu là-dessus.
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre
#8
Pour les curieux voilà le code, même si je sais que y'en a qui vont sauter au plafond lol

Code :
#include <Stepper.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

// Définition des pins utilisés par le Shield LCD
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

#define ONE_WIRE_BUS 6 // Définition de la valeur du BUS OneWire
OneWire oneWire(ONE_WIRE_BUS); // Définition du BUS OneWire
DallasTemperature sensors(&oneWire); // Conversion OneWire > DallasTemperature

// Adressage des sondes DS18B20 ( Evap, surchauffe )
DeviceAddress Sonde_SR = { 0x28, 0xC2, 0x75, 0x82, 0x05, 0x00, 0x00, 0xBB };
DeviceAddress Sonde_SC = { 0x28, 0xFF, 0xEC, 0x99, 0x3C, 0x04, 0x00, 0x9F };

float Surchauffe = 6.5;
float Surchauffe_cal;
int Position_det = 0;
float Temp_BP = 0;
float Temp_HP = 0;
int Pin_Capteur_BP = A4;
int Pin_Capteur_HP = A5;
int Capteur_BP;
int Capteur_HP;

// initialize the stepper library on pins 2 through 5:
Stepper myStepper(480, 2, 3, 4, 5);

void setup() {
  // Initialisation écran
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Initialisation");
  delay(500);
 
  // initialize the serial port:
  Serial.begin(9600);

  // Configuration des sondes DS18B20
  sensors.begin();
  sensors.setResolution(Sonde_SR, 10);
  sensors.setResolution(Sonde_SC, 10);

  // Nombre de tour/min détendeur
  myStepper.setSpeed(4);

  // Fermeture détendeur
  lcd.setCursor(0,1);
  lcd.print("Ferm EEV > 0%");
  //myStepper.step(-500); // 480 + 20 ( sécu )

  delay(3000);
 
  // Ouverture détendeur 50%
  lcd.setCursor(0,1);
  lcd.print("Ouv EEV > 50%");
  //myStepper.step(+240);
  Position_det = 240;

  delay(3000);
}

float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void loop() {
  // Récupération des températures
  sensors.requestTemperatures();

  // Récupération pression BP
  Capteur_BP = analogRead(Pin_Capteur_BP);
  float Capteur_BP_Out = mapf(Capteur_BP, 102, 1023, 0.0, 9.8); // 102 = 0.5V mini / 1023 = 5V maxi / 0 bars mini / 9.8 bars maxi

  // Conversion Pression/température BP
  float Temp_BP_Out = mapf(Capteur_BP, 102, 1023, -26, 42);

  // Récupération pression HP
  Capteur_HP = analogRead(Pin_Capteur_HP);
  float Capteur_HP_Out = mapf(Capteur_HP, 102, 1023, 0, 38.5); // 102 = 0.5V mini / 1023 = 5V maxi / 0 bars mini / 38.5 bars maxi

  // Conversion Pression/température HP
  float Temp_HP_Out = mapf(Capteur_HP, 102, 1023, -25, 100); // 102 = 0.5V mini / 1023 = 5V maxi / -25°C mini / 100°C maxi
 
  delay(250);

  // Attribution des valeurs
  float Sonde_SR = sensors.getTempCByIndex(0);
  float Sonde_SC = sensors.getTempCByIndex(1);

 
  Surchauffe_cal = Temp_BP + Surchauffe;

  // Action si Surchauffe_Réelle supérieur à Surchauffe_Calculée
  if (Sonde_SC > Surchauffe_cal && Position_det < 480)
  {
    myStepper.step(+1); // Ouverture détendeur
    ++Position_det;
  }
 
  // Action si Surchauffe_Réelle inférieur à Surchauffe_Calculée
  else if (Sonde_SC < Surchauffe_cal && Position_det > 10)
  {
    myStepper.step(-1); // Fermeture détendeur
    --Position_det;
  }
  else {
    // Rien
  }

  int bouton = analogRead(A0);
 
  // Affichage LCD alterné
  if (bouton > 1000)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Tc:");
    lcd.print(Temp_HP_Out);
    lcd.setCursor(8,0);
    lcd.print("Te:");
    lcd.print(Temp_BP_Out);
    lcd.setCursor(0,1);
    lcd.print("SR:");
    lcd.print(Temp_HP_Out - Sonde_SR);
    lcd.setCursor(8,1);
    lcd.print("SC:");
    lcd.print(Sonde_SC - Temp_BP_Out);
  }
  else {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Pc:");
    lcd.print(Capteur_HP_Out);
    lcd.setCursor(8,0);
    lcd.print("Pe:");
    lcd.print(Capteur_BP_Out);
    lcd.setCursor(0,1);
    lcd.print("Pos det:");
    lcd.print(Position_det);
  }
 
  delay(250);
}

Et le calcul c'est pour remplacer la fonction "map" qui ne prend pas les virgules et moi je les veux ^_^

Pour les régulateurs, c'est pourtant le genre de chose qui est utilisé par les fabricants de clim mais bon  Spamafote
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#9
(2019-12-04 19:51:33)BiduleOhm a écrit : Et un 78xx c'est pourri comme référence de tension, perso je baserais pas ma régu là-dessus.

Ah oui ? Qu'est ce qui est mieux qu'un régulateur linéaire comme référence de tension pour un montage de base non critique ?
Répondre
#10
Perso je ferais tous mes calculs en virgule fixe pour éviter les flottants (spa vraiment ce qu'il y a de mieux sur l'arduino...).

~

Une référence de tension, genre TL431 par ex. A défaut une zener correctement biaisée.

Le problème du régu c'est qu'il dérive avec la température (-1 mV/°C, vu la Rthjc t'es vite entre 50 et 100 mV dans les choux) et comme il s'échauffe en fonction du courant consommé la dérive est aléatoire. Sans compter tous les autres défauts qui sont en principe pas un problème vu qu'il n'est pas prévu pour ça à la base (la tension peut être n'importe où entre 11.5 et 12.5 V en sortie d'usine, +/- 100 mV selon le courant consommé, ...). Quand tu cumules tous les effets tu te retrouves avec une précision vraiment pourrie.
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre
#11
Virgule fixe ? C'est quoi la différence ? Limiter le nombre de chiffres après la virgule ? Tongue


Quand même étonnant ce que tu annonce pour les régulateurs, tous les fabricants en utilisent sur leurs PCB principal pour alimenter
les sondes & capteurs et il n'y aucune régulation derrière, ça va direct du régulateur au composant final et pourtant c'est sujet à des températures
qui peut être -10°C comme 50°C vu qu'elles sont toujours dans l'UE.

Par exemple dans le cas d'hitachi ça alimente en direct les capteurs de pression, c'est pourtant un organe critique pour la régulation.
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#12
En gros oui, sauf que comme tu connais le nombre de chiffres après la virgule tu peux utiliser des simples entiers. Par exemple pour un prix ce sera toujours 2 décimales donc tu peux le représenter comme 123.45 ou alors 12345. Pour des °C tu peux travailler avec des dixièmes de degrés, 25.3 °C devient 253 par ex.

Je n'ai pas dit que ça marchait pas, je dis que c'est imprécis. Les fabricants préfèrent économiser et simplifier les PCB (ce qui engendre d'autres économies au passage...) donc ils sont prêts à sacrifier cette précision. Mais si je conçois un truc moi-même je préfère rajouter 34 cts (le coût d'un TL431...) et avoir une vraie référence...

Après c'est ce que je ferais et ce que je conseille, t'es pas obligé du tout de suivre, mais ne crois pas que tu pourras réguler à 2 décimales (ou même une en fait; 5 % de 50 °C ça fait déjà 2.5 °C, et 5 % c'est optimiste...) si tu te bases sur un 78xx comme ref de tension.
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre
#13
Pas con de fonctionner avec des entiers mais ça fait rajouter des calculs en plus pour reconvertir les données à chaque fois que
tu veux les afficher ou autres, donc kif kif, après j'ai un délais de presque 1 seconde entre chaque boucle donc je lui demande pas
l'impossible non plus en terme de vitesse, surtout que j'utilise des delay et step qui sont bloquants.

Pour les 78xx, les températures donnés étaient à titre indicatif, dans mon cas l'arduino va être dans une armoire métallique avec une température
beaucoup plus linéaire qu'en extérieur et c'est un circuit test, c'est loin d'être une version définitive vu que la plus part des fonctions doivent être
reprises par l'automate siemens une fois programmé, mais certaines resterons sur arduino comme le détendeur vu que pas de pwm sur le siemens.
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#14
En principe y'a qu'un seul calcul, qui est juste une division d'ailleurs, vu que tu affiches les valeurs qu'à un endroit.

Faut absolument que t’apprenne à faire un vrai timer (non bloquant) si tu veux faire un truc sérieux (voir ci-après), tu peux pas te permettre de bloquer la régu juste pour pouvoir afficher un truc par ex, sans compter que tu peux pas faire plusieurs choses à différentes vitesses avec des delay().

T'oublie l'échauffement du régu lui-même, c'est pas juste l'environnement, mais comme je disais c'est toi qui vois, je te laisse tranquille Wink

Donc, concernant le timer c'est vraiment pas compliqué; le concept c'est de de stocker le temps au début du timer et de calculer la différence entre le temps actuel et le départ: si la durée obtenue est inférieure au délai voulu on ne fait rien, si elle est supérieure on exécute ce qu'on voulait exécuter après le délai voulu :

Code :
uint32_t    start;

void setup()
{
    start = millis();
}

void loop()
{
    if ((millis() - start) > 5000) {
        //
        // fait ce que t'as à faire après 5 secondes
        //
        start = millis(); // supprime cette ligne si tu veux juste que le timer s'exécute une seule fois après le démarrage
    }
}

Pour un peu plus de propreté et pouvoir faire plusieurs timers sans se mélanger les pinceaux je m'étais fait une classe https://pastebin.com/zr5AGtr2 t'as juste à inclure ce code avant le reste et pour l'utiliser c'est simple :

Code :
Timer    *myTimer        = new Timer();
Timer    *myOtherTimer    = new Timer();

void    setup()
{
    myTimer->reset(5000UL);
}

void    loop()
{
    myTimer->update();

    if (myTimer->hasEnded()) {
        // fait ce que tu veux ici après 5 secondes
    }

    myOtherTimer->update();

    if (myOtherTimer->hasEnded(1000UL)) {        
        myOtherTimer->reset();
        // fait ce que tu veux ici toutes les secondes
    }
}

Comme tu peux voir il y a deux utilisations possibles: en général on utilise la première version (myTimer) quand on veut un timer qui s'exécute qu'une fois, et on utilisera la seconde version (myOtherTimer) qui prend le délai directement dans le test de fin quand on ne sait pas le délai à l'avance (dans setup()), ou quand on veut un timer qui boucle à l'infini ou encore quand on veut pouvoir changer le délai dynamiquement.

Si tu veux un timer qui s'exécute qu'une fois il suffit de retirer le ->reset(); qui est dans le if, comme dans l'exemple du premier timer.

N'oublies pas le ->update(); parce que sinon le délai sera infini et le code s'exécutera jamais...

Et même si le timer n'est pas bloquant n'oublies pas que ce que tu exécutes l'est. Par exemple dans le premier timer si tu prends 2 sec pour faire un truc alors ce que tu exécutes dans le second timer ne sera pas exécuté toutes les secondes comme voulu mais toutes les 2 secondes, l'arduino n'est pas multi-tâches...
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre
#15
Ah oui pour alimenter les sondes, je voulais juste savoir pourquoi ça convenait pas juste pour alimenter des IC Big Grin

Oui ça fait plus de sens effectivement Wink
Répondre
#16
Désolé mais je connais déjà le principe de faire un timer non bloquant et déjà utilisé ailleurs mais la
pour le coup je m'en fou pour l'instant.
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#17
pour l'affichage d'un entier d'un réel, t'as juste une virgule a placer , sans division ^^
Répondre
#18
Ok Wink

Oui mais vu comment l'affichage marche c'est bien plus simple et rapide de faire une division qu'autre chose Smile
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre
#19
Bon bah moi pas comprendre ... La fonction mapf fait n'importe quoi avec les valeurs ...

Si je met "mapf(Capteur_BP, 102, 1023, 0.0, 9.8)", ça me renvoie une pression complètement bidon par contre si je
met "mapf(Capteur_BP, 0, 1023, 0.0, 9.8)" j'ai la bonne pression.

Les températures sont quand à elles complètement à l'ouest mais je me doute du pourquoi, elles ne sont visiblement
pas du tout linéaire d'après le tableau et on en avait déjà parlé avec la fonction quadratique pour corriger de mémoire.
( qui donne y = 0,0022x2 - 0,0098x + 0,4992 et j'ai trouvé ça https://eskimon.fr/tuto-arduino-502-diff...de-mesures )

La valeur 102 est importante vu que c'est le point zéro du capteur, à 0bars relatif il est à 0.5V que ce soit pour le BP
ou le HP, par contre à 2bars relatif je suis à 1V sur le BP et 0.6V sur le HP ( arrondi ).
T'as un problème, t'veux un ban ?  Ohgod
Répondre
#20
D'où sort mapf() ? parce qu'elle ne fait pas partie de la lib standard de l'arduino. J'aimerais bien avoir au moins le proto, mais le code complet serait encore mieux parce que sinon je ne peux pas t'aider sans plus d'infos.

Concernant la non linéarité tu utilises quel capteur ?
Congratulations !!! You've just created a temporal loophole... Mon site | Mon forum
Répondre