Décaler la lecture de tension d'un capteur de pression

Bonjour,
Je suis sur un projet d'un boitier régulateur de sur-pression pour réaliser des essais au boulot.
Ce boitier est composé d'un NANO, un afficheur LCD I2C 4x20, des boutons, un moteur pas à pas, un clavier sans contact 12 touches et un capteur de pression (désolé croquis fait au début du projet):

Le principe est assez simple:
Le nano lit la tension sur la résistance du capteur et pilote le moteur pour augmenter ou diminuer la pression suivant la consigne rentrée.

Le capteur de pression est un Keller 0-2 bar avec sortie 4-20mA. En mettant une résistance dans le circuit d'alimentation, il est possible d'avoir la pression en volt (U=r*i).
La ou j'ai un problème, c'est que je ne travaille que sur la moitié de la plage (surpression de la pression ambiante jusqu'à 2 bars) et la conversion via l'entrée analogique me fait perdre en résolution (1024 points). Voici un graphique de la tension avec une résistance de 220 Ohm:

Je me retrouve avec une plage de tension ridicule pour mes mesures.
Existe t-il une solution pour "décaler" la mesure à partir d'environ 2.4/2.5V -> avoir les 1024 points d'environ 950 à 2000mbar ? ce qui ferait presque doubler la résolution.

Je partagerais l'avancée du projet au fur et à mesure.
Merci

En rajoutant un ampli différentiel vous pourriez retrouver un 0-5V (Les modèles Arduino classiques comme l’UNO, le Nano ou le Mega n’ont pas de capacité de mesure différentielle intégrée. Leur ADC mesure toujours la tension d’un point par rapport à GND).

PS: sinon prendre un meilleur ADC qui sera sur 24 bits par exemple - vous aurez l’équivalent de 12 bits sur votre intervalle ( ADS1256).

Notez aussi que Sur un Arduino Nano, l’ADC peut utiliser la référence par défaut (Vcc/5V), une référence interne de 1,1 V, ou une référence externe connectée à la broche AREF. ça permet aussi de diminuer l’intervalle entre GND et votre borne max

Bonjour,

:+1:

Ou 1 ampli operationnel avec reglage d'un offset et du gain...

oui effectivement, c'est peut être une meilleure idée même

déjà merci pour les réponses rapide !
J'ai une option sans composants externe avec l'utilisation de la référence interne de 1.1V ?
Mon problème est que l'intervalle de mesure est entre 2.5V et 5V, dans l'idéal il faudrait je "j'enlève" 2.5V. Si je peux mesurer de 1.1V à 5V c'est déjà bien dans un premier temps.

Je vais regarder du coté d'un AOP, je n'ai pas une grande maitrise de ces petit composants :slightly_smiling_face: mais internet est mon ami (et ce forum :+1:)

merci

Une tension est une différence de potentiel - donc dans l'absolu si vous aviez une référence à 2.5V et que vous mesuriez la tension entre ces 2.5V et la valeur du capteur, ça vous donnerait cette tension absolue qui varie entre 0 et 2.5V et si vous rentrez ces 2.5V sur un AREF, vous auriez la pleine dynamique des 10 bits...

Mais comme dit plus haut, la Nano ne permet pas de mesurer la tension entre deux points arbitraires, c'est toujours un point comparé avec GND.

Donc c'est pour cela qu'il vous faudra d'autres composants.

ok j'ai compris la subtilité !
Pour le choix de l'AOP, on se fourni chez RS principalement, et quand je vois le choix je suis perdu ! par exemple celui-là :

j'ai vu ce schémas qui à l'air de correspondre à mon besoin (certes 3 amplis mais utilisation facile car la ref est réglable via V2)

Le nombre montages à AOP est illimités.

Par exemple celui là:

En V2, vous entrez votre signal, en V1 vous mettez un potentiométre alimenté entre 0V et +5V pour régler l'offset.

Vous faites en sorte d'adapter les résistances pour ne pas fausser les gains...

Comment traitez vous votre signal 4-20mA pour le transformer en tension (quel schéma?).

Autrement, passer à une carte avec un ATmega2560 et essayer le code de ce site.
L'ATmega2560 est capable de faire des mesures différentielles. Et on peut dans ce cas changer le gain avant l'ADC.

J'ai cherché un peu vite et il est possible qu'il y ait des librairies mieux ficelées.

Il y a aussi ça, mais je n'arrive pas à lire le schéma!

https://seeeddoc.github.io/Grove-Differential_Amplifier_v1.2/

@jef59

EasyEDA peut importer des documents Eagle, c'est le cas içi
je joins le résultat
Schematic_Grove-Differential-Amplifier-v1.2.sch_2024-11-12.pdf (50,3 Ko)
A première vue on retrouve un schéma d'amplificateur d'instrumentation utilisant un INA132 et 3 AOP non référencés sur ce schéma du module Groove

les 2 AOP d'entrée reproduisent cet exemple de la dataSheet du INA132 :

l'AOP ajouté , sur le module Groove, après la sortie de l'INA132 est montré en amplificateur non inverseur

Ce module ne propose que 2 valeurs possibles pour l'amplification (x35 et x1085) :frowning_face:

Concernant le traitement du signal 4-20mA, je mesure la différence de potentiel aux bornes de la résistance en série de l'alimentation (c'est en bas à gauche de mon dessin au post #1)
C'est pour ça que j'ai repéré le montage "amplificateur d'instrumentation" qui ne consomme pas de courant pour réaliser la mesure...

Est-ce que l'AOP cité en lien est bon pour ce montage ?
Merci

Hello,

Il faut que je jette un oeil avec les infos obtenues grâce à @al1fch ...

Là je suis entre 2 corvées, le temps me manque, le coup du gain me laisse interogatif pour l'instant.

l'INA132 me semble adapté à la situation.

merci, je n'attends pas de réponse dans la minutes, je sais bien que chacun est bénévole sur ce forum :wink:
L'AOP que j'ai cité est en boitier DIP, le INA132 en boitier SOIC
J'avoue que je préfère un boitier DIP traversant, que je peux souder tranquille, qu'un boitier SOIC ou je vais clairement flinguer le CI :flushed:

Si tu te fournis chez RS, c'est top, tu as l'embarras du choix.

Dont celui que tu propose en DIP qui peut avoir 1, 2, 3 io 4 AOP par boîtier.

Regarde ce montage

Tu peux faire Vref avec un potentiomètre de faible valeur par rapport à R1 (du 2éme montage).

Tu peux aussi augmenter la dynamique de sortie aux bornes de la résistance mise en sortie de ton géné 4-20mA en augmentant sa valeur, mais jusqu'à où?

Tu te vois réaliser ce genre de montage?
Comment?

Perso j'essaierais (pour faire des tests) sur une breadboard si j'avais à le faire.

J'AI REALISÉ UNE GROSSE BOURDE:

Pour que se soit interessant avec ces montages, il faudrait Vref négatif.

Ou faire en sorte que V2-V1 soit négatif, ce qui n'est pas impossible.

Et dans ce cas, si on calcule avec astuce les gains, on aurait à 950 mBar Uout proche de 5V et à 2000mBar Uout proche de 0V, avec une variation purement linéaire entre les 2.

Ce ne serait pas gênant puisque tu traduis ces valeurs par le code que tu écris à ta convenance.

A voir de + prés.

j'ai du matériel de base au boulot, mise à part la soudure CMS minuscule, je peux réaliser des circuits sur breadboard ou sur plaque à trous.

En jouant sur la résistance en série, je veux effectivement augmenter la tension max, j'ai choisi la résistance à l'origine pour ne pas dépasser les 5V à la pression max (à 20mA: 220Ohm => 4.4v, 240Ohm => 4.8V et 260Ohm => 5.2V)

Je n'ai pas d'alimentation symétrique disponible, si je peux éviter d'avoir à utiliser des tensions négatives cela m'arrangerais :smiley:

Merci :wink:

Juste pour être sûr - vous disposez quand même sans rien faire d’un échantillonnage sur environ 500 points. Êtes vous sûr que ce n’est pas assez pour votre besoin et que retrouver 1000 points serait vraiment significatif ?

Quelle est l’intervalle de pilotage du moteur ?

Bonne relarque

Sinon, astuce:

Ca évite dnavoir une alim négative je pense.

en fait je n'ai pas 500 points, j'ai une plage 4-20mA qui équivaut à 0.88-4.4V une fois relié à la resistance de 220Ohm. Sur ça je n'utilise que de la pression ambiante (environ 980mBar) à 2Bars soit de 2.6V à 4.4V donc 1.8V de plage de mesure utile (environ 370 points et 3mBar par point). Si j'ai moyen d'augmenter cela cela serait plus qu'appréciable :slight_smile:

Pour expliquer le principe de l'essai:
On a un caisson dans lequel on place l'équipement client. On ferme le caisson, on monte en pression avec de l'air comprimé et un réducteur de pression , on tests l'équipement puis on revient à l'ambiante. Assez basique mais il faut jouer en continue sur la molette du réducteur de pression pour ajuster la pression (monté, stabilisation et descente) dans le caisson. D'ou l'idée d'automatiser cela avec un arduino...
Coté code:
L'arduino démarre, il s'assure que le bouton "Start" ne soit pas enfoncé puis demande d'appuyer sur la touche "valider" pour continuer.
Il y a un bouton pour entrer la consigne à atteindre et un bouton pour rentrer la rampe de variation, une fois rentrées on peut lancer la régul.
Dès que le bouton "start" est enfoncé, je boucle en continue (exemple pour la montée en pression):
lecture A0 + conversion en pression -> si pression inférieure on tourne le moteur pour augmenter / si pression supérieur on tourne pour diminuer. Le moteur est accouplé sur la molette du réducteur de pression

j'en suis à l'étape d'affiner la régulation (prendre en compte la rampe demandée) et c'est là que la résolution me bloque.
Un échantillonnage de 3mBar pour une rampe qui peut être de 2mBar/secondes c'est pas idéal !

je vous mets le code que j'ai écris jusqu'à présent (je sais qu'il y a plein d'optimisations possible mais mon niveau en programmation n'en est pas encore là :flushed:):

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include "Adafruit_MPR121.h"

#ifndef _BV
#define _BV(bit) (1 << (bit))
#endif

// déclaration pour le moteur PàP
#include <Stepper.h>
#define STEPS 32
Stepper stepper(STEPS, 9, 11, 10, 12);

//déclaration clavier 12 touches
Adafruit_MPR121 cap = Adafruit_MPR121();
/*
  code binaire des touches
  0 = 1
  1 = 2
  2 = 4
  3 = 8
  4 = 16
  5 = 32
  6 = 64
  7 = 128
  8 = 256
  9 = 512
  10 = 1024
  11 = 2048
  */

//déclaration écran LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);

// variables du programme
uint16_t lasttouched = 0;
uint16_t currtouched = 0;
bool start = false;                    //on a démarré le programme OUI/NON
const int buttonstart = 2;             // pin du bouton Start/Stop
int etatstart = 0;                     //définie l'état initial de lecture du bouton
const int buttonconsigne = 3;          // pin du bouton d'entrée de consigne
int etatconsigne = 0;                  //définie l'état initial de lecture du bouton
const int buttonrampe = 4;             // pin du bouton d'entrée de la rampe
int etatrampe = 0;                     //définie l'état initial de lecture du bouton
const int buttonAU = 5;                // pin du bouton d'arret d'urgence
int etatAU = 0;                        //définie l'état initial de lecture du bouton
const int capteurpression = A0;        // pin du capteur de pression
int dixvaleurpression = 0;             // variable pour la lecture de 10 pression pour faire la moyenne
float valeur_pression = 0;             // valeur de la pression en mbar
float valeur_pression_precedente = 0;  // valeur de la pression en mbar
float vitesse = 0;                     // vitesse de changement de pression (pression-précédente)
int valeur_lueA0 = 0;                  // valeur lue de A0 de 0 à 1023 du capteur
String text_pression = "****";         //texte d'affichage de la pression
int consigne = 0;                      // consigne actuelle validée
int entreeconsigne = 0;                // valeur de consigne entrée au clavier mais non validé
String text_consigne = "****";         //texte d'affichage de la consigne
int rampe = 0;                         // rampe actuelle validée
int entreerampe = 0;                   // valeur de rampe entrée au clavier mais non validé
String text_rampe = "****";            //texte d'affichage de la rampe
int modeFct = 0;                       // mode de fonctionnement:
                                       // 0 = en attente
                                       // 1 = en régulation
                                       // 2 = entrée consigne
                                       // 3 = entrée rampe
                                       // 4 =
int sensregulation = 0;                // 0 = on monte en pression
                                       // 1 = on descend en pression
String ligne1 = "                    ";
String ligne2 = "                    ";
String ligne3 = "                    ";
String ligne4 = "                    ";
String lignevide = "                    ";


void subaffiche() {  //                                                       ==========   void subaffiche() >>>>>>>>>>>
  /*
  Serial.println("--  ==  Mise à jour LCD  ==  --");
  Serial.print("ligne1[");
  Serial.print(ligne1);
  Serial.println("]");
  Serial.print("ligne2[");
  Serial.print(ligne2);
  Serial.println("]");
  Serial.print("ligne3[");
  Serial.print(ligne3);
  Serial.println("]");
  Serial.print("ligne4[");
  Serial.print(ligne4);
  Serial.println("]");
  */
  lcd.setCursor(0, 0);
  lcd.print(lignevide);
  lcd.setCursor(0, 0);
  lcd.print(ligne1);
  lcd.setCursor(0, 1);
  lcd.print(lignevide);
  lcd.setCursor(0, 1);
  lcd.print(ligne2);
  lcd.setCursor(0, 2);
  lcd.print(lignevide);
  lcd.setCursor(0, 2);
  lcd.print(ligne3);
  lcd.setCursor(0, 3);
  lcd.print(lignevide);
  lcd.setCursor(0, 3);
  lcd.print(ligne4);

}  //                                                                         <<<<<<<<<   fin void subaffiche() ==========

void setup() {  //                                                       ==========   void setup() >>>>>>>>>>>

  //initialise la liaison série
  Serial.begin(9600);

  while (!Serial) {  // needed to keep leonardo/micro from starting too fast!
    delay(10);
  }

  // initialise le clavier address i2c 0x5A
  if (!cap.begin(0x5A)) {
    Serial.println("MPR121 non trouvé, vérifier cables");
    while (1)
      ;
  }
  Serial.println("MPR121 trouvé!");

  // initialise l'ecran adresse i2c 0x27
  lcd.init();
  lcd.init();
  lcd.backlight();
  ligne1 = "Coffret surpression";
  ligne2 = "Bouton Start sur OFF";
  ligne3 = "Puis appuyer sur";
  ligne4 = "la touche valider";
  subaffiche();
  // définie la vitesse du moteur
  stepper.setSpeed(300);


  /*
  lcd.setCursor(0, 0);
  lcd.print("Coffret surpression");
  lcd.setCursor(0, 1);
  lcd.print("Bouton Start sur OFF");
  lcd.setCursor(0, 2);
  lcd.print("Puis appuyer sur");
  lcd.setCursor(0, 3);
  lcd.print("la touche OK");
*/
  Serial.println("Init LCD fait...");
  pinMode(buttonstart, INPUT_PULLUP);
  pinMode(buttonconsigne, INPUT_PULLUP);
  pinMode(buttonrampe, INPUT_PULLUP);
  pinMode(buttonAU, INPUT_PULLUP);
  Serial.println("Entrées configurées");
  attente_ok();
}  //                                                                         <<<<<<<<<   fin void setup() ==========

void attente_ok() {  //                                                       ==========   void attente_ok() >>>>>>>>>>>
  //boucle qui attend d'avoir le bouton start relaché et que l'on appuie sur la touche OK
  etatstart = digitalRead(buttonstart);
  Serial.print("Etat entrée start : ");
  Serial.println(etatstart);
  Serial.println("");
  while ((etatstart == LOW)) {  // tant que le bouton est enfoncé on boucle
    etatstart = digitalRead(buttonstart);
    Serial.print("Etat entrée start : ");
    Serial.print(etatstart);
    Serial.println(" -> Attente START = OFF");
    delay(200);
  }
  ligne2 = "Bouton Start OK     ";
  ligne3 = "-> Appuyer sur      ";
  ligne4 = "  la touche valider ";
  subaffiche();
  Serial.println("Bouton start OK, attente touche valider");
  while ((start == false)) {  // tant que la touche valider est pas enfoncée on boucle
    // récupère la touche active
    currtouched = cap.touched();
    if (currtouched == 256) {
      Serial.println("Touche valider appuyée");
      start = true;
    }
  }
  ligne2 = "   Initialisation   ";
  ligne3 = "      terminee      ";
  ligne4 = "     ..........     ";
  subaffiche();
  Serial.println("Init OK...");
  delay(3000);
  ligne2 = "Consigne = ****     ";
  ligne3 = "Rampe = ****        ";
  ligne4 = "Pression = ****     ";
  subaffiche();
  Serial.println("Prêt...");

}  //                                                                         <<<<<<<<<   fin void attente_ok() ==========


void subregulation() {  //                                                       ==========   void subregulation() >>>>>>>>>>>

  //dans la boucle on vérifie si le bouton est toujours sur LOW pour continuer
  //                          si le bouton d'AU est pas enfoncé
  //                          on a bien une valeur de pression lue
  //int sensregulation = 0;          // 0 = on monte en pression
  //                                 // 1 = on descend en pression  Serial.println("boucle de régul");
  if (sensregulation == 1) {
    ligne1 = "Regul. en cours:  -";
    Serial.println("Régulation en baisse");
    //on baisse
  } else {
    ligne1 = "Regul. en cours:  +";
    Serial.println("Régulation en hausse");
    //on monte
  }

  while ((etatstart == LOW)) {  // tant que le bouton est enfoncé on boucle
    etatstart = digitalRead(buttonstart);
    sublecturepression();  //appel la sub pour lire la pression du capteur
    //calculs : durée de variation = (consigne - valeur_pression)/rampe

    if (valeur_pression < consigne) {  //augmente la pression tant que pas atteind la consigne
      //pression lue inférieure à la consigne

      // on vérifie si la pression augmente ou pas
      if (valeur_pression > valeur_pression_precedente) {  // la pression augmente bien

        //calcul l'écart par rapport à la consigne pour voir la vitesse de progression
        vitesse = valeur_pression - valeur_pression_precedente;
        /*
        il faut regarder la vitesse de variation par rapport à l'objectif à atteindre et la rampe définie
        si vitesse comprise entre rampe*0.9<V<rampe*1.1 et valeur_pression est éloignée de plus de 5*rampe de la consigne, alors on continue de tourner + 0.5 tour
        si vitesse < rampe*0.9 et valeur_pression est éloignée de plus de 5*rampe de la consigne, alors on fait +1 tour
        si vitesse < rampe*0.9 et valeur_pression est éloignée de moins de 5*rampe de la consigne, alors on arrete de tourner
        si vitesse > rampe*1.1 alors on détourne pour ralentir la montée - 0.5 tour
        */
        Serial.print("vitesse = ");
        Serial.print(vitesse);
        Serial.print(" | rampe * 1.2 = ");
        Serial.print(String(rampe * 1.2));
        Serial.print(" | rampe * 0.8 = ");
        Serial.println(String(rampe * 0.8));

        // on regarde la vitesse de variation pour voir si on tourne encore ou pas
        if (vitesse > (rampe * 1.2)) {
          Serial.println("la vitesse est suppérieure à la rampe * 1.2, pas de rotation moteur");
          //la vitesse est plus élevée que la rampe on arrete de tourner pour ce bouclage
        }
        if ((vitesse > (rampe * 0.8)) && (vitesse < (rampe * 1.2))) {
          //la vitesse est conforme à la rampe on poursuit comme ça
          //fait tourner le moteur en sens horaire
          Serial.println("la vitesse est conforme à la rampe * 1.2, rotation moteur normale");
          stepper.step(-250);
        }
        if (vitesse < (rampe * 0.8)) {
          //la vitesse est plus basse que la rampe on tourne plus
          //fait tourner le moteur en sens horaire
          Serial.println("la vitesse est inferieure à la rampe * 1.2, rotation moteur accélérée");
          stepper.step(-400);
        }

      } else {

        //la pression n'augmente pas on tourne +
        //fait tourner le moteur en sens horaire
        stepper.step(-250);
      }
    }

    if (valeur_pression > consigne) {  //diminue la pression
      //pression lue inférieure à la consigne
      // on vérifie si la pression diminue ou pas
      if (valeur_pression < valeur_pression_precedente) {  //ça diminue on regarde la vitesse pour pas diminuer trop vite
        //calcul l'écart par rapport à la consigne pour voir la vitesse de progression
        vitesse = abs(valeur_pression - valeur_pression_precedente);
        /*
          il faut regarder la vitesse de variation par rapport à l'objectif à atteindre et la rampe définie
          si vitesse comprise entre rampe*0.9<V<rampe*1.1 et valeur_pression est éloignée de plus de 5*rampe de la consigne, alors on continue de tourner + 0.5 tour
          si vitesse < rampe*0.9 et valeur_pression est éloignée de plus de 5*rampe de la consigne, alors on fait +1 tour
          si vitesse < rampe*0.9 et valeur_pression est éloignée de moins de 5*rampe de la consigne, alors on arrete de tourner
          si vitesse > rampe*1.1 alors on détourne pour ralentir la montée - 0.5 tour
          */
        Serial.print("vitesse = ");
        Serial.print(vitesse);
        Serial.print(" | rampe * 1.2 = ");
        Serial.print(String(rampe * 1.2));
        Serial.print(" | rampe * 0.8 = ");
        Serial.println(String(rampe * 0.8));

        // on regarde la vitesse de variation pour voir si on tourne encore ou pas
        if (vitesse > (rampe * 1.2)) {
          Serial.println("la vitesse est suppérieure à la rampe * 1.2, pas de rotation moteur");
          //la vitesse est plus élevée que la rampe on arrete de tourner pour ce bouclage
        }
        if ((vitesse > (rampe * 0.8)) && (vitesse < (rampe * 1.2))) {
          //la vitesse est conforme à la rampe on poursuit comme ça
          //fait tourner le moteur en sens horaire
          Serial.println("la vitesse est conforme à la rampe * 1.2, rotation moteur normale");
          stepper.step(250);
        }
        if (vitesse < (rampe * 0.8)) {
          //la vitesse est plus basse que la rampe on tourne plus
          //fait tourner le moteur en sens horaire
          Serial.println("la vitesse est inferieure à la rampe * 1.2, rotation moteur accélérée");
          stepper.step(400);
        }
      }
      // on regarde la vitesse de variation pour voir si on tourne encore ou pas
      // on tourne le moteur en +
      if (valeur_pression > valeur_pression_precedente) {  //ça diminue pas ou ça augmente

        //fait tourner le moteur en sens horaire + pour accélérer
        stepper.step(400);
      }
    }

    //
    //Serial.println("bouton START enfoncé");


    delay(500);
  }

  //quite la sub de régul
  ligne1 = "Coffret surpression";
  subaffiche();
  modeFct = 0;
  Serial.println("bouton START relaché boucle terminée");

}  //                                                                          <<<<<<<<<   fin void subregulation() ==========

void sublecturepression() {  //                                                       ==========   void sublecturepression() >>>>>>>>>>>

  //sauve l'ncienne valeur
  valeur_pression_precedente = valeur_pression;
  // lit 10 mesures pour faire la moyenne et lisser la mesure
  dixvaleurpression = 0;
  for (int i = 0; i <= 9; i++) {
    int sensorValue = analogRead(A0);
    dixvaleurpression = dixvaleurpression + sensorValue;
    delay(10);
  }
  int sensorValue = (dixvaleurpression / 10);
  //calcul la pression 182=0mbars,1024=2000mbars
  valeur_pression = ((sensorValue - 182) * (2000.0 / 719));
  //Serial.print("sensorValue = ");
  //Serial.print(sensorValue);
  //Serial.print(" | valeur_pression = ");
  //Serial.println(valeur_pression);
  //affiche la pression
  text_pression = String(valeur_pression);
  ligne4 = String("Pression = " + text_pression);
  subaffiche();

}  //                                                                          <<<<<<<<<   fin void sublecturepression() ==========


void subconsigne() {  //                                                       ==========   void subconsigne() >>>>>>>>>>>
  ligne2 = "Entrez la consigne";
  ligne3 = "C = ";
  ligne4 = "puis touche valider";
  subaffiche();
  entreeconsigne = 0;
  while (modeFct == 2) {  //tant qu'on est en mode consigne, on reboucle
    //a chaque touche on fait  valeur = (10 * valeur) + touche
    currtouched = cap.touched();
    //Serial.println(currtouched);

    for (uint8_t i = 0; i < 12; i++) {
      // it if *is* touched and *wasnt* touched before, alert!
      if ((currtouched & _BV(i)) && !(lasttouched & _BV(i))) {
        //Serial.print(i);
        //Serial.println(" touched");
        //ici on a la touche "i" d'éffleurée on va faire une selection à base de if:
        if (i == 0) {
          //"touche annulée", on ne valide pas la consigne et on sort du mode d'entrée consigne
          Serial.println("touche annuler");
          modeFct = 0;
        }
        if (i == 1) {
          //touche "1"
          entreeconsigne = (entreeconsigne * 10) + 1;
          Serial.print("touche 1, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 2) {
          //touche "4"
          entreeconsigne = (entreeconsigne * 10) + 4;
          Serial.print("touche 4, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 3) {
          //touche "7"
          entreeconsigne = (entreeconsigne * 10) + 7;
          Serial.print("touche 7, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 4) {
          //touche "0"
          entreeconsigne = (entreeconsigne * 10);
          Serial.print("touche 4, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 5) {
          //touche "2"
          entreeconsigne = (entreeconsigne * 10) + 2;
          Serial.print("touche 2, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 6) {
          //touche "5"
          entreeconsigne = (entreeconsigne * 10) + 5;
          Serial.print("touche 5, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 7) {
          //touche "8"
          entreeconsigne = (entreeconsigne * 10) + 8;
          Serial.print("touche 8, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 8) {
          //touche "valider", on valide la consigne et on sort du mode d'entrée consigne
          Serial.print("touche valider, entreeconsigne=");
          Serial.println(entreeconsigne);
          consigne = entreeconsigne;
          Serial.print("Valeur de la consigne validée =");
          Serial.println(consigne);
          text_consigne = String(consigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
          modeFct = 0;
        }
        if (i == 9) {
          //touche "3"
          entreeconsigne = (entreeconsigne * 10) + 3;
          Serial.print("touche 3, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 10) {
          //touche "6"
          entreeconsigne = (entreeconsigne * 10) + 6;
          Serial.print("touche 6, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
        if (i == 11) {
          //touche "9"
          entreeconsigne = (entreeconsigne * 10) + 9;
          Serial.print("touche 9, entreeconsigne=");
          Serial.println(entreeconsigne);
          text_consigne = String(entreeconsigne);
          ligne3 = String("Consigne = " + text_consigne);
          subaffiche();
        }
      }
    }
    // reset du status
    lasttouched = currtouched;
  }
  Serial.print("Sortie boucle consigne, consigne = ");
  Serial.println(consigne);
  text_consigne = String(consigne);
  ligne2 = String("Consigne = " + text_consigne + " mB");
  ligne3 = String("Rampe = " + text_rampe + " mB/s");
  ligne4 = "Pression = ******";
  subaffiche();
}  //                                                                         <<<<<<<<<   fin void subconsigne() ==========

void subrampe() {  //                                                         ==========   void subrampe() >>>>>>>>>>>

  ligne2 = "Entrez la rampe";
  ligne3 = "R = ";
  ligne4 = "OK pour valider";
  subaffiche();
  entreerampe = 0;
  while (modeFct == 3) {  //tant qu'on est en mode consigne, on reboucle
    //a chaque touche on fait  valeur = (10 * valeur) + touche
    currtouched = cap.touched();
    //Serial.println(currtouched);

    for (uint8_t i = 0; i < 12; i++) {
      // it if *is* touched and *wasnt* touched before, alert!
      if ((currtouched & _BV(i)) && !(lasttouched & _BV(i))) {
        //Serial.print(i);
        //Serial.println(" touched");
        //ici on a la touche "i" d'éffleurée on va faire une selection à base de if:
        if (i == 0) {
          //"touche annulée", on ne valide pas la consigne et on sort du mode d'entrée consigne
          Serial.println("touche annuler");
          modeFct = 0;
        }
        if (i == 1) {
          //touche "1"
          entreerampe = (entreerampe * 10) + 1;
          Serial.print("touche 1, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 2) {
          //touche "4"
          entreerampe = (entreerampe * 10) + 4;
          Serial.print("touche 4, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 3) {
          //touche "7"
          entreerampe = (entreerampe * 10) + 7;
          Serial.print("touche 7, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 4) {
          //touche "0"
          entreerampe = (entreerampe * 10);
          Serial.print("touche 0, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 5) {
          //touche "2"
          entreerampe = (entreerampe * 10) + 2;
          Serial.print("touche 2, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 6) {
          //touche "5"
          entreerampe = (entreerampe * 10) + 5;
          Serial.print("touche 5, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 7) {
          //touche "8"
          entreerampe = (entreerampe * 10) + 8;
          Serial.print("touche 8, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 8) {
          //touche "valider", on valide la consigne et on sort du mode d'entrée consigne
          Serial.print("touche valider, entreerampe=");
          Serial.println(entreerampe);
          rampe = entreerampe;
          Serial.print("Valeur de la rampe=");
          Serial.println(rampe);
          text_rampe = String(rampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
          modeFct = 0;
        }
        if (i == 9) {
          //touche "3"
          entreerampe = (entreerampe * 10) + 3;
          Serial.print("touche 3, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 10) {
          //touche "6"
          entreerampe = (entreerampe * 10) + 6;
          Serial.print("touche 6, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
        if (i == 11) {
          //touche "9"
          entreerampe = (entreerampe * 10) + 9;
          Serial.print("touche 9, entreerampe=");
          Serial.println(entreerampe);
          text_rampe = String(entreerampe);
          ligne3 = String("Rampe = " + text_rampe);
          subaffiche();
        }
      }
    }
    // reset du status
    lasttouched = currtouched;
  }
  //on a fini la SUB -> remet l'affichage
  Serial.print("Sortie boucle rampe, rampe = ");
  Serial.println(rampe);
  text_rampe = String(rampe);
  ligne2 = String("Consigne = " + text_consigne + " mB");
  ligne3 = String("Rampe = " + text_rampe + " mB/s");
  ligne4 = "Pression = ****     ";
  subaffiche();

}  //                                                                         <<<<<<<<<   fin void subrampe() ==========



void loop() {  //                                                             ==========   void loop() >>>>>>>>>>>

  sublecturepression();  //appel la sub pour lire la pression du capteur
  //Serial.println("loop...");

  //appel de la sub d'entrée de la consigne à atteindre
  etatconsigne = digitalRead(buttonconsigne);
  if (etatconsigne == LOW) {
    Serial.println("mode d'entrée de la valeur de consigne");
    modeFct = 2;
    Serial.println("Boucle d'entrée...");
    subconsigne();
    Serial.println("Retour mode attente...");
  }

  //appel de la sub d'entrée de la rampe de variation
  etatrampe = digitalRead(buttonrampe);
  if (etatrampe == LOW) {
    Serial.println("mode d'entrée de la valeur de rampe");
    modeFct = 3;
    Serial.println("Boucle d'entrée...");
    subrampe();
    Serial.println("Retour mode attente...");
  }

  etatstart = digitalRead(buttonstart);
  if (etatstart == LOW) {
    Serial.println("mode de régulation");
    // vérifie qu'on a une consigne diff de zéro
    //vérifie qu'on a une rampe diff de zéro
    if (rampe == 0) {
      Serial.println("Pas de start si la rampe est à 0");
      return;
    }
    if (consigne == 0) {
      Serial.println("Pas de start si la consigne est à 0");
      return;
    }
    modeFct = 1;
    //détermine si on monte ou on descend en pression
    sensregulation = 1;  // on descend en pression
    if (valeur_pression < consigne) {
      sensregulation = 0;  // on monte en pression
    }
    subregulation();
    Serial.println("Retour mode attente...");
  }

  delay(50);
}  //                                                                            <<<<<<<<<   fin void loop() ==========