Je me suis équipé d'un débitmètre et la documentation associée propose le programme suivant :
// reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com
// Code adapted by Charles Gantt from PC Fan RPM code written by Crenn @thebestcasescenario.com
// http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;
int hallsensor = 2; //The pin location of the sensor
void rpm () //This is the function that the interupt calls
{
NbTopsFan++; //This function measures the rising and falling edge of the
hall effect sensors signal
}
// The setup() method runs once, when the sketch starts
void setup() //
{
pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
Serial.begin(9600); //This is the setup function where the serial port is
initialised,
attachInterrupt(0, rpm, RISING); //and the interrupt is attached
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop ()
{
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
sei(); //Enables interrupts
delay (1000); //Wait 1 second
cli(); //Disable interrupts
Calc = (NbTopsFan * 60 / 7.5); //(Pulse frequency x 60) / 7.5Q, = flow rate
in L/hour
Serial.print (Calc, DEC); //Prints the number calculated above
Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a new line
}
J'aimerai le comprendre pour ensuite, sans doute, le modifier et l'adapter à mes besoins. J'ai un peu de mal à le comprendre, il est question d'interruptions mais j'ai cherché des explications et je ne vois pas trop en quoi cela est utilisé dans le programme, ou plus exactement quel est l'intérêt de l'interruption dans le cas de ce programme.
Pourriez-vous m'aider à le comprendre ?
Merci
Oui cette technique efficace est utilsée dans le programme montré au dessus.
A chaque front montant (RISING) du signal issu du capteur la fonction rpm() est exécutée automatiquement
C'est la fonction attachinterrupt() qui installe ce lien de cause à effet.
Le programme décrit dans la boucle loop() est donc interrompu au moment opportun, pour exécuter rpm(), et reprend ensuite là ou il avait été interrompu.
En procédant de la sorte on évite de mobiliser le microcontrolleur à scruter en continu l'état du capteur jusqu'à ce que le front montant arrive.
Pour être un peu plus précis le programme dans la loop() active les interruption puis attend une seconde sans rien faire (le delay(1000)).
Pendant cette seconde des fronts montants en provenance du capteur arrivent et viennent interrompre cette attente et la fonction rpm() est appellée et compte le nombre de fronts pendant cette seconde donc; une fois la seconde terminée le programme désactivé les interruptions, le débitmètre ne déclenche donc plus le comptage et on fait le calcul du débit en fonction des spec du capteur (NbTopsFan * 60 / 7.5) le *60 c’est pour avoir le nombre de ticks en 1 minute (puisque vous avez mesuré sur 1 seconde) et la division par 7.5 vient du design du capteur
Oui, l'interruption prend la main. Le 'blocage' n'existe pas a face à une interruption.
Pour 'protéger' une section de code des interruptions il faudrait explicitement désactiver celles -çi
imaginez être en train de cuisiner et découper des légumes, vous recevez un coup de fil - c'est votre interruption - vous posez le couteau, prenez le téléphone, répondez et discutez, puis vous raccrochez et reprenez votre découpe. c'est un peu la même chose en informatique avec les interruptions.
Le programme principal est effectivement "bloqué" dans la boucle d'attente active de la fonction delay() mais le principe des interruptions, comme le nom l'indique, c'est d'interrompre quelque chose momentanément pour aller faire quelque chose d'autre puis revenir là où il était.
Les commandes sei() et cli() activent et désactivent les interruptions et vous pouvez voir qu'elles sont "stratégiquement" placées autour du delay(1000).
En pratique cependant pour le premier tour de loop() les interruptions auront été activées dans le setup() dès l'appel de attachInterrupt(0, rpm, RISING);et donc vous allez avoir un peu plus d'une seconde d'interruption pour le premier tour. ici comme vous ne faites rien d'autre ça ne prête pas à conséquence, mais s'il y avait plus de choses dans le setup, des delay() etc alors votre première mesure serait fausse.
Cet appel serait mieux écrit sous la forme attachInterrupt(digitalPinToInterrupt(2), rpm, RISING); --> cf la documentation