Pages: [1]   Go Down
Author Topic: Fonction attachInterrupt() et fréquence  (Read 2038 times)
0 Members and 1 Guest are viewing this topic.
Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonsoir,

Je suis sur un projet de capteur sur un véhicule, je mesure la pression d'huile que je compare aux t/min et si cette valeur comparée est correcte, pas de soucis, autrement une alarme se met en fonction.

Je dois récupérer une fréquence avec la fonction attachInterrupt(), je pensais trouver la fréquence maxi que je pouvais lire, mais dans les références il n'en est pas fait mention.

Quelqu'un saurait-il me donner cette valeur ?
« Last Edit: February 01, 2009, 02:15:45 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Sophia-Antipolis (06)
Offline Offline
God Member
*****
Karma: 4
Posts: 618
Rejoignez le club !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

"attachInterrupt" sert à gérer les 2 pattes d'interruption externe.

tout d'abord, il faut savoir qu'il faut rester le moins longtemps possible dans une interruption, au cas où de nouvelles interruptions arriveraient. donc il vaut mieux juste changer une valeur (incrémenter un compteur par exemple) pour ensuite traiter cette valeur quand il y a moins de stress (dans le "loop" par exemple).

sur une autre carte que l'Arduino mais avec un microcontrôleur identique (ATmega8) et un quartz de 8 MHz, je faisais l'acquisition de 20000 impulsions sans problème. Mais tout dépend de ce que tu mets dans ta fonction, on doit pouvoir aller beaucoup plus haut. Je vérifierai le chiffre exact.

Mais je n'ai pas compris ce que tu voulais faire et en quoi l'interruption externe allait t'aider.
Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

J'amène quelques précisions :

Sur un véhicule à moteur thermique, l'alimentation électrique est assurée par l'alternateur, le courant en sortie de collecteur est redressé par une série de diodes et la batterie en faisant "tampon"permet de stabiliser quelques peu ce courant, mais seulement dans une certaine fourchette.
Au ralenti il peut y avoir 12,5 volts et moteur tournant à 3000-4000 tour/min on peut avoir jusqu'à 14,5 volts, ces valeurs varient lors de l'allumage ou l'extinction de consommateurs (phares, ventilation...).

Pour l'acquisition de données sur les capteurs de la voiture je passe par une isolation galvanique en utilisant des optocoupleurs, ces derniers ne faisant passer que des informations lolgiques (1/0).
le problème est que certaines de mes jauges me transmettent des données en faisant varier une tension que je n'arrive pas à faire parvenir tel quelles par le biais de mes optos. Pour pallier à cet inconvénient j'utilise un circuit VCO qui converti les tensions en fréquences que je peux ensuite lire sur les pins 2 et 3.
Jusque là ça va encore, mais voici le fond du problème qui me fait poser ces questions :

Comme je l'explique plus haut le circuit électrique dans un véhicule à moteur thermique est soumis à de fortes variations de tension. Les tensions renvoyées par les capteurs du véhicule subissent les mêmes variations et deviennent de ce fait "imprécis" (15 % de variation des mesures).
Pour pallier ce contrer ces variations, il faut que j'alimente ces capteurs avec une tension qui ne subit aucune variations (même en branchant des consommateurs), je pensait utiliser un autre circuit VCO afin de lire quel est la tension (par le biais de la fréquence générée) sur le véhicule et la corriger en commandant avec une PWM un Mosfet qui hachera le courant afin d'avoir une courant à la tension qui me convient.

Par contre d'après ce que tu me dis la fonction attachInterrupt() prend énormément de  ressource CPU ?

Est-ce possible de "daemoniser" cette fonction ?

J'espère ne pas avoir été trop long dans mon explication...  smiley-wink
« Last Edit: February 02, 2009, 02:52:01 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Je viens de relire les références et effectivement, si l'on ne veut pas rater une impulsions il faut que le µc soit dédié uniquement à cette fonction...
« Last Edit: February 02, 2009, 02:52:24 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Sophia-Antipolis (06)
Offline Offline
God Member
*****
Karma: 4
Posts: 618
Rejoignez le club !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

