problème de bloquage de lecture de sonde température ds18B20

Bonjour à tous,

Je me tourne vers vous car j'ai un problème avec mes arduinos leonardo.

le projet:

Des frigos à la base normaux ont été modifiés complètement afin de pouvoir contrôler différents paramètres (humidité O2 température etc). Le contrôle du compresseur ( système de refroidissement du frigo) est effectué grâce à un arduino leonardo couvert par un relay shield.

Le problème:

Complétement aléatoirement le arduino (qui contrôle une sonde de température en fonction de laquelle le compresseur du frigo est lancé ou arrêté) se bloque (ex: je demande au frigo d'être a 8°C il "reçoit" comme information de la ds18b20 qu il est à 9°C; la température qu il affiche reste toujours la meme elle ne bouge pas c'est la que je vois qu il y a un soucis. Ainsi le compresseur est activé ce qui est correct par rapport a ce qu'il a comme information ( il doit être à 8°C il est à 9°C il doit refroidir donc activer le compresseur), mais du coup il ne s'arrête plus de refroidir et j'atteins des températures de -12°C.

J'ai constater qu'en appuyant sur le bouton reset du arduino il se remet bien et repart correctement.

Une solution:

Je n'arrive pas à identifier d'ou vient le problème car c'est un problème qui est totalement aléatoire. Ce que j'aimerais si c est possible c est de lui faire régulièrement un autoreset (comme si j'appuie sur le bouton reset) par le code afin que mon essai ne soit pas détruit en allant a -12°C. Est ce que c'est possible ?

le code de mes arduinos leonardo est ci-dessous.

Je vous remercie par avance pour votre aide précieux.

#include <EEPROM.h>
#include <Wire.h>
#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//Define Variables for the Menu
int Heater;
int recByte=0;
int startFlag=0;
int tempWriteFlag=0;
int regFlag=0;
int heaterFlag=0;
int ColdUnitState;
int AirPumpState;

//Define Variables we'll be connecting to
volatile long onTime = 0;

// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10 

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// InputOutput
#define Relay_Heater 4
#define Relay_ColdUnit 5
#define Relay_AirPump 6
#define InPumpFromRPI 13

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
double Kp=500, Ki=0.5, Kd=0.01;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

int WindowSize = 10000;
unsigned long windowStartTime;

// maximum difference between input and setpoint accepted before switching on
// or off the compressor
float threshold = 0.25f;

// Defines when next the compressor might be switched on or off
long nextUpdate = 0;

// Defines delays between compressor status modification
int updateDelay = 5000;

// Alarm (when ringing) tone management
const int maxAlarmTone = 880;
const int minAlarmTone = 440;
int alarmTone = minAlarmTone;
const int alarmSpeed = 20;
const int alarmPin = 11;
const float maxTempDiff = 2.0f;

void setup()
{
  windowStartTime = millis();

  //Enable the Outputpin
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(alarmPin, OUTPUT);
  pinMode(13, INPUT);


  //Enable the serial port
  Serial.begin(9600);
  
  //initialize the variables we're linked to from the EEPROM
  Heater = EEPROM.read(1);
  Setpoint = EEPROM.read(0);

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);

  // Depending on how the PCM is managed by the atmega on the arduino,
  // the value might need a sync - ms
 
  sensors.setWaitForConversion(true);
}

void loop()

{
   digitalWrite(Relay_Heater,Heater);// Toggle Heater
   
   if(digitalRead(InPumpFromRPI) == 1)
  {
    digitalWrite(Relay_AirPump,LOW); //Disable the airExtraction.
    AirPumpState=0;
    
  }
  else 
  {
    digitalWrite(Relay_AirPump,HIGH); //Eanble the airExtraction.
    AirPumpState=1;
    delay(10);
     
  }
    
    // call sensors.requestTemperatures() to issue a global temperature 
    // request to all devices on the bus.
    
    sensors.requestTemperatures(); // Send the command to get temperatures
    

    // After we got the temperatures, we can print them here.
    // We use the function ByIndex, and as an example get the temperature from the first sensor only.
    
    float newInput = sensors.getTempCByIndex(0);

    bool readErr = newInput==DEVICE_DISCONNECTED_C;
    if (!readErr) {
        Input = newInput;
    }
//*******************************
    else{
    Serial.println("probleme d'actualisation");
    oneWire.reset();
    delay(2000);
    }
//****************************


    // Alarm management
    if (readErr || abs(Input-Setpoint)>=maxTempDiff) {
      alarmTone += alarmSpeed;
      if (alarmTone>maxAlarmTone) {
        alarmTone = minAlarmTone;
      }
      tone(alarmPin, alarmTone);
    } else {
      noTone(alarmPin);
    }

  /************************************************
   * turn the output pin on/off directly based on input
   ************************************************/
   
  long now = millis();
  
  if (now>=nextUpdate) {
    nextUpdate = now + updateDelay;
    
    else if (Input <( Setpoint - threshold)) {
      Serial.println("je desactive le compresseur");
       digitalWrite(Relay_ColdUnit,LOW); //disable the compresor
       ColdUnitState=0;
    } 
    else if (Input > (Setpoint + threshold))
    
        {
         Serial.println("j'actiuve le compresseur");
       digitalWrite(Relay_ColdUnit,HIGH); //Enable the compresor
       ColdUnitState=1;
       }
       
  
  }
  /************************************************
   * Send the information on the serial
   ************************************************/


  Serial.print("Setpoint: ");Serial.print(Setpoint); Serial.print(" ");
  Serial.print("Input: ");Serial.print(Input); Serial.print(" ");
  
  Serial.print("ColdUnit: ");if(ColdUnitState==1){Serial.print("On");}else{Serial.print("Off");};Serial.print(" ");
  Serial.print("Heater: ");if(Heater==1){Serial.print("Off");}else{Serial.print("On");};Serial.print(" ");
  Serial.print("AirPump: ");if(AirPumpState==1){Serial.print("On");}else{Serial.print("Off");};Serial.print(" ");
  
  Serial.print("\n\r");

  // Interative serial Menu:
   if(Serial.available()>0){
       // store received byte
        recByte=Serial.read();
       // Serial.println(recByte, DEC);
        if(recByte=='0')
        {
          Serial.print("Menu started\n\r");
          startFlag=1;
          Serial.print("Tip:(1) Update Setpoint \n\r");
          Serial.print("Tip:(2) Read Setpoint \n\r");
          Serial.print("Tip:(3) Toogle Heater \n\r");
          Serial.print("Tip:(4) Exit \n\r");
          Serial.flush();
          while(Serial.available()==0);
         }

        
        else if((recByte=='1')&&(startFlag==1))
        {
          tempWriteFlag=1;
        }
        else if((recByte=='2')&&(startFlag==1))
        {
          Serial.print("Temp [C°] \n\r");
          Serial.print(Setpoint);
          Serial.print("\n\r");
        }
        else if((recByte=='3')&&(startFlag==1))
        {
          heaterFlag=1;
          
        }
        else if((recByte=='4')&&(startFlag==1))
        {
          Serial.print("Exit \n\r");
        }
        else
        {
          Serial.print("Invalid!\n\r");
        }

        // Heater Toogle
        if((startFlag==1)&&(heaterFlag==1))
        {
          Serial.print("typ: On(1), Off(2) \n\r");
          Serial.flush();
          
          while(Serial.available()==0);
          regFlag = Serial.parseInt();
     
          if (regFlag == 1)
          {
            EEPROM.write(1,0);
            Serial.print("Heater Enable \n\r");
          }
          else if (regFlag == 2)
          {
            EEPROM.write(1,1);
            Serial.print("Heater Disable \n\r");
          }
          Heater=EEPROM.read(1);
          heaterFlag=0;
          startFlag=0;
         }

   
        //Updat Setpoint
        if((startFlag==1)&&(tempWriteFlag==1))
        {
          Serial.print("Update Temp ? Yes:1, No:2 \n\r");
          Serial.flush();
          
          while(Serial.available()==0);
          regFlag = Serial.parseInt();
        
          //Temp. update
          if (regFlag == 1)
          {
            Serial.print("Typ the new val(1050 = 10,5 [C°] & 1 [C°]= 100 etc..): \n\r");
            
            while(Serial.available()==0);
            Setpoint = Serial.parseInt();
            Setpoint = Setpoint/100;
            EEPROM.write(0,Setpoint);
            Serial.print("New Temp [C°] \n\r");
            Serial.print(Setpoint);
            Serial.print("\n\r");
           }
           else if (regFlag == 2)
          {
            Serial.print("Exit \n\r");
            
          }                  
          tempWriteFlag=0;
          startFlag=0;
        }
  }

}

Hey^^
Je pense que le problème viens du fait que le timer millis() overflow (repart de 0) après 50 jours, ce qui peut produire incoherence dans le programme (si le bug arrive beaucoup plus fréquemment, c'est que le problème de vient pas de là)
Pour Reset une Arduino, il suffit de declarer une fonction reset puis de l'appeller de la manière suivante :

void(* reset_function) (void) = 0;  //declaration de la fonction
//on a besoin de reset ici
reset_function();

Néanmoins, si le problème ne vient pas de l'overflow de millis(), il vaut mieux essayer de comprendre d'ou il vient plûtot que d'essayer de le résoudre "magiquement" avec un reset .

Salut,

Je te remercie pour ta réponse rapide. J'ai deja pensé au problème de l'overflow et j'ai pu tester que ce n'était pas ca. Les frigos sont éteints et allumés toute les semaines.

Pour être plus précis j'ai 8 frigos montés pareils.
Le problème est très aléatoire. Ce que j'ai pu constater c'est que lorsqu'un de mes frigos n'est pas à la bonne température c'est systématiquement que le arduino "croit" être à une autre température. A ce niveau je ne sais pas comment tester ce problème. Ce que j'ai constater aussi c'est que sitôt que j'appuie sur le bouton reset il "se met à jour" l'alarme sonne et le compresseur est régulé correctement.

Concernant le code que tu propose?

Je déclare la fonction

void(* reset_function) (void) = 0;

en dehors des fonction setup() et loop()

et je l'appel

reset_function();

dans le loop()

?
Est ce que cet ajout reset le arduino de la même façon que lorsque j'appuie sur le bouton reset?

Merci beaucoup

Hello

dans ton code, passe toutes les variables qui concernent la fonction millis() en unsigned long

pour l’instant tu en as en unsigned long et en long.

la fonction de reset soft est :

if (problème){ asm volatile (" jmp 0");}

à toi de mettre le bon contrôle pour détecter un problème.

  • 1 avec mon voisin du dessus, l0w-s3c, il vaudrait mieux trouver la cause du problème

Bonjour,
Pour le débordement de millis() : How to manage the overflow of millis()

dfgh:
...dans ton code, passe toutes les variables qui concernent la fonction millis() en unsigned long

pour l'instant tu en as en unsigned long et en long. ...

Vous avez aussi

int updateDelay = 5000;

Tout cela ne fait pas bon ménage.

Mais ce n'est peut-être pas le problème. Vouloir faire un "reset" pour que tout reparte bien est un cache misère. Il me semble préférable d'identifier le problème (qui peut être de câblage entre autres).

Cordialement.

Pierre

Bonsoir

+1000 pour construire un code propre, plutôt que d'essayer de déclencher un reset avant que tout pète

Néanmoins j'ajouterais bien une petite nuance :

Une fois le code rendu propre, rien n'empêche d'ajouter un filet de sécurité supplémentaire pour se mettre définitivement à l'abri de tout blocage.
L'arduino a une fonction en natif pour cela : le watchdog.

Perso, dès qu'un montage est prévu pour un fonctionnement en H24, je lui colle systématiquement un watchdog.