[RESOLU] gestion servo suivant temperature

Bonjour a tous
je suis en train de faire un code pour que un servo se deplace suivant une temperature ( si la temperature est superieur a la consigne le servo bouge dans un sens si la temperature est inferieur a la consigne le servo bouge dans l’autre sens )

le code est simple mais un bug se produit
ma position de servo ( pos dans le code )
ne fait que monter
impossible de la faire redescendre
avez vous une idée du pourquoi du comment
merci a vous

#include <OneWire.h> // Inclusion de la librairie OneWire
#include <Servo.h> 

#define DS18B20 0x28     // Adresse 1-Wire du DS18B20
#define BROCHE_ONEWIRE 7 // Broche utilisée pour le bus 1-Wire
#define max 175          //valeur max de consigne servo
#define min 5            //valeur min de servo


OneWire ds(BROCHE_ONEWIRE); // Création de l'objet OneWire ds

Servo myservo;  // creation de la variable servo 

int potpin = 0;  // entrer du potar de consigne
int consigne;    // variable pour la pin de consigne 
int pos;

// Fonction récupérant la température depuis le DS18B20
// Retourne true si tout va bien, ou false en cas d'erreur
boolean getTemperature(float *temp){
  byte data[9], addr[8];
  // data : Données lues depuis le scratchpad
  // addr : adresse du module 1-Wire détecté

  if (!ds.search(addr)) { // Recherche un module 1-Wire
    ds.reset_search();    // Réinitialise la recherche de module
    return false;         // Retourne une erreur
  }
  
  if (OneWire::crc8(addr, 7) != addr[7]) // Vérifie que l'adresse a été correctement reçue
    return false;                        // Si le message est corrompu on retourne une erreur

  if (addr[0] != DS18B20) // Vérifie qu'il s'agit bien d'un DS18B20
    return false;         // Si ce n'est pas le cas on retourne une erreur

  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  
  ds.write(0x44, 1);      // On lance une prise de mesure de température
  delay(50);             // Et on attend la fin de la mesure
  
  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  ds.write(0xBE);         // On envoie une demande de lecture du scratchpad

  for (byte i = 0; i < 9; i++) // On lit le scratchpad
    data[i] = ds.read();       // Et on stock les octets reçus
  
  // Calcul de la température en degré Celsius
  *temp = ((data[1] << 8) | data[0]) * 0.0625; 
  
  // Pas d'erreur
  return true;
}

// setup()
void setup() {
  Serial.begin(9600); // Initialisation du port série
    myservo.attach(9, 2000, 2000);  // attaches the servo on pin 9 to the servo object 
    myservo.write(90);                  // met le servo a la position de val 
    delay(500);                           // attente de positionnement du servo
}

// loop()
void loop() {
  float temp;
  int tempok;
  
  // Lit la température ambiante à ~1Hz
  if(getTemperature(&temp)) {
    tempok = (int) temp;
    // Affiche la température
    Serial.print("Temperature : ");
    Serial.print(tempok);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }
  consigne = analogRead(potpin);            // lit la valeur du potar comprise entre 0 et 1023 
  consigne = map(consigne, 0, 1023, 0, 100);     // converti cette valeur entre 0 et 100 

  Serial.print("consigne:");
  Serial.println(consigne);
  
  pos = constrain(pos, min, max);

  if (tempok <= consigne) {
    pos = pos - 5;
    myservo.write(pos);              
    delay(15); 
  }
  else {    
    pos = pos + 5;
    myservo.write(pos);              
    delay(15);                       
  }
  
    Serial.println(pos);
    delay(500);
}

Bonjour,

Tu devrais essayer d’initaliser la valeur de “pos” dans le setup :

    myservo.attach(9, 2000, 2000);  // attaches the servo on pin 9 to the servo object 
    pos = 90;
    myservo.write(pos);                  // met le servo a la position de val 
    delay(500);                           // attente de positionnement du servo
}

Sinon, quelles sont les valeurs affichées “tempok” et “consigne”…

merci a toi
je viens d'essayer en donnant une valeur a pos comme tu la marquer
cela ne change rien du tout
ma valeur tempok affiche la température dans la pièce ( environ 28°C) et la consigne elle affiche une valeur entr e0 et 100 suivant la position du potar

j'avoue ne pas comprendre pourquoi le pos = pos + 5;
fonctionne mais pas le pos = pos - 5;

L'initialisation du servo n'est pas correcte.

myservo.attach(9, 2000, 2000);