non non pas du tout, ce n'est pas un problème de ressources CPU, ça ne prend quasiment rien d'entrer en interruption (6 cycles d'horloge, et l'Arduino fait 16 millions de cycles par seconde) et encore moins d'en sortir (4 cycles).

ce qui se passe, c'est que tant que tu es dans la fonction que tu as "attachée", le CPU ne fait rien d'autre, donc il faut vite en sortir.

une solution est d'en faire le moins possible dans l'interruption.

Code:
int count = 0;
int frequence = 0;

void setup()
{
  attachInterrupt(0, interrupt, RISING);
}

void loop()
{
  // mesurer la fréquence comme le nombre de fronts montants en 1 s.
  frequence = count;
  count = 0;
  // traiter la fréquence
  ...
 delay(1000);  // attendre une seconde pour avoir la fréquence en Hz
}

void interrupt()
{
  count++;
}

mais si c'est pour mesurer une fréquence, tu devrais plutôt regarder du côté des timers en mode "compteur" sur une patte externe.
Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
mais si c'est pour mesurer une fréquence, tu devrais plutôt regarder du côté des timers en mode "compteur" sur une patte externe.

C'est à dire ?


Pour l'instant j'ai un code comme ça :
Code:
unsigned long sendTime=0;
 volatile byte ppmcount;

 unsigned long ppm;

 unsigned long timeold;
 unsigned long timeold2;
 int pwmVolt = 255;
 int pinVolt = 9;
 
 void setup()
 {
   Serial.begin(9600);
   attachInterrupt(0, ppm_fun, FALLING);

   ppmcount = 0;
   ppm = 0;    //Pulse per minute
   timeold = 0;
 }

 void loop()
 {
   if (ppmcount >= 250) {
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     ppm = 30*1000/(millis() - timeold)*ppmcount;
    
     timeold = millis();
     ppmcount = 0;
    
    
   }

//********** ici c'est pour corriger la valeur de la tension*********

 if (ppm >=10251){  
  pwmVolt--;
}

if (ppm <=10249){
  pwmVolt++;
}

  analogWrite(pinVolt,pwmVolt)

 //************  jusque là..... mais c'est qu'une ébauche  ;) *********
  
   sendTime=millis()-timeold2;
   if (sendTime >=1000){
     Serial.print(ppm,DEC);
     Serial.print("   ");
     Serial.println(pwmVolt,DEC);
    
   timeold2 = millis();}
 }

 void ppm_fun()
 {
   ppmcount++;
   //Each pulse, this interrupt function is run twice
 }


« Last Edit: February 02, 2009, 04:23:19 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ici une alimentation régulée par PWM avec utilisant un AVR.
Et le code utilisé....

C'est un peu tard, je regarderai ça demain  smiley
« Last Edit: February 02, 2009, 07:04:24 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Avec ce code je mesure la tension en sortie PWM pin 9,
la tension est stable à environ 1-2/10ème de volt (je peux la régler en changeant la variable "freq") :

Code:

volatile byte ppmcount;
unsigned long sendTime=0;
unsigned long timeold;
unsigned long timeold2;
unsigned int diffPpm;
long ppm;
int pwmVolt = 254;
int pinVolt = 9;

void setup()
{
  TCCR1B = 0x09;

  Serial.begin(9600);
  attachInterrupt(0, ppm_fun, FALLING);
  pinMode(pinVolt,OUTPUT);
  ppmcount = 0;
  ppm = 0;    //Pulse per minute
  timeold = 0;
}

void loop()
{

  sendTime=millis()-timeold2;

  if (ppmcount >= 120) {
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update
    ppm = 1000/(millis() - timeold)*ppmcount;

    timeold = millis();
    ppmcount = 0;


  }


  long freq = 900000;
  freq/=35;

  if(ppm>=freq+1){

    diffPpm = ppm-freq;

    pwmVolt=0+255*(freq+1)/diffPpm;



    
    if( pwmVolt >255){
      pwmVolt= 255;
    }
    analogWrite(pinVolt,pwmVolt);


  }

  else if (ppm<=freq){

    diffPpm = freq-ppm;

    pwmVolt = 255-255*freq/diffPpm;


    if( pwmVolt >255){
      pwmVolt= 255;
    }
  
    analogWrite(pinVolt,pwmVolt);

  }
  else {
    analogWrite(pinVolt,pwmVolt);
  }




  if (sendTime >=1000){
    Serial.print(ppm,DEC);
    Serial.print("   ");
    Serial.println(pwmVolt,DEC);
    timeold2 = millis();
  }
}

void ppm_fun()
{
  ppmcount++;
  //Each pulse, this interrupt function is run twice
}


Je cherche à stabiliser ça encore plus, dans les 2-3/100ème... si quelqu'un à une piste a m'indiquer  smiley-wink
« Last Edit: February 04, 2009, 04:40:58 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Petit essai pour réguler une tension 12 volt avec un tansistor commandé en PWM... ça fonctionne smiley-grin, mais la stabilité est de 2-4/10ème de volt, je cherche toujours à mieux stabiliser cette tension.  
« Last Edit: February 04, 2009, 08:33:24 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Maintenant avec ce code je commande un transistor Tip127 et j'ai une "précisions" (c'est relatif... :smiley) de 0,5 volts en étant programmé pour réguler une tension de 8 volts :

Code:
volatile int ppm_count;
unsigned long send_Time=0;
unsigned long send_Freq=0;
unsigned long timeold_Time;
unsigned long timeold_Freq;
                               //unsigned long diff_Ppm;
unsigned long ppm;                          //Pulse per minute
int pwm_Volt;
int pinVolt = 9;
int val;
void setup()
{
  TCCR1B = 0x09;
  Serial.begin(9600);
  attachInterrupt(0, ppm_fun, FALLING);
  pinMode(pinVolt,OUTPUT);
}
void loop()
{
  if (ppm_count >= 145) {
    ppm = 540/(millis() - timeold_Freq)*ppm_count;
    timeold_Freq = millis();
    ppm_count = 0;
    val=1;
  }
  long freq = 80000;                 //tension x 10'000
                        // freq/=35;
  if (val==1){
    if(ppm>=freq){
                       // diff_Ppm = freq-ppm;
                       //pwm_Volt=255-255*diff_Ppm/freq;
      pwm_Volt--;    
    }
    if (ppm<=freq){
                      //diff_Ppm = freq-ppm;
                      // pwm_Volt = 0+255*diff_Ppm/freq;
      pwm_Volt++;
    }
    if( pwm_Volt >255){
      pwm_Volt= 255;
    }
    if( pwm_Volt < 0){
      pwm_Volt= 0;
    }
    val=0;
  }
  analogWrite(pinVolt,pwm_Volt);
  send_Time=millis()-timeold_Time;
  if (send_Time >=1000){
    Serial.print(" ppm : ");
    Serial.print(ppm,DEC);
    Serial.print("   ");
    Serial.print("  ppm_count : ");
    Serial.print(ppm_count,DEC);
    Serial.print("   ");
    Serial.print("  pwm : ");
    Serial.println(pwm_Volt,DEC);
    timeold_Time = millis();
  }
}
void ppm_fun()
{
  ppm_count++;
  //Each pulse, this interrupt function is run twice
}


Je cherche toujours un moyen d'affiner cette régulation.
« Last Edit: February 05, 2009, 08:28:10 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Dans le Playground j'ai trouvé ça :

Regulated Positive Voltage Booster


Pour continuer le sujet sur une alimentation dont la tension serait pilotée  :

Tension pilotée et stable
« Last Edit: February 07, 2009, 12:06:39 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3231
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pour en revenir au sujet, j'ai lu sur une page du net que quelqu'un se servait de cette fonction pour contrôler des fréquences et qu'il avait réussi à contrôler un quartz d'horloge à 32,768 kHz.
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Pages: [1]   Go Up
Jump to: