Posts | Comments

Planet Arduino

Archive for the ‘planet’ Category

Sep
14

Régulation PID, comment la régler 1/2

arduino, AVR, diy, Électronique, expérimentation, General, planet, Programmation, théorie Comments Off on Régulation PID, comment la régler 1/2 

Étant donné que je n’ai pas encore tout le matériel nécessaire pour avancer mes autres projets, j’en profite pour approfondir un peu mes connaissances théoriques et vous en fait donc profiter. Mon projet ici est simple : Réguler une température à l’aide d’un microcontrolleur, mais surtout bien comprendre les tenants et aboutissements des différents réglages et algorithmes. L’objectif ici n’est pas tant d’expliquer ce qu’est un PID, ni comment il fonctionne dans le detail, mais plutôt de donner une méthode permettant d’approximer les coefficients du régulateur.

Je profiterais de cette expérience pour faire 2 articles :
– celui-ci concernant le PID a proprement parler
– Un second article concernant ma méthode pour obtenir des courbes « lives » a partir d’un arduino et d’un PC.

Qu’es-ce qu’un PID

Pour simplifier, on parlera dans la suite de régulation de température, vu que ce sera notre application ici. Mais bien entendu, une régulation peut se faire sur tout type de process (vitesse, débit, etc…)

Lorsqu’on veut réguler la température (d’une pièce par exemple), l’idée la plus simple qui nous vient à l’esprit est de faire une régulation tout-ou-rien : on est en dessous d’un premier seuil, on allume la chauffe, on passe au dessus d’un second seuil on coupe la chauffe. Cette façon de procéder, bien que très simple à implémenter n’est pas exempte de défauts. Par exemple, la température ne sera jamais vraiment constante, même si elle l’est « en moyenne ». Selon le process, on peut arriver à fortement dépasser les consignes (dans un sens ou dans l’autre), en fonction de l’inertie du système, ce qui peut s’avérer nuisible selon ce qu’on veut faire. Enfin, la puissance du chauffage oscillera entre 0 et 100%, ce qui engendre une surconsommation non négligeable.

La régulation PID permet de coller « au plus juste » à la consigne, en évitant les dépassement (en fonction du réglage comme on le verra plus loin), et en n’utilisant que la puissance nécessaire à aller à la consigne et à la maintenir. Concrètement, dans PID, on a P pour Proportionnelle, D pour Dérivée, et I pour Intégrale. Si comme moi vous avez tendance à être un peu allergique aux maths, vous commencez déjà à vous sauver, mais en fait c’est moins compliqué que ça n’en a l’air.

Proportionnelle : c’est ni plus ni moins que la différence entre votre consigne et la valeur actuelle, multiplié par un coefficient de proportionnalité (Que vous définissez, cf la suite). Dans la suite, nous l’écrirons Kc.e(t)

Intégrale : A chaque mesure, vous allez avoir une différence avec la consigne (en plus ou en moins). Prenez cette erreur à chaque pas de temps, multipliez la par un (autre) coefficient de proportionnalité, et additionnez le résultat de tous les pas de temps depuis le début, et vous avez la fameuse composante Intégrale. Dans la suite, l’intégrale sera notée de la façon suivante :

I

 

Dérivée : Son rôle est de « freiner » l’augmentation de puissance calculée en fonction de P et de I, de manière à ne pas dépasser la consigne. C’est une façon de prendre en compte la vitesse d’évolution de notre process. Pour le calculer, vous faites erreur actuelle – erreur précédente, multiplié par un troisième coefficient de proportionnalité

La formule globale de notre régulateur PID peut donc s’écrire de la manière suivante (plus d’explications plus bas):

Formule PID, source ControlGuru

Formule PID, source ControlGuru

 

Description du materiel

Le montage utilisé pour ces essais est très simple : un arduino, un bouton 2 positions, 1 capteur de température (DS18B20), un mosfet (IRF540), une résistance 10Ω 5W, et une alimentation 12V. Le mosfet est piloté par une sortie PWM de l’arduino, et gère le courant (puissance) transitant dans la résistance. Cette dernière chauffe donc plus ou moins en fonction du ratio PWM (la tension change) envoyé par l’arduino. Le bouton 2 positions sert à passer d’une première consigne (valeur PWM 5 sur 255) à une seconde (valeur PWM 30 sur 255) Un petit programme python enregistre les valeurs dans un fichier texte sur le pc (via connection série), et j’utilise GnuPlot pour avoir une jolie courbe et pouvoir lire les valeurs des graphiques plus facilement que directement sur l’image. Par la suite, j’ai ameliore mon script python, de maniere a pouvoir saisir une consigne via le port serie, tout en continuant de logguer.

Montage régulation de température

Montage régulation de température. Attention, utiliser une résistance 5W mini !

Méthode de réglage

Je vous présente une méthode « graphique » directement tirée du site Control Guru, appliquée à mon montage de test. Ce site étant en anglais et très dense en informations, j’ai essayé de résumer les points essentiels ici. J’invite ceux qui voudraient approfondir le sujet à consulter ce site qui est une véritable mine d’information sur la régulation.

Définitions

  • PV : Process Variable, cela correspond à la grandeur mesurée que l’on veut influencer (la température dans cet exemple)
  • CO : Controller Output , la sortie de notre contrôleur en %. (Correspond à l’ouverture de la vanne par exemple)
  • Kp : Gain du process
  • Kc : Gain du contrôleur

Introduction

Une fois modélisé notre boucle de contrôle, nous allons pouvoir en déterminer les trois paramètres principaux par expérimentation, mesure et calcul (et oui…)

Les paramètres à déterminer sont :

  • Kp : la Gain du process, ou, dit autrement, le sens et la grandeur de la variation de la sortie
  • Tp : Constante de temps du process, ou la vitesse de variation quand le process a commencé à répondre
  • θp : (Prononcer Thêta P) Temps mort du process, ou le délai écoulé avant que le process commence à réagir
Boucle de contrôle

Boucle de contrôle

Afin de pouvoir déterminer nos trois paramètres, il va nous falloir mesurer la façon dont réagis notre système. La première étape consiste donc à fixer une première valeur de sortie à notre contrôleur (CO) et attendre que la variable de sortie (PV, ici la température) soit bien stabilisée.

Une fois cette dernière stable, nous allons modifier la valeur de sortie du contrôleur (CO), et mesurer le changement obtenu sur la variable de sortie (PV). On logue bien sûr tout ça dans un fichier, avec les pas de temps, de manière à pouvoir également déterminer le temps mort du process (θp) et la vitesse de variation (Tp).

On se sert ensuite de ces mesures pour tracer un joli graphique, qui nous servira à déterminer nos différentes valeurs.

La formule permettant de déterminer notre premier paramètre Kc, qui est à la base du calcul de nos 3 paramètres (cf. formule) est la suivante :

source : controlguru

source : controlguru

pour déterminer Kc, nous devons donc commencer par déterminer différentes variables intermédiaires.

Calcul de Kp

Kp décrit le sens et de combien va évoluer PV, en fonction d’un changement de consigne (CO) Le cacul de Kp est assez simple : Kp=ΔPV/ΔCO ou en d’autre termes Kp = (différence en PV initial et PV final)/(différence entre consigne initiale et finale)

Sur mon prototype, j’ai modifié la consigne initiale (1,96%) pour une nouvelle consigne à 11.76%, voici la courbe obtenue:

Graphique test du système.

Graphique test du système.

En appliquant la formule ci-dessus, on a donc Kp = (79-40)/(11,76-1,96) = 39/9.8 = 3.98°C/%

Détermination de la constante de temps Tp

Tp représente le « en combien de temps » le système va réagir. En partant du même graphique, on va déterminer quand l’état de sortie vaut 63% de δPV, à partir du moment où le système à déjà commencé à réagir (et pas à partir du moment où on a modifié la consigne. Pour ceux qui se demandent d’où sort les 63%, vous trouverez toutes les explications (attention, maths !) dans ce pdf Fichier:Derive63rule.pdf On regarde donc le nombre de secondes écoulées lorsqu’on arrive à 63% de δPV (ici 39*0.63 + 40 = 64.6°C), et le nombre de secondes écoulées au moment où le système commence à réagir (très rapide ici)

Détermination de la constante de temps TP

Détermination de la constante de temps Tp

On obtiens donc Tp = 172 secondes.

Le cas de θp

θp représente le temps mort avant réaction. Dans une boucle de contrôle, il n’est jamais très bon d’avoir du temps mort, et il sera nécessaire d’avoir cette valeur la plus faible possible. Du fait de mon montage de test, le temps mort est ici très réduit. Ceci s’explique facilement par la position du capteur (sur la résistance), et par le faible volume à chauffer (uniquement la résistance. De manière assez intuitive, on imagine très bien que plus le volume à chauffer sera important, plus le temps mort sera long, pour une même puissance de chauffe.

Si on reprend le graphique ci-dessus, on vois que la consigne a été modifié à T1=195s, et j’ai décider de compter le début de la réaction à T2=198s. On a donc θp = T2 – T1 = 198 – 195 = 3s.

Il est intéressant de noter ici que mon échantillonnage étant d’une seconde, la valeur de θp peut être sensiblement erronée, du fait de sa faible durée dans ce cas.

Application à un modèle PID

Formule PID, source ControlGuru

Formule PID, source ControlGuru

Avec:

  • CO = Sortie du contrôleur (Controller Output)
  • CObias = biais du contrôleur, ou valeur nulle.
  • e(T) = Erreur actuelle, définie par SP – PV
  • SP = consigne (Set Point)
  • PV = valeur actuelle du process (Process Value)
  • Kc = Gain du controlleur, un paramètre de réglage
  • Ti = reset time, un paramètre de réglage
  • Td = derivative time, un paramètre de réglage

Calcul du gain et du reset time

Il faut tout d’abord se demander si notre process accepte un dépassement de consigne ou pas, ainsi que la vitesse à laquelle ce process doit réagir.

  • Si on accepte un dépassement, on peut choisir un réglage agressif, et donc un faible temps de réponse (petit Tc). Dans ce cas, Tc est le plus grand de 0.1Tp ou 0.8θp
  • Modéré, le contrôleur produira peu ou pas de dépassement. Dans ce cas, Tc est le plus grand de 1.Tp ou 8.θP
  • Conservateur, le contrôleur ne produira pas de dépassement, mais ira doucement, Tc sera le plus grand de 10.Tp ou 80.θP

Une fois décidé du comportement de notre contrôleur, et calculé Tc, on peut calculer le gain du contrôleur et le reset time grâce à la formule suivante :

source : controlguru

source : controlguru

Pour mon application, je vais choisir un comportement modéré. Tc sera donc la plus grande valeur de 1.Tp ou 8.θP (1×172 ou 8*3=24). On retiendra donc Tc = 172.

J’obtiens donc Kc = (1/3.98)*(172/(3+172)) = 0.25%/°C et Ti = 172

Je peux maintenant calculer mes deux principaux paramètres P et I :
P = Kc = 0.25
I=Kc/Ti. = 0.25/172 = 0.00145
Reste à déterminer D. la formule permettant de déterminer D est Kc.Td, avec Td = (Tp.θP)/(2Tp+θP) = (172*3)/(344+3) = 1.487. D vaut donc 0.25*1.487=0.372
D = 0.372

Mise en application

Reste maintenant à confronter les calculs à la réalité. Voici le code Arduino que j’ai utilisé pour effectuer mes tests :

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// 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);
DeviceAddress insideThermometer;

unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int sampleTime = 1000; //1 sec
double outMin, outMax;
String cmd = String("");
double tfirst = 0;

float printTemperature(DeviceAddress deviceAddress)
{
  sensors.getAddress(insideThermometer, 0);
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print(" ");
  Serial.print(Output);
  Serial.print(" ");
  Serial.println(Setpoint);
  return(tempC);
}

void compute()
{
  unsigned long now = millis();
  int timeChange = (now-lastTime);
  if(timeChange>=sampleTime)
    {
      //get the new input value
      Input = getInput();
      //compute all working error variables
      double error = Setpoint - Input;
      ITerm+=(ki * error);
      if(ITerm>outMax) ITerm = outMax;
      else if(ITerm < outMin) ITerm = outMin;
      double dInput = (Input - lastInput);
      
      //compute PID output
      Output = kp * error + ITerm - kd * dInput;
      if(Output > outMax) Output = outMax;
      else if(Output < outMin) Output = outMin;
      
      //remember some variables for next round
      lastInput = Input;
      lastTime = now;
    }
}

void setTunings(double Kp, double Ki, double Kd)
{
  double sampleTimeInSec = ((double)sampleTime)/1000;
  kp = Kp;
  ki = Ki * sampleTimeInSec;
  kd = Kd / sampleTimeInSec;
}

void setSampleTime(int NewSampleTime)
{
  if (NewSampleTime>0)
  {
    double ratio = (double)NewSampleTime / (double)sampleTime;
    
    ki *= ratio;
    kd /= ratio;
    sampleTime = (unsigned long)NewSampleTime;
  }
}

void setOutputLimits(double Min, double Max)
{
  if(Min > Max) return;
  outMin = Min;
  outMax = Max;
  
  if(Output > outMax) Output = outMax;
  else if (Output < outMin) Output = outMin;
  
  if(ITerm>outMax) ITerm = outMax;
  else if(ITerm<outMin) ITerm = outMin;
}

double getInput(void)
{
  sensors.setResolution(insideThermometer, 9);
  sensors.requestTemperatures(); // Send the command to get temperatures
  return printTemperature(insideThermometer);
}

void setup()
{
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  Setpoint = 0; //on fixe 0 de consigne
  double P, I, D;
  P = 0.25;
  I = 0.00145;
  D = 0.372;
  int STime = 1000;
  setTunings(P,I,D);
  setSampleTime(STime);
  setOutputLimits(0, 255);
}

void loop(){
compute();
analogWrite(3,Output);
if (Serial.available() > 0) {
      char SerialInByte;
      SerialInByte = Serial.read();
      
      if(SerialInByte==13){
        Setpoint = cmd.toInt();
        cmd = String("");
      }
      else
      {
        cmd += String(SerialInByte);
      }
  }
}

et voici le résultat :

Test des paramètres PID calculés

Test des paramètres PID calculés

Conclusion :

J’ai utilisé des paramètres « conservateurs » afin d’éviter de dépasser la consigne. On peut voir qu’effectivement la consigne n’est jamais dépassée, au prix d’une montée en charge un peu lente. En partant sur cette bonne base, il est maintenant facile d’affiner si l’on souhaite quelque chose d’un peu plus réactif, il reste de la marge de manœuvre.

Sources :

La régulation étant un vaste domaine, j’ai trouvé beaucoup d’informations pertinentes sur les deux sites suivants. Si vous n’êtes pas anglophobe, et désirez approfondir le sujet, je vous les recommandes chaudement !
ControlGuru
brettbeauregard.com, auteur d’osPID

Étant donné que je n’ai pas encore tout le matériel nécessaire pour avancer mes autres projets, j’en profite pour approfondir un peu mes connaissances théoriques et vous en fait donc profiter. Mon projet ici est simple : Réguler une température à l’aide d’un microcontrolleur, mais surtout bien comprendre les tenants et aboutissements des différents réglages et algorithmes. L’objectif ici n’est pas tant d’expliquer ce qu’est un PID, ni comment il fonctionne dans le detail, mais plutôt de donner une méthode permettant d’approximer les coefficients du régulateur.

Je profiterais de cette expérience pour faire 2 articles :
– celui-ci concernant le PID a proprement parler
– Un second article concernant ma méthode pour obtenir des courbes « lives » a partir d’un arduino et d’un PC.

Qu’es-ce qu’un PID

Pour simplifier, on parlera dans la suite de régulation de température, vu que ce sera notre application ici. Mais bien entendu, une régulation peut se faire sur tout type de process (vitesse, débit, etc…)

Lorsqu’on veut réguler la température (d’une pièce par exemple), l’idée la plus simple qui nous vient à l’esprit est de faire une régulation tout-ou-rien : on est en dessous d’un premier seuil, on allume la chauffe, on passe au dessus d’un second seuil on coupe la chauffe. Cette façon de procéder, bien que très simple à implémenter n’est pas exempte de défauts. Par exemple, la température ne sera jamais vraiment constante, même si elle l’est « en moyenne ». Selon le process, on peut arriver à fortement dépasser les consignes (dans un sens ou dans l’autre), en fonction de l’inertie du système, ce qui peut s’avérer nuisible selon ce qu’on veut faire. Enfin, la puissance du chauffage oscillera entre 0 et 100%, ce qui engendre une surconsommation non négligeable.

La régulation PID permet de coller « au plus juste » à la consigne, en évitant les dépassement (en fonction du réglage comme on le verra plus loin), et en n’utilisant que la puissance nécessaire à aller à la consigne et à la maintenir. Concrètement, dans PID, on a P pour Proportionnelle, D pour Dérivée, et I pour Intégrale. Si comme moi vous avez tendance à être un peu allergique aux maths, vous commencez déjà à vous sauver, mais en fait c’est moins compliqué que ça n’en a l’air.

Proportionnelle : c’est ni plus ni moins que la différence entre votre consigne et la valeur actuelle, multiplié par un coefficient de proportionnalité (Que vous définissez, cf la suite). Dans la suite, nous l’écrirons Kc.e(t)

Intégrale : A chaque mesure, vous allez avoir une différence avec la consigne (en plus ou en moins). Prenez cette erreur à chaque pas de temps, multipliez la par un (autre) coefficient de proportionnalité, et additionnez le résultat de tous les pas de temps depuis le début, et vous avez la fameuse composante Intégrale. Dans la suite, l’intégrale sera notée de la façon suivante :

I

 

Dérivée : Son rôle est de « freiner » l’augmentation de puissance calculée en fonction de P et de I, de manière à ne pas dépasser la consigne. C’est une façon de prendre en compte la vitesse d’évolution de notre process. Pour le calculer, vous faites erreur actuelle – erreur précédente, multiplié par un troisième coefficient de proportionnalité

La formule globale de notre régulateur PID peut donc s’écrire de la manière suivante (plus d’explications plus bas):

Formule PID, source ControlGuru

Formule PID, source ControlGuru

 

Description du materiel

Le montage utilisé pour ces essais est très simple : un arduino, un bouton 2 positions, 1 capteur de température (DS18B20), un mosfet (IRF540), une résistance 10Ω 5W, et une alimentation 12V. Le mosfet est piloté par une sortie PWM de l’arduino, et gère le courant (puissance) transitant dans la résistance. Cette dernière chauffe donc plus ou moins en fonction du ratio PWM (la tension change) envoyé par l’arduino. Le bouton 2 positions sert à passer d’une première consigne (valeur PWM 5 sur 255) à une seconde (valeur PWM 30 sur 255) Un petit programme python enregistre les valeurs dans un fichier texte sur le pc (via connection série), et j’utilise GnuPlot pour avoir une jolie courbe et pouvoir lire les valeurs des graphiques plus facilement que directement sur l’image. Par la suite, j’ai ameliore mon script python, de maniere a pouvoir saisir une consigne via le port serie, tout en continuant de logguer.

Montage régulation de température

Montage régulation de température. Attention, utiliser une résistance 5W mini !

Méthode de réglage

Je vous présente une méthode « graphique » directement tirée du site Control Guru, appliquée à mon montage de test. Ce site étant en anglais et très dense en informations, j’ai essayé de résumer les points essentiels ici. J’invite ceux qui voudraient approfondir le sujet à consulter ce site qui est une véritable mine d’information sur la régulation.

Définitions

  • PV : Process Variable, cela correspond à la grandeur mesurée que l’on veut influencer (la température dans cet exemple)
  • CO : Controller Output , la sortie de notre contrôleur en %. (Correspond à l’ouverture de la vanne par exemple)
  • Kp : Gain du process
  • Kc : Gain du contrôleur

Introduction

Une fois modélisé notre boucle de contrôle, nous allons pouvoir en déterminer les trois paramètres principaux par expérimentation, mesure et calcul (et oui…)

Les paramètres à déterminer sont :

  • Kp : la Gain du process, ou, dit autrement, le sens et la grandeur de la variation de la sortie
  • Tp : Constante de temps du process, ou la vitesse de variation quand le process a commencé à répondre
  • θp : (Prononcer Thêta P) Temps mort du process, ou le délai écoulé avant que le process commence à réagir
Boucle de contrôle

Boucle de contrôle

Afin de pouvoir déterminer nos trois paramètres, il va nous falloir mesurer la façon dont réagis notre système. La première étape consiste donc à fixer une première valeur de sortie à notre contrôleur (CO) et attendre que la variable de sortie (PV, ici la température) soit bien stabilisée.

Une fois cette dernière stable, nous allons modifier la valeur de sortie du contrôleur (CO), et mesurer le changement obtenu sur la variable de sortie (PV). On logue bien sûr tout ça dans un fichier, avec les pas de temps, de manière à pouvoir également déterminer le temps mort du process (θp) et la vitesse de variation (Tp).

On se sert ensuite de ces mesures pour tracer un joli graphique, qui nous servira à déterminer nos différentes valeurs.

La formule permettant de déterminer notre premier paramètre Kc, qui est à la base du calcul de nos 3 paramètres (cf. formule) est la suivante :

source : controlguru

source : controlguru

pour déterminer Kc, nous devons donc commencer par déterminer différentes variables intermédiaires.

Calcul de Kp

Kp décrit le sens et de combien va évoluer PV, en fonction d’un changement de consigne (CO) Le cacul de Kp est assez simple : Kp=ΔPV/ΔCO ou en d’autre termes Kp = (différence en PV initial et PV final)/(différence entre consigne initiale et finale)

Sur mon prototype, j’ai modifié la consigne initiale (1,96%) pour une nouvelle consigne à 11.76%, voici la courbe obtenue:

Graphique test du système.

Graphique test du système.

En appliquant la formule ci-dessus, on a donc Kp = (79-40)/(11,76-1,96) = 39/9.8 = 3.98°C/%

Détermination de la constante de temps Tp

Tp représente le « en combien de temps » le système va réagir. En partant du même graphique, on va déterminer quand l’état de sortie vaut 63% de δPV, à partir du moment où le système à déjà commencé à réagir (et pas à partir du moment où on a modifié la consigne. Pour ceux qui se demandent d’où sort les 63%, vous trouverez toutes les explications (attention, maths !) dans ce pdf Fichier:Derive63rule.pdf On regarde donc le nombre de secondes écoulées lorsqu’on arrive à 63% de δPV (ici 39*0.63 + 40 = 64.6°C), et le nombre de secondes écoulées au moment où le système commence à réagir (très rapide ici)

Détermination de la constante de temps TP

Détermination de la constante de temps Tp

On obtiens donc Tp = 172 secondes.

Le cas de θp

θp représente le temps mort avant réaction. Dans une boucle de contrôle, il n’est jamais très bon d’avoir du temps mort, et il sera nécessaire d’avoir cette valeur la plus faible possible. Du fait de mon montage de test, le temps mort est ici très réduit. Ceci s’explique facilement par la position du capteur (sur la résistance), et par le faible volume à chauffer (uniquement la résistance. De manière assez intuitive, on imagine très bien que plus le volume à chauffer sera important, plus le temps mort sera long, pour une même puissance de chauffe.

Si on reprend le graphique ci-dessus, on vois que la consigne a été modifié à T1=195s, et j’ai décider de compter le début de la réaction à T2=198s. On a donc θp = T2 – T1 = 198 – 195 = 3s.

Il est intéressant de noter ici que mon échantillonnage étant d’une seconde, la valeur de θp peut être sensiblement erronée, du fait de sa faible durée dans ce cas.

Application à un modèle PID

Formule PID, source ControlGuru

Formule PID, source ControlGuru

Avec:

  • CO = Sortie du contrôleur (Controller Output)
  • CObias = biais du contrôleur, ou valeur nulle.
  • e(T) = Erreur actuelle, définie par SP – PV
  • SP = consigne (Set Point)
  • PV = valeur actuelle du process (Process Value)
  • Kc = Gain du controlleur, un paramètre de réglage
  • Ti = reset time, un paramètre de réglage
  • Td = derivative time, un paramètre de réglage

Calcul du gain et du reset time

Il faut tout d’abord se demander si notre process accepte un dépassement de consigne ou pas, ainsi que la vitesse à laquelle ce process doit réagir.

  • Si on accepte un dépassement, on peut choisir un réglage agressif, et donc un faible temps de réponse (petit Tc). Dans ce cas, Tc est le plus grand de 0.1Tp ou 0.8θp
  • Modéré, le contrôleur produira peu ou pas de dépassement. Dans ce cas, Tc est le plus grand de 1.Tp ou 8.θP
  • Conservateur, le contrôleur ne produira pas de dépassement, mais ira doucement, Tc sera le plus grand de 10.Tp ou 80.θP

Une fois décidé du comportement de notre contrôleur, et calculé Tc, on peut calculer le gain du contrôleur et le reset time grâce à la formule suivante :

source : controlguru

source : controlguru

Pour mon application, je vais choisir un comportement modéré. Tc sera donc la plus grande valeur de 1.Tp ou 8.θP (1×172 ou 8*3=24). On retiendra donc Tc = 172.

J’obtiens donc Kc = (1/3.98)*(172/(3+172)) = 0.25%/°C et Ti = 172

Je peux maintenant calculer mes deux principaux paramètres P et I :
P = Kc = 0.25
I=Kc/Ti. = 0.25/172 = 0.00145
Reste à déterminer D. la formule permettant de déterminer D est Kc.Td, avec Td = (Tp.θP)/(2Tp+θP) = (172*3)/(344+3) = 1.487. D vaut donc 0.25*1.487=0.372
D = 0.372

Mise en application

Reste maintenant à confronter les calculs à la réalité. Voici le code Arduino que j’ai utilisé pour effectuer mes tests :

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// 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);
DeviceAddress insideThermometer;

unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int sampleTime = 1000; //1 sec
double outMin, outMax;
String cmd = String("");
double tfirst = 0;

float printTemperature(DeviceAddress deviceAddress)
{
  sensors.getAddress(insideThermometer, 0);
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print(" ");
  Serial.print(Output);
  Serial.print(" ");
  Serial.println(Setpoint);
  return(tempC);
}

void compute()
{
  unsigned long now = millis();
  int timeChange = (now-lastTime);
  if(timeChange>=sampleTime)
    {
      //get the new input value
      Input = getInput();
      //compute all working error variables
      double error = Setpoint - Input;
      ITerm+=(ki * error);
      if(ITerm>outMax) ITerm = outMax;
      else if(ITerm < outMin) ITerm = outMin;
      double dInput = (Input - lastInput);
      
      //compute PID output
      Output = kp * error + ITerm - kd * dInput;
      if(Output > outMax) Output = outMax;
      else if(Output < outMin) Output = outMin;
      
      //remember some variables for next round
      lastInput = Input;
      lastTime = now;
    }
}

void setTunings(double Kp, double Ki, double Kd)
{
  double sampleTimeInSec = ((double)sampleTime)/1000;
  kp = Kp;
  ki = Ki * sampleTimeInSec;
  kd = Kd / sampleTimeInSec;
}

void setSampleTime(int NewSampleTime)
{
  if (NewSampleTime>0)
  {
    double ratio = (double)NewSampleTime / (double)sampleTime;
    
    ki *= ratio;
    kd /= ratio;
    sampleTime = (unsigned long)NewSampleTime;
  }
}

void setOutputLimits(double Min, double Max)
{
  if(Min > Max) return;
  outMin = Min;
  outMax = Max;
  
  if(Output > outMax) Output = outMax;
  else if (Output < outMin) Output = outMin;
  
  if(ITerm>outMax) ITerm = outMax;
  else if(ITerm<outMin) ITerm = outMin;
}

double getInput(void)
{
  sensors.setResolution(insideThermometer, 9);
  sensors.requestTemperatures(); // Send the command to get temperatures
  return printTemperature(insideThermometer);
}

void setup()
{
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  Setpoint = 0; //on fixe 0 de consigne
  double P, I, D;
  P = 0.25;
  I = 0.00145;
  D = 0.372;
  int STime = 1000;
  setTunings(P,I,D);
  setSampleTime(STime);
  setOutputLimits(0, 255);
}

void loop(){
compute();
analogWrite(3,Output);
if (Serial.available() > 0) {
      char SerialInByte;
      SerialInByte = Serial.read();
      
      if(SerialInByte==13){
        Setpoint = cmd.toInt();
        cmd = String("");
      }
      else
      {
        cmd += String(SerialInByte);
      }
  }
}

et voici le résultat :

Test des paramètres PID calculés

Test des paramètres PID calculés

Conclusion :

J’ai utilisé des paramètres « conservateurs » afin d’éviter de dépasser la consigne. On peut voir qu’effectivement la consigne n’est jamais dépassée, au prix d’une montée en charge un peu lente. En partant sur cette bonne base, il est maintenant facile d’affiner si l’on souhaite quelque chose d’un peu plus réactif, il reste de la marge de manœuvre.

Sources :

La régulation étant un vaste domaine, j’ai trouvé beaucoup d’informations pertinentes sur les deux sites suivants. Si vous n’êtes pas anglophobe, et désirez approfondir le sujet, je vous les recommandes chaudement !
ControlGuru
brettbeauregard.com, auteur d’osPID

Bonjour à tous,

J’ai reçu quelques capteurs intéressants, dont un capteur infrarouge (permettant par exemple de détecter une source de chaleur), on va donc reprendre un tuto avec ce capteur et un arduino (et un bonus en deuxième partie de tutoriel).

Le matériel

Pour ce tutoriel il nous faudra :

  • Un arduino (ici un Uno)
  • Un capteur HC SR-501
  • 3 fils
  • Une led 5mm

Et c’est tout. Minimaliste comme montage non ?

Le principe

Un capteur infrarouge permet de détecter un mouvement dans son champ de vision en se basant sur l’infrarouge. On parle aussi de capteur pyroélectrique ou PIR. Le PIR sont capable de détecter une variation des ondes infrarouges, ce qui génère un courant électrique. Dans le cas de notre capteur, il est en fait divisé en deux partie différente reliées ensemble afin de détecter une variation lors qu’une des moitiés capte plus qu’une autre. On a ainsi un relevé d’une différence, et non plus d’une valeur simple.

Lors d’un mouvement, la variation des deux moitiés vont varier, et on va donc capter cette variation positive.

Principe de fonctionnement

Principe de fonctionnement

Le capteur

Le capteur lui même ressemble à ça :

Le capteur

Le capteur

Et l’intérieur fonctionne de la manière suivante :

PIR_interneLes spécifications techniques sont les suivantes :

  • Entrée : Courant continue de 4.5 à 20V
  • Sortie : High 3.3 V / Low 0V (Détection ou non)
  • Angle : <100 °
  • Dimension : 32 mm * 24 mm
  • Délai : de 5 à 200 secondes (ajustable)
  • Portée : de 3 à 7 mètres (ajustable).
  • Au repos : 50 microampères.

Le montage

Au vu des éléments nécessaires, vous allez voir, c’est plutôt simple !

Branchement du PIR sur l'arduino Uno

Branchement du PIR sur l’arduino Uno

On branche donc :

  • Le VCC du Pir  sur le 5V de l’arduino
  • Le GRD du PIR sur le GRD de l’arduino
  • La dernière branche sur le pin 2 de l’arduino
  • On ajoute une led de contrôle entre le pin 13 et un GRD de l’arduino

Mais attention : D’un PIR à l’autre, les branchements sont inversés ! J’avais 2 types de PIR, et j’ai grillé 2 PIR avant de me rendre compte que le branchement + et – était différent entre les 2 types de capteurs. BIEN SE RENSEIGNER AUPRÈS DU REVENDEUR !

Le code

Il est enfin temps de faire fonctionner tout ça ! Rien de bien compliqué non plus. On va commencer par laisser 30 secondes au PIR pour se calibrer, puis un fois cela fait, on va en boucle relever la valeur que nous renvoi le capteur : 0 ou 1. 0 signifiant pas de signal et 1 signifiant qu’il détecte une variation infrarouge.

Le code en lui même est disponible sur mon dépôt github : ici.

Si vous n’êtes pas à l’aise avec github, je vous le reproduis ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);

  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}

On commence donc par initialiser les pins dans leur état d’entrée ou de sortie, puis on calibre le capteur.

Puis dans le loop, on relève la valeur renvoyée par le capteur et on agit en conséquence. Quand vous lancez le moniteur, vous avez alors un retour comme ceci :

Ce que le moniteur nous ressort

Ce que le moniteur nous ressort

 

Bonus : Créer une lampe qui s’allume automatiquement

On va profiter de ce capteur pour l’utiliser dans un cas pratique ! Nous allons le coupler avec un relai, qui va nous permettre de contrôler du courant (du 220V par exemple) pour allumer ou éteindre une lampe lorsque l’on détecte un mouvement. Cette deuxième partie est donc un cas pratique d’utilisation de notre capteur de mouvement.

Le matériel nécessaire, en plus est le suivant :

Pour la lampe, j’ai acheté une lampe à LED chez Castorama à 12€. Vu qu’il faut couper le câble d’alimentation pour le montage, évitez de sacrifier une lampe de qualité (ça vaut mieux pour la paix des ménages).

Un relais, ou relais électromagnétique est, selon wikipedia un organe électrique permettant de dissocier la partie puissance de la partie commande, autrement dit,  Il permet l’ouverture / la fermeture d’un circuit électrique par un second circuit totalement isolé. Ici, nous allons donc contrôler l’ouverture ou la fermeture du circuit en 220V (enfin 12V sur ma lampe de test) avec un second circuit en 5V contrôlé par la carte Arduino.

Voila à quoi va désormais ressembler notre montage :

Schéma du montage PIR et relais

Schéma du montage PIR et relais

Comme vous pouvez le voir, le montage du PIR ne varie pas, on le connecte toujours aux mêmes bornes.

Pour le relais, il faut faire 2 choses : Connecter GND à la masse commune du montage (pir et relais doivent avoir la même masse), connecter le VCC au 5V fourni par l’arduino, et connecter le pin de données au port 3 de l’arduino.

De l’autre côté du relais, il va falloir couper votre câble d’alimentation de la lampe.  On va donc avoir quelque chose qui ressemble à ça :

Contrôle de l'alimentation de la lampe grâce au module relais

Contrôle de l’alimentation de la lampe grâce au module relais

Le montage dans son ensemble

Le montage dans son ensemble

Avant de vous donner le code, voici une petite vidéo qui vous montre comment tout cela fonctionne :

Passons au code désormais. Comme vous pouvez vous en douter, on va utiliser le code de la première partie du tutoriel que l’on va enrichir pour prendre en compte le contrôle du module relais.

Vous trouverez le code sur mon dépôt github, ici.

Si vous êtes githubophobe, vous trouverez le code ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;  
// The time the device will stay on
int delayTime = 5000;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int relayPin = 3;
int pirState = LOW;             // we start, assuming no motion detected
int stateRelay = HIGH;
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(relayPin, OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);
  digitalWrite(relayPin, stateRelay);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  //Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);    

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);    
      if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }

  Serial.println(pirState);
  if(pirState == HIGH){
     digitalWrite(relayPin, LOW);
     delay(delayTime);
  } else {
     digitalWrite(relayPin, HIGH);
  }
}

Comme vous pouvez le voir, rien de bien compliqué ! Comme dans le premier montage, on contrôle si on détecte un mouvement, et si oui, dans ce cas on va activer le module relais pour allumer la lampe.

Et voila, c’est fini pour ce tutoriel.

Précaution importante

Ce montage est assez simpliste et n’est en soit pas sécurisé pour l’arduino. En effet, le fait d’ouvrir ou fermer un relai va générer des surtensions. Si vous souhaitez utiliser ce montage de manière régulière, il va donc être IMPÉRATIF de protéger votre circuit. Heureusement, c’est assez simple.

Je vous invite à lire ce tuto pour en savoir plus et protéger votre circuit. L’idée est d’utiliser une diode pour protéger notre arduino des retours potentiels du relais. Il se peut aussi que votre module relais possède déjà cette sécurité, donc à vous de vérifier en fonction du module que vous avez acheté !

Voila, c’est enfin tout pour ce tutoriel. Si vous avez des questions, n’hésitez pas !

 

Bonjour à tous,

J’ai reçu quelques capteurs intéressants, dont un capteur infrarouge (permettant par exemple de détecter une source de chaleur), on va donc reprendre un tuto avec ce capteur et un arduino (et un bonus en deuxième partie de tutoriel).

Le matériel

Pour ce tutoriel il nous faudra :

  • Un arduino (ici un Uno)
  • Un capteur HC SR-501
  • 3 fils
  • Une led 5mm

Et c’est tout. Minimaliste comme montage non ?

Le principe

Un capteur infrarouge permet de détecter un mouvement dans son champ de vision en se basant sur l’infrarouge. On parle aussi de capteur pyroélectrique ou PIR. Le PIR sont capable de détecter une variation des ondes infrarouges, ce qui génère un courant électrique. Dans le cas de notre capteur, il est en fait divisé en deux partie différente reliées ensemble afin de détecter une variation lors qu’une des moitiés capte plus qu’une autre. On a ainsi un relevé d’une différence, et non plus d’une valeur simple.

Lors d’un mouvement, la variation des deux moitiés vont varier, et on va donc capter cette variation positive.

Principe de fonctionnement

Principe de fonctionnement

Le capteur

Le capteur lui même ressemble à ça :

Le capteur

Le capteur

Et l’intérieur fonctionne de la manière suivante :

PIR_interneLes spécifications techniques sont les suivantes :

  • Entrée : Courant continue de 4.5 à 20V
  • Sortie : High 3.3 V / Low 0V (Détection ou non)
  • Angle : <100 °
  • Dimension : 32 mm * 24 mm
  • Délai : de 5 à 200 secondes (ajustable)
  • Portée : de 3 à 7 mètres (ajustable).
  • Au repos : 50 microampères.

Le montage

Au vu des éléments nécessaires, vous allez voir, c’est plutôt simple !

Branchement du PIR sur l'arduino Uno

Branchement du PIR sur l’arduino Uno

On branche donc :

  • Le VCC du Pir  sur le 5V de l’arduino
  • Le GRD du PIR sur le GRD de l’arduino
  • La dernière branche sur le pin 2 de l’arduino
  • On ajoute une led de contrôle entre le pin 13 et un GRD de l’arduino

Mais attention : D’un PIR à l’autre, les branchements sont inversés ! J’avais 2 types de PIR, et j’ai grillé 2 PIR avant de me rendre compte que le branchement + et – était différent entre les 2 types de capteurs. BIEN SE RENSEIGNER AUPRÈS DU REVENDEUR !

Le code

Il est enfin temps de faire fonctionner tout ça ! Rien de bien compliqué non plus. On va commencer par laisser 30 secondes au PIR pour se calibrer, puis un fois cela fait, on va en boucle relever la valeur que nous renvoi le capteur : 0 ou 1. 0 signifiant pas de signal et 1 signifiant qu’il détecte une variation infrarouge.

Le code en lui même est disponible sur mon dépôt github : ici.

Si vous n’êtes pas à l’aise avec github, je vous le reproduis ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);

  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}

On commence donc par initialiser les pins dans leur état d’entrée ou de sortie, puis on calibre le capteur.

Puis dans le loop, on relève la valeur renvoyée par le capteur et on agit en conséquence. Quand vous lancez le moniteur, vous avez alors un retour comme ceci :

Ce que le moniteur nous ressort

Ce que le moniteur nous ressort

 

Bonus : Créer une lampe qui s’allume automatiquement

On va profiter de ce capteur pour l’utiliser dans un cas pratique ! Nous allons le coupler avec un relai, qui va nous permettre de contrôler du courant (du 220V par exemple) pour allumer ou éteindre une lampe lorsque l’on détecte un mouvement. Cette deuxième partie est donc un cas pratique d’utilisation de notre capteur de mouvement.

Le matériel nécessaire, en plus est le suivant :

Pour la lampe, j’ai acheté une lampe à LED chez Castorama à 12€. Vu qu’il faut couper le câble d’alimentation pour le montage, évitez de sacrifier une lampe de qualité (ça vaut mieux pour la paix des ménages).

Un relais, ou relais électromagnétique est, selon wikipedia un organe électrique permettant de dissocier la partie puissance de la partie commande, autrement dit,  Il permet l’ouverture / la fermeture d’un circuit électrique par un second circuit totalement isolé. Ici, nous allons donc contrôler l’ouverture ou la fermeture du circuit en 220V (enfin 12V sur ma lampe de test) avec un second circuit en 5V contrôlé par la carte Arduino.

Voila à quoi va désormais ressembler notre montage :

Schéma du montage PIR et relais

Schéma du montage PIR et relais

Comme vous pouvez le voir, le montage du PIR ne varie pas, on le connecte toujours aux mêmes bornes.

Pour le relais, il faut faire 2 choses : Connecter GND à la masse commune du montage (pir et relais doivent avoir la même masse), connecter le VCC au 5V fourni par l’arduino, et connecter le pin de données au port 3 de l’arduino.

De l’autre côté du relais, il va falloir couper votre câble d’alimentation de la lampe.  On va donc avoir quelque chose qui ressemble à ça :

Contrôle de l'alimentation de la lampe grâce au module relais

Contrôle de l’alimentation de la lampe grâce au module relais

Le montage dans son ensemble

Le montage dans son ensemble

Avant de vous donner le code, voici une petite vidéo qui vous montre comment tout cela fonctionne :

Passons au code désormais. Comme vous pouvez vous en douter, on va utiliser le code de la première partie du tutoriel que l’on va enrichir pour prendre en compte le contrôle du module relais.

Vous trouverez le code sur mon dépôt github, ici.

Si vous êtes githubophobe, vous trouverez le code ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;  
// The time the device will stay on
int delayTime = 5000;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int relayPin = 3;
int pirState = LOW;             // we start, assuming no motion detected
int stateRelay = HIGH;
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(relayPin, OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);
  digitalWrite(relayPin, stateRelay);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  //Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);    

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);    
      if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }

  Serial.println(pirState);
  if(pirState == HIGH){
     digitalWrite(relayPin, LOW);
     delay(delayTime);
  } else {
     digitalWrite(relayPin, HIGH);
  }
}

Comme vous pouvez le voir, rien de bien compliqué ! Comme dans le premier montage, on contrôle si on détecte un mouvement, et si oui, dans ce cas on va activer le module relais pour allumer la lampe.

Et voila, c’est fini pour ce tutoriel.

Précaution importante

Ce montage est assez simpliste et n’est en soit pas sécurisé pour l’arduino. En effet, le fait d’ouvrir ou fermer un relai va générer des surtensions. Si vous souhaitez utiliser ce montage de manière régulière, il va donc être IMPÉRATIF de protéger votre circuit. Heureusement, c’est assez simple.

Je vous invite à lire ce tuto pour en savoir plus et protéger votre circuit. L’idée est d’utiliser une diode pour protéger notre arduino des retours potentiels du relais. Il se peut aussi que votre module relais possède déjà cette sécurité, donc à vous de vérifier en fonction du module que vous avez acheté !

Voila, c’est enfin tout pour ce tutoriel. Si vous avez des questions, n’hésitez pas !

 

Jun
27

Tuto – Lire un capteur infrarouge avec Arduino

arduino, ArduRasp, capteur, diy, Domotique, planet, tutoriel Comments Off on Tuto – Lire un capteur infrarouge avec Arduino 

Bonjour à tous,

J’ai reçu quelques capteurs intéressants, dont un capteur infrarouge (permettant par exemple de détecter une source de chaleur), on va donc reprendre un tuto avec ce capteur et un arduino (et un bonus en deuxième partie de tutoriel).

Le matériel

Pour ce tutoriel il nous faudra :

  • Un arduino (ici un Uno)
  • Un capteur HC SR-501
  • 3 fils
  • Une led 5mm

Et c’est tout. Minimaliste comme montage non ?

Le principe

Un capteur infrarouge permet de détecter un mouvement dans son champ de vision en se basant sur l’infrarouge. On parle aussi de capteur pyroélectrique ou PIR. Le PIR sont capable de détecter une variation des ondes infrarouges, ce qui génère un courant électrique. Dans le cas de notre capteur, il est en fait divisé en deux partie différente reliées ensemble afin de détecter une variation lors qu’une des moitiés capte plus qu’une autre. On a ainsi un relevé d’une différence, et non plus d’une valeur simple.

Lors d’un mouvement, la variation des deux moitiés vont varier, et on va donc capter cette variation positive.

Principe de fonctionnement

Principe de fonctionnement

Le capteur

Le capteur lui même ressemble à ça :

Le capteur

Le capteur

Et l’intérieur fonctionne de la manière suivante :

PIR_interneLes spécifications techniques sont les suivantes :

  • Entrée : Courant continue de 4.5 à 20V
  • Sortie : High 3.3 V / Low 0V (Détection ou non)
  • Angle : <100 °
  • Dimension : 32 mm * 24 mm
  • Délai : de 5 à 200 secondes (ajustable)
  • Portée : de 3 à 7 mètres (ajustable).
  • Au repos : 50 microampères.

Le montage

Au vu des éléments nécessaires, vous allez voir, c’est plutôt simple !

Branchement du PIR sur l'arduino Uno

Branchement du PIR sur l’arduino Uno

On branche donc :

  • Le VCC du Pir  sur le 5V de l’arduino
  • Le GRD du PIR sur le GRD de l’arduino
  • La dernière branche sur le pin 2 de l’arduino
  • On ajoute une led de contrôle entre le pin 13 et un GRD de l’arduino

Mais attention : D’un PIR à l’autre, les branchements sont inversés ! J’avais 2 types de PIR, et j’ai grillé 2 PIR avant de me rendre compte que le branchement + et – était différent entre les 2 types de capteurs. BIEN SE RENSEIGNER AUPRÈS DU REVENDEUR !

Le code

Il est enfin temps de faire fonctionner tout ça ! Rien de bien compliqué non plus. On va commencer par laisser 30 secondes au PIR pour se calibrer, puis un fois cela fait, on va en boucle relever la valeur que nous renvoi le capteur : 0 ou 1. 0 signifiant pas de signal et 1 signifiant qu’il détecte une variation infrarouge.

Le code en lui même est disponible sur mon dépôt github : ici.

Si vous n’êtes pas à l’aise avec github, je vous le reproduis ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);

  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}

On commence donc par initialiser les pins dans leur état d’entrée ou de sortie, puis on calibre le capteur.

Puis dans le loop, on relève la valeur renvoyée par le capteur et on agit en conséquence. Quand vous lancez le moniteur, vous avez alors un retour comme ceci :

Ce que le moniteur nous ressort

Ce que le moniteur nous ressort

 

Bonus : Créer une lampe qui s’allume automatiquement

On va profiter de ce capteur pour l’utiliser dans un cas pratique ! Nous allons le coupler avec un relai, qui va nous permettre de contrôler du courant (du 220V par exemple) pour allumer ou éteindre une lampe lorsque l’on détecte un mouvement. Cette deuxième partie est donc un cas pratique d’utilisation de notre capteur de mouvement.

Le matériel nécessaire, en plus est le suivant :

Pour la lampe, j’ai acheté une lampe à LED chez Castorama à 12€. Vu qu’il faut couper le câble d’alimentation pour le montage, évitez de sacrifier une lampe de qualité (ça vaut mieux pour la paix des ménages).

Un relais, ou relais électromagnétique est, selon wikipedia un organe électrique permettant de dissocier la partie puissance de la partie commande, autrement dit,  Il permet l’ouverture / la fermeture d’un circuit électrique par un second circuit totalement isolé. Ici, nous allons donc contrôler l’ouverture ou la fermeture du circuit en 220V (enfin 12V sur ma lampe de test) avec un second circuit en 5V contrôlé par la carte Arduino.

Voila à quoi va désormais ressembler notre montage :

Schéma du montage PIR et relais

Schéma du montage PIR et relais

Comme vous pouvez le voir, le montage du PIR ne varie pas, on le connecte toujours aux mêmes bornes.

Pour le relais, il faut faire 2 choses : Connecter GND à la masse commune du montage (pir et relais doivent avoir la même masse), connecter le VCC au 5V fourni par l’arduino, et connecter le pin de données au port 3 de l’arduino.

De l’autre côté du relais, il va falloir couper votre câble d’alimentation de la lampe.  On va donc avoir quelque chose qui ressemble à ça :

Contrôle de l'alimentation de la lampe grâce au module relais

Contrôle de l’alimentation de la lampe grâce au module relais

Le montage dans son ensemble

Le montage dans son ensemble

Avant de vous donner le code, voici une petite vidéo qui vous montre comment tout cela fonctionne :

Passons au code désormais. Comme vous pouvez vous en douter, on va utiliser le code de la première partie du tutoriel que l’on va enrichir pour prendre en compte le contrôle du module relais.

Vous trouverez le code sur mon dépôt github, ici.

Si vous êtes githubophobe, vous trouverez le code ci dessous :

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;  
// The time the device will stay on
int delayTime = 5000;

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int relayPin = 3;
int pirState = LOW;             // we start, assuming no motion detected
int stateRelay = HIGH;
int val = 0;                    // variable for reading the pin status

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(relayPin, OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);
  digitalWrite(relayPin, stateRelay);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    delay(1000);
  }
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

void loop(){
  val = digitalRead(inputPin);  // read input value
  //Serial.println(val);
  if (val == HIGH) { // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(150);    

    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    delay(300);    
      if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }

  Serial.println(pirState);
  if(pirState == HIGH){
     digitalWrite(relayPin, LOW);
     delay(delayTime);
  } else {
     digitalWrite(relayPin, HIGH);
  }
}

Comme vous pouvez le voir, rien de bien compliqué ! Comme dans le premier montage, on contrôle si on détecte un mouvement, et si oui, dans ce cas on va activer le module relais pour allumer la lampe.

Et voila, c’est fini pour ce tutoriel.

Précaution importante

Ce montage est assez simpliste et n’est en soit pas sécurisé pour l’arduino. En effet, le fait d’ouvrir ou fermer un relai va générer des surtensions. Si vous souhaitez utiliser ce montage de manière régulière, il va donc être IMPÉRATIF de protéger votre circuit. Heureusement, c’est assez simple.

Je vous invite à lire ce tuto pour en savoir plus et protéger votre circuit. L’idée est d’utiliser une diode pour protéger notre arduino des retours potentiels du relais. Il se peut aussi que votre module relais possède déjà cette sécurité, donc à vous de vérifier en fonction du module que vous avez acheté !

Voila, c’est enfin tout pour ce tutoriel. Si vous avez des questions, n’hésitez pas !

 

Bonjour,

Lors de ma visite au Maker Faire 2014, j’ai eut la possibilité de découvrir un nouveau magazine francophone dédié à la bidouille : Hackable Magazine. Intéressé par le concept, j’ai décidé de m’acheter le premier numéro dont le gros titre était : Rejoignez la révolution Arduino.

Hackable magazine : premier numéro

Hackable magazine : premier numéro

Tout un programme !

Je l’ai reçu très rapidement (3 jours après l’avoir commandé), et je l’ai dévoré de bout en bout. Un très bon premier jet !

Au sommaire de ce premier numéro vous trouverez :

  • La station de soudage, votre amie pour la vie
  • Un arduino de la taille d’une cacahouète
  • L’arduino starter kit : découverte
  • Arduino : un projet, une révolution et une gamme de cartes
  • Découvrir et apprendre le langage arduino
  • Loi d’Ohm : toute résistance est futile
  • Votre Raspberry Pi toujours à l’heure
  • L’ardu-sonnette intelligente : est-on passé en votre absence ?
  • L’ardu-sonnette intelligente : ajoutons un écran
  • E-Cigarette : rien de magique, que du technique
  • Comprendre la PWM

Voila pour ce premier numéro. Bien qu’étant habitué à l’arduino, j’ai tout de même fait l’effort de lire les articles (même si j’avoue avoir sauté quelques parties basiques), et c’était plutôt intéressant. Les articles sont plutôt bien écrit, et j’ai été agréablement surpris par le dossier sur la E-Cigarette.

Je me suis abonné pour 6 numéros pour 39 € livraison comprise, si ils sont tous aussi bien fait que celui là, je ne vais pas être déçu. Je vous invite à découvrir ce magazine fait pour les makers en herbe ou expérimentés.

Vous l’avez lu ? Qu’en avez vous pensé ?

 

Jun
26

Hackable Magazine

arduino, ArduRasp, diy, magazine, planet, Raspberry Pi Comments Off on Hackable Magazine 

Bonjour,

Lors de ma visite au Maker Faire 2014, j’ai eut la possibilité de découvrir un nouveau magazine francophone dédié à la bidouille : Hackable Magazine. Intéressé par le concept, j’ai décidé de m’acheter le premier numéro dont le gros titre était : Rejoignez la révolution Arduino.

Hackable magazine : premier numéro

Hackable magazine : premier numéro

Tout un programme !

Je l’ai reçu très rapidement (3 jours après l’avoir commandé), et je l’ai dévoré de bout en bout. Un très bon premier jet !

Au sommaire de ce premier numéro vous trouverez :

  • La station de soudage, votre amie pour la vie
  • Un arduino de la taille d’une cacahouète
  • L’arduino starter kit : découverte
  • Arduino : un projet, une révolution et une gamme de cartes
  • Découvrir et apprendre le langage arduino
  • Loi d’Ohm : toute résistance est futile
  • Votre Raspberry Pi toujours à l’heure
  • L’ardu-sonnette intelligente : est-on passé en votre absence ?
  • L’ardu-sonnette intelligente : ajoutons un écran
  • E-Cigarette : rien de magique, que du technique
  • Comprendre la PWM

Voila pour ce premier numéro. Bien qu’étant habitué à l’arduino, j’ai tout de même fait l’effort de lire les articles (même si j’avoue avoir sauté quelques parties basiques), et c’était plutôt intéressant. Les articles sont plutôt bien écrit, et j’ai été agréablement surpris par le dossier sur la E-Cigarette.

Je me suis abonné pour 6 numéros pour 39 € livraison comprise, si ils sont tous aussi bien fait que celui là, je ne vais pas être déçu. Je vous invite à découvrir ce magazine fait pour les makers en herbe ou expérimentés.

Vous l’avez lu ? Qu’en avez vous pensé ?

 

Bonjour,

Lors de ma visite au Maker Faire 2014, j’ai eut la possibilité de découvrir un nouveau magazine francophone dédié à la bidouille : Hackable Magazine. Intéressé par le concept, j’ai décidé de m’acheter le premier numéro dont le gros titre était : Rejoignez la révolution Arduino.

Hackable magazine : premier numéro

Hackable magazine : premier numéro

Tout un programme !

Je l’ai reçu très rapidement (3 jours après l’avoir commandé), et je l’ai dévoré de bout en bout. Un très bon premier jet !

Au sommaire de ce premier numéro vous trouverez :

  • La station de soudage, votre amie pour la vie
  • Un arduino de la taille d’une cacahouète
  • L’arduino starter kit : découverte
  • Arduino : un projet, une révolution et une gamme de cartes
  • Découvrir et apprendre le langage arduino
  • Loi d’Ohm : toute résistance est futile
  • Votre Raspberry Pi toujours à l’heure
  • L’ardu-sonnette intelligente : est-on passé en votre absence ?
  • L’ardu-sonnette intelligente : ajoutons un écran
  • E-Cigarette : rien de magique, que du technique
  • Comprendre la PWM

Voila pour ce premier numéro. Bien qu’étant habitué à l’arduino, j’ai tout de même fait l’effort de lire les articles (même si j’avoue avoir sauté quelques parties basiques), et c’était plutôt intéressant. Les articles sont plutôt bien écrit, et j’ai été agréablement surpris par le dossier sur la E-Cigarette.

Je me suis abonné pour 6 numéros pour 39 € livraison comprise, si ils sont tous aussi bien fait que celui là, je ne vais pas être déçu. Je vous invite à découvrir ce magazine fait pour les makers en herbe ou expérimentés.

Vous l’avez lu ? Qu’en avez vous pensé ?

 

Apr
20

Fan de ce style depuis pas mal de temps déjà, c’est ma première réalisation concrète. L’idée était de réaliser un (joli) thermomètre d’ambiance, histoire de savoir quelle température il fait dans la pièce. J’avais déjà réalisé un thermomètre à tubes Nixies, mais ce dernier avait deux défauts : les tubes n’étaient pas centrés sur le pcb, et il consommait un peu trop pour avoir envie de le laisser allumé en permanence (et en plus, il n’était pas « habillé »…).

Du coups, la première étape de cette réalisation a été de refaire un pcb complet. Pas simplement déplacer les tubes, j’en ai profité pour alléger le tout, histoire de supprimer les composants qui n’étaient pas nécessaires. En effet, sur la version précédente, j’utilisais un NE555 pour générer les impulsions nécessaires à la haute tension. Désormais cette tâche est réalisée par le microcontrolleur lui-même.

Schéma thermomètre Nixie

Schéma thermomètre Nixie

Quitte a devoir reprogrammer le microcontrolleur pour rajouter la génération de la haute tension, j’en ai profité pour tout ré-écrire en avrc. Ca me permet d’avoir un timing très précis, autant sur la génération du signal HT que sur le multiplexage des tubes. (La fréquence est importante pour la génération de la haute tension car elle joue pour beaucoup dans le rendement). Mon code aurais pu être grandement optimisé si j’avais un peu mieux réfléchi à mes branchements, mais sur ma version, je m’étais trompé sur certaines liaisons (ce qui expliquera les fils visibles sur les photos). Le schéma proposé corrige ces erreurs.

tarthermomètre nixie (AVRC)

 

Thermomètre à tube Nixie Steampunk

Thermomètre à tube Nixie Steampunk

Pour l’habillage, je me suis fait un peu plaisir. Les deux « chapeaux » sont en laiton, que j’ai tourné, moitié façon meca, c’est à dire en utilisant le tour de manière traditionnelle, moitié à main levée à l’aide d’une lime (pour les arrondis notamment). Le reste de l’accastillage est composé de différents tubes de laitons, diamètre 5 et 3mm, que l’on trouve facilement en magasin de modélisme.
Le tube est quand a lui un tube de plexyglass acheté pour l’occasion.

Socle vu de dessous

Socle vu de dessous

Le socle a été tourné dans un beau morceau de chêne, par un ami car je ne disposais pas de tour à bois, et le tour à metal n’est vraiment pas adapté à ce genre d’opérations. Le plot du milieu est assez profond pour que le tube laiton soit bien maintenu, mais ne va pas jusqu’en bas pour pouvoir laisser passer les fils. J’ai repris ensuite le socle tourné pour le fraiser afin de fixer le connecteur d’alimentation, et fait les 4 perçages nécessaires (2 pour les tubes verticaux, un pour le capteur de température, et un pour le connecteur d’alim).

Détail du capteur de température

Détail du capteur de température

Le capteur de température utilisé est un LM35. Pas particulièrement esthétique donc. Pour le masquer, je l’ai donc glissé à l’intérieur d’une douille de 22lr qu’un ami tireur m’a gentiment fourni. Le capteur est fixé à l’intérieur à la colle à chaud.

En fonctionnement

En fonctionnement

Fan de ce style depuis pas mal de temps déjà, c’est ma première réalisation concrète. L’idée était de réaliser un (joli) thermomètre d’ambiance, histoire de savoir quelle température il fait dans la pièce. J’avais déjà réalisé un thermomètre à tubes Nixies, mais ce dernier avait deux défauts : les tubes n’étaient pas centrés sur le pcb, et il consommait un peu trop pour avoir envie de le laisser allumé en permanence (et en plus, il n’était pas « habillé »…).

Du coups, la première étape de cette réalisation a été de refaire un pcb complet. Pas simplement déplacer les tubes, j’en ai profité pour alléger le tout, histoire de supprimer les composants qui n’étaient pas nécessaires. En effet, sur la version précédente, j’utilisais un NE555 pour générer les impulsions nécessaires à la haute tension. Désormais cette tâche est réalisée par le microcontrolleur lui-même.

Schéma thermomètre Nixie

Schéma thermomètre Nixie

Quitte a devoir reprogrammer le microcontrolleur pour rajouter la génération de la haute tension, j’en ai profité pour tout ré-écrire en avrc. Ca me permet d’avoir un timing très précis, autant sur la génération du signal HT que sur le multiplexage des tubes. (La fréquence est importante pour la génération de la haute tension car elle joue pour beaucoup dans le rendement). Mon code aurais pu être grandement optimisé si j’avais un peu mieux réfléchi à mes branchements, mais sur ma version, je m’étais trompé sur certaines liaisons (ce qui expliquera les fils visibles sur les photos). Le schéma proposé corrige ces erreurs.

tarthermomètre nixie (AVRC)

 

Thermomètre à tube Nixie Steampunk

Thermomètre à tube Nixie Steampunk

Pour l’habillage, je me suis fait un peu plaisir. Les deux « chapeaux » sont en laiton, que j’ai tourné, moitié façon meca, c’est à dire en utilisant le tour de manière traditionnelle, moitié à main levée à l’aide d’une lime (pour les arrondis notamment). Le reste de l’accastillage est composé de différents tubes de laitons, diamètre 5 et 3mm, que l’on trouve facilement en magasin de modélisme.
Le tube est quand a lui un tube de plexyglass acheté pour l’occasion.

Socle vu de dessous

Socle vu de dessous

Le socle a été tourné dans un beau morceau de chêne, par un ami car je ne disposais pas de tour à bois, et le tour à metal n’est vraiment pas adapté à ce genre d’opérations. Le plot du milieu est assez profond pour que le tube laiton soit bien maintenu, mais ne va pas jusqu’en bas pour pouvoir laisser passer les fils. J’ai repris ensuite le socle tourné pour le fraiser afin de fixer le connecteur d’alimentation, et fait les 4 perçages nécessaires (2 pour les tubes verticaux, un pour le capteur de température, et un pour le connecteur d’alim).

Détail du capteur de température

Détail du capteur de température

Le capteur de température utilisé est un LM35. Pas particulièrement esthétique donc. Pour le masquer, je l’ai donc glissé à l’intérieur d’une douille de 22lr qu’un ami tireur m’a gentiment fourni. Le capteur est fixé à l’intérieur à la colle à chaud.

En fonctionnement

En fonctionnement



  • Newsletter

    Sign up for the PlanetArduino Newsletter, which delivers the most popular articles via e-mail to your inbox every week. Just fill in the information below and submit.

  • Like Us on Facebook