les 2 valeurs sont impulsion min et impulsion max (voir là:http://arduino.cc/en/Reference/ServoAttach). Si tu ne sais pas quoi mettre le mieux c'est de ne pas utiliser cette forme de la méthode attach et d'utiliser la version simplifiée.

myservo.attach(9);

Pour comprendre ce qui se passe il faudrait faire un print de la température, de la consigne et de pos.

Je pense que tu vas t'apercevoir que pos fait n'importe quoi. Ton problème doit venir d'une boucle très rapide (15ms) avec un système qui réagit relativement lentement. Comme tu ne mets pas de borne à pos après l'incrémentation ou la décrémentation, la variable doit déborder et le programme fait n'importe quoi. Normalement pos devrait être limité à l'intervalle 0 - 180.

effectivement la durée des impulsions ne me sert pas j’enlève
j'ai un print de la température de la consigne et de la position
pos ne fait qu'augmenter jusqu'a 180 ( constrain le bloque pour ne pas qu'il aille au delà)
mais impossible de le faire redescendre

le log

position servo: 90
Temperature: 25°C
consigne: 72
position servo: 89
consigne: 72
position servo: 90
Temperature: 25°C
consigne: 72
position servo: 89
consigne: 72
position servo: 90
Temperature: 25°C
consigne: 72
position servo: 89
consigne: 72
position servo: 90
Temperature: 25°C
consigne: 71
position servo: 89
consigne: 71
position servo: 90
Temperature: 25°C
consigne: 70
position servo: 89
consigne: 69
position servo: 90
Temperature: 25°C
consigne: 68
position servo: 89
consigne: 68
position servo: 90
Temperature: 25°C
consigne: 67
position servo: 89
consigne: 67
position servo: 90
Temperature: 25°C
consigne: 65
position servo: 89
consigne: 65
position servo: 90
Temperature: 25°C
consigne: 63
position servo: 89
consigne: 63
position servo: 90
Temperature: 25°C
consigne: 62
position servo: 89
consigne: 61
position servo: 90
Temperature: 25°C
consigne: 59
position servo: 89
consigne: 59
position servo: 90
Temperature: 25°C
consigne: 57
position servo: 89
consigne: 57
position servo: 90
Temperature: 25°C
consigne: 56
position servo: 89
consigne: 55
position servo: 90
Temperature: 25°C
consigne: 54
position servo: 89
consigne: 54
position servo: 90
Temperature: 25°C
consigne: 52
position servo: 89
consigne: 52
position servo: 90
Temperature: 25°C
consigne: 50
position servo: 89
consigne: 51
position servo: 90
Temperature: 25°C
consigne: 48
position servo: 89
consigne: 47
position servo: 90
Temperature: 25°C
consigne: 45
position servo: 89
consigne: 45
position servo: 90
Temperature: 25°C
consigne: 43
position servo: 89
consigne: 43
position servo: 90
Temperature: 25°C
consigne: 41
position servo: 89
consigne: 41
position servo: 90
Temperature: 25°C
consigne: 39
position servo: 89
consigne: 39
position servo: 90
Temperature: 25°C
consigne: 39
position servo: 89
consigne: 37
position servo: 90
Temperature: 25°C
consigne: 36
position servo: 89
consigne: 36
position servo: 90
Temperature: 25°C
consigne: 34
position servo: 89
consigne: 34
position servo: 90
Temperature: 25°C
consigne: 33
position servo: 89
consigne: 36
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 33
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 36
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 32
position servo: 89
consigne: 32
position servo: 90
Temperature: 25°C
consigne: 30
position servo: 89
consigne: 30
position servo: 90
Temperature: 25°C
consigne: 29
position servo: 89
consigne: 29
position servo: 90
Temperature: 25°C
consigne: 28
position servo: 89
consigne: 28
position servo: 90
Temperature: 25°C
consigne: 27
position servo: 89
consigne: 27
position servo: 90
Temperature: 25°C
consigne: 26
position servo: 89
consigne: 26
position servo: 90
Temperature: 25°C
consigne: 26
position servo: 89
consigne: 26
position servo: 90
Temperature: 25°C
consigne: 26
position servo: 89
consigne: 28
position servo: 90
Temperature: 25°C
consigne: 26
position servo: 89
consigne: 26
position servo: 90
Temperature: 25°C
consigne: 25
position servo: 89
consigne: 25
position servo: 90
Temperature: 25°C
consigne: 24
position servo: 91
consigne: 24
position servo: 92
Temperature: 25°C
consigne: 23
position servo: 93
consigne: 23
position servo: 94
Temperature: 25°C
consigne: 24
position servo: 95
consigne: 23
position servo: 96
Temperature: 25°C
consigne: 19
position servo: 97
consigne: 19
position servo: 98
Temperature: 25°C
consigne: 17
position servo: 99
consigne: 17
position servo: 100
Temperature: 25°C
consigne: 16
position servo: 101
consigne: 16
position servo: 102
Temperature: 25°C
consigne: 14
position servo: 103
consigne: 14
position servo: 104
Temperature: 25°C
consigne: 13
position servo: 105
consigne: 12
position servo: 106
Temperature: 25°C
consigne: 11
position servo: 107
consigne: 10
position servo: 108
Temperature: 25°C
consigne: 9
position servo: 109
consigne: 8
position servo: 110
Temperature: 25°C
consigne: 7
position servo: 111
consigne: 7
position servo: 112
Temperature: 25°C
consigne: 6
position servo: 113
consigne: 5
position servo: 114
Temperature: 25°C
consigne: 5
position servo: 115
consigne: 9
position servo: 116
Temperature: 25°C
consigne: 4
position servo: 117
consigne: 4
position servo: 118
Temperature: 25°C
consigne: 4
position servo: 119
consigne: 4
position servo: 120
Temperature: 25°C
consigne: 4
position servo: 121
consigne: 4
position servo: 122
Temperature: 25°C
consigne: 5
position servo: 123
consigne: 5
position servo: 124
Temperature: 25°C
consigne: 7
position servo: 125
consigne: 8
position servo: 126
Temperature: 25°C
consigne: 10
position servo: 127
consigne: 10
position servo: 128
Temperature: 25°C
consigne: 11
position servo: 129
consigne: 12
position servo: 130
Temperature: 25°C
consigne: 14
position servo: 131
consigne: 15
position servo: 132
Temperature: 25°C
consigne: 17
position servo: 133
consigne: 17
position servo: 134
Temperature: 25°C
consigne: 20
position servo: 135
consigne: 20
position servo: 136
Temperature: 25°C
consigne: 26
position servo: 135
consigne: 23
position servo: 136
Temperature: 25°C
consigne: 26
position servo: 135
consigne: 26
position servo: 136
Temperature: 25°C
consigne: 29
position servo: 135
consigne: 29
position servo: 136
Temperature: 25°C
consigne: 32
position servo: 135
consigne: 32
position servo: 136
Temperature: 25°C
consigne: 34
position servo: 135
consigne: 37
position servo: 136
Temperature: 25°C
consigne: 37
position servo: 135
consigne: 37
position servo: 136
Temperature: 25°C
consigne: 38
position servo: 135
consigne: 38
position servo: 136
Temperature: 25°C
consigne: 38
position servo: 135
consigne: 38
position servo: 136
Temperature: 25°C
consigne: 38
position servo: 135
consigne: 38
position servo: 136
Temperature: 25°C
consigne: 38
position servo: 135
consigne: 39
position servo: 136

comme on le voit la position du servo est a peu prés stable ( a 1° pres)
quand ma consigne est au dessus de ma temp rien ne ce passe alors que la position de mon servo devrait diminuer
par contre quand la consigne est en dessous de la temp la le servo augmente ( ce pour quoi il est programmer )
donc juste la descente bug
est ce le pos = pos -5 qui pose problème ?

Bonjour,

Je vois un soucis dans le code : tempok est une variable locale. Sa valeur au début de loop est donc indéterminée. Comme elle est valuée conditionnellement dans le if qui permet l'acquisition d'une nouvelle température,, elle n'a pas toujours une valeur connue lors de sont utilisation dans le reste de loop.

Passe cette variable en static, de cette manière sa valeur sera retenue d'une exécution de loop à l'autre.

static int tempok;

Je ne garantie pas que le pb vienne de là mais c'est une possibilité sérieuse :slight_smile:

effectivement çà aurais pu être ça mais ça a rien changer toujours le même problème
je laisse car c'est bon a savoir

Je ne vois pas pour l'instant

Ce n'est pas le seul problème ceci dit. pos, quand il augmente, augment de 5 en 5 alors que le log fait apparaître des variations qui ne sont pas de 5 en 5.

D'autre part, le test fait que soit pos augmente de 5 en 5, soit il diminue de 5 en 5. En aucun cas il ne peut rester stable.

Pourrais-tu poster le code actuel ? la sortie du log ne peut pas être produite par le code que je vois

oui effectivement une petite variation ce fait sentir mais cela s’expliquer surement par la breadboard et par mes fils
je n’est pas mit pour le moment d’état stable quand la température est la même que la consigne
je rajoute ça après

je te mets le code actuel mais tu vérra qu’il n’y a vraiment pas grand chose de plus

#include <OneWire.h> // Inclusion de la librairie OneWire
#include <Servo.h> 

#define DS18B20 0x28     // Adresse 1-Wire du DS18B20
#define BROCHE_ONEWIRE 7 // Broche utilisée pour le bus 1-Wire
#define max 179          //valeur max de consigne servo
#define min 1            //valeur min de servo


OneWire ds(BROCHE_ONEWIRE); // Création de l'objet OneWire ds

Servo myservo;  // creation de la variable servo 

int potpin = 0;  // entrer du potar de consigne
int consigne;    // variable pour la pin de consigne 
int pos = 90;

// Fonction récupérant la température depuis le DS18B20
// Retourne true si tout va bien, ou false en cas d'erreur
boolean getTemperature(float *temp){
  byte data[9], addr[8];
  // data : Données lues depuis le scratchpad
  // addr : adresse du module 1-Wire détecté

  if (!ds.search(addr)) { // Recherche un module 1-Wire
    ds.reset_search();    // Réinitialise la recherche de module
    return false;         // Retourne une erreur
  }
  
  if (OneWire::crc8(addr, 7) != addr[7]) // Vérifie que l'adresse a été correctement reçue
    return false;                        // Si le message est corrompu on retourne une erreur

  if (addr[0] != DS18B20) // Vérifie qu'il s'agit bien d'un DS18B20
    return false;         // Si ce n'est pas le cas on retourne une erreur

  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  
  ds.write(0x44, 1);      // On lance une prise de mesure de température
  delay(50);             // Et on attend la fin de la mesure
  
  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  ds.write(0xBE);         // On envoie une demande de lecture du scratchpad

  for (byte i = 0; i < 9; i++) // On lit le scratchpad
    data[i] = ds.read();       // Et on stock les octets reçus
  
  // Calcul de la température en degré Celsius
  *temp = ((data[1] << 8) | data[0]) * 0.0625; 
  
  // Pas d'erreur
  return true;
}

// setup()
void setup() {
  Serial.begin(9600); // Initialisation du port série
    myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
    myservo.write(pos);                  // met le servo a la position de val 
    delay(500);                           // attente de positionnement du servo
}

// loop()
void loop() {
  float temp;
 static  int tempok;
  
  // Lit la température ambiante à ~1Hz
  if(getTemperature(&temp)) {
    tempok = (int) temp;
    // Affiche la température
    Serial.print("Temperature: ");
    Serial.print(tempok);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }
  consigne = analogRead(potpin);            // lit la valeur du potar comprise entre 0 et 1023 
  consigne = map(consigne, 0, 1023, 0, 100);     // converti cette valeur entre 0 et 100 

  Serial.print("consigne: ");
  Serial.println(consigne);
  
  pos = constrain(pos, min, max);

  if (tempok <= consigne) {
    pos = pos - 1;
    myservo.write(pos);              
    delay(15); 
  }
  else {    
    pos = pos + 1;
    myservo.write(pos);              
    delay(15);                       
  }
    Serial.print("position servo: ");
    Serial.println(pos);
   // delay(300);
}

Je ne vois pas le static devant int tempok;

effectivement si j'enregistre pas mon code en faisant une modif ca marche moins bien
c'est rajouter

saloperie de connerie la ca marche
hum merci a toi jlbechennec
par contre j'avoue que j'aimerais bien comprendre pourquoi pour un static ca bug
je rajoute dessus ce qu'il faut pour quand la temp = consigne

anthology:
par contre j'avoue que j'aimerais bien comprendre pourquoi pour un static ca bug

sans un static ça buggue.

Sans le static, tempok est une variable locale, c'est à dire allouée sur la pile, voire directement dans un registre du micro. Dans les deux cas sa valeur initiale, en l'absence d'initialisation, dépend de l'historique du programme : quelle fonction s'est exécutée avant loop et ce qu'elle a fait sur la pile.

Comme une fois sur 2, si j'en juge par la trace de ton programme, tempok a une valeur initiale indéterminée, pos est incrémenté ou décrémenté de manière aléatoire (en première approche, il faudrait creuser)

Avec le static, la variable est allouée dans les globales mais n'est connue que de loop. Elle retient donc sa valeur précédente et c'est ce que tu veux. À vrai dire, je la mettrais carrément dans les globales et je l'initialiserait dans setup en faisant un getTemperature (et en le faisant jusqu'à ce qu'il retourne vrai)

ah ok je comprends
oui effectivement c'est bon a savoir qu'il faut penser a mettre des static pour des variables
pas réellement besoin de le mettre dans les globales mais après tu peux me montrer un exemples avec le getTemperature je suis preneur pour apprendre
merci beaucoup

Comme ceci, de cette manière temperature a une valeur initiale valide :

#include <OneWire.h> // Inclusion de la librairie OneWire
#include <Servo.h>

#define DS18B20 0x28 // Adresse 1-Wire du DS18B20
#define BROCHE_ONEWIRE 7 // Broche utilisée pour le bus 1-Wire
#define max 179 //valeur max de consigne servo
#define min 1 //valeur min de servo

OneWire ds(BROCHE_ONEWIRE); // Création de l’objet OneWire ds

Servo myservo; // creation de la variable servo

int potpin = 0; // entrer du potar de consigne
int consigne; // variable pour la pin de consigne
int pos = 90;
int temperature; // temperature courante

// Fonction récupérant la température depuis le DS18B20
// Retourne true si tout va bien, ou false en cas d’erreur
boolean getTemperature(float *temp){
byte data[9], addr[8];
// data : Données lues depuis le scratchpad
// addr : adresse du module 1-Wire détecté

if (!ds.search(addr)) { // Recherche un module 1-Wire
ds.reset_search(); // Réinitialise la recherche de module
return false; // Retourne une erreur
}

if (OneWire::crc8(addr, 7) != addr[7]) // Vérifie que l’adresse a été correctement reçue
return false; // Si le message est corrompu on retourne une erreur

if (addr[0] != DS18B20) // Vérifie qu’il s’agit bien d’un DS18B20
return false; // Si ce n’est pas le cas on retourne une erreur

ds.reset(); // On reset le bus 1-Wire
ds.select(addr); // On sélectionne le DS18B20

ds.write(0x44, 1); // On lance une prise de mesure de température
delay(50); // Et on attend la fin de la mesure

ds.reset(); // On reset le bus 1-Wire
ds.select(addr); // On sélectionne le DS18B20
ds.write(0xBE); // On envoie une demande de lecture du scratchpad

for (byte i = 0; i < 9; i++) // On lit le scratchpad
data* = ds.read(); // Et on stock les octets reçus*

  • // Calcul de la température en degré Celsius*
    _ *temp = ((data[1] << 8) | data[0]) * 0.0625; _

  • // Pas d’erreur*

  • return true;*
    }
    // setup()
    void setup() {
    _ Serial.begin(9600); // Initialisation du port série_

  • myservo.attach(9); // attaches the servo on pin 9 to the servo object*

  • myservo.write(pos); // met le servo a la position de val*

  • delay(500); // attente de positionnement du servo*

  • // lit la temperature initiale*

  • float temp;*

  • // attend que getTemperature rende une valeur*

  • while (! getTemperature(&temp));*

  • temperature = (int)temp;*
    }
    // loop()
    void loop() {

  • float temp;*

  • // Lit la température ambiante à ~1Hz*

  • if (getTemperature(&temp)) {*

  • temperature = (int) temp;*

  • // Affiche la température*
    _ Serial.print("Temperature: ");_
    _ Serial.print(temperature);_
    _ Serial.write(176); // caractère °_
    _ Serial.write(‘C’);_
    _ Serial.println();_

  • }*

  • consigne = analogRead(potpin); // lit la valeur du potar comprise entre 0 et 1023*

  • consigne = map(consigne, 0, 1023, 0, 100); // converti cette valeur entre 0 et 100*
    _ Serial.print("consigne: ");_
    _ Serial.println(consigne);_

  • pos = constrain(pos, min, max);*

  • if (temperature < consigne)*

  • {*

  • pos = pos - 1;*

  • myservo.write(pos); *

  • delay(15);*

  • }*

  • else if (temperature > consigne) { *

  • pos = pos + 1;*

  • myservo.write(pos); *

  • delay(15); *

  • }*

_ Serial.print("position servo: ");_
_ Serial.println(pos);_
}
[/quote]

daccord ça me permet de rassembler les déclaration et variables en haut ce qui est pas plus mal
j'en est profiter pour remonter mon float temp

tout m'a l'air clean ma foi
j'ai rajouter quelque code pour le debug
genre si debug = 1 je lance la liaison série et envoie les valeurs
si debug = 0 j’exécute juste le code de gestion et roule

un grand merci a toi pour cette aide ou j'ai apprit pourquoi un static est nécessaire dans certains cas