Fréquence d'un signal PWM

Bonjour,

Je travail un peu avec les signaux PWM et j'aimerais pouvoir mesurer la fréquence d'un signal PWM mais je ne sais pas torp comment faire. J'utilise les interrupt pour afficher la valeur de mon PWM avec des fronts RISING et FALLING

void rising() {
  attachInterrupt(PWM_PIN_SERVO, falling, FALLING);
  prev_time = micros();
}
 
void falling() {
  attachInterrupt(PWM_PIN_SERVO, rising, RISING);
  pwm_value = micros()-prev_time;
  SerialUSB.println(pwm_value);
}

Ca fonctionne super j'ai bien la valeur de mon PWM mais comment calculer la fréquence ?

Option 1 :
si vous êtes capables de calculer la durée entre un front montant et un front descendant, vous savez calculer la demi periode (à 50% de duty cycle - sinon tenir compte du rapport), donc la période et la fréquence étant l'inverse de la période, ça ne devrait pas être trop compliqué...

  • pas la peine d'attacher les interruptions dans les interruptions, faites ça dans le setup une fois pour toutes
  • les variables globales utilisées dans les interruptions doivent être déclarées volatile
  • il faudra une section critique dans la loop pour calculer la fréquence

Option 2 : vous regardez la doc et la fréquence du PWM est connue :slight_smile:

par défaut, pour un Arduino à base de 328P :

  • PWM de 976,56 Hz sur les broches D5 ou D6
  • PWM de 490,20 Hz sur les broches D3, D9, D10, ou D11

Et pour un Arduino Mega :

  • PWM de 976,56 Hz sur les broches D4 ou D13
  • PWM de 490,20 Hz sur les broches D2, D3, D5, D6, D7, D8, D9, D10, D11, ou D12
  • PWM de 490,20 Hz sur les broches D44, D45, ou D46

à lire :

Si tu es capable de mesurer le temps de "1" et le temps de "0" il suffit d'additionner ces deux temps et tu as la période de la PWM.

Sachant que pour un signal répétitif comme la PWM, la fréquence est l'inverse de la période.

Note :
Si c'est juste pour connaitre la valeur sans la traiter ultérieurement dans le programme, le plus simple est de faire la mesure avec l'analyseur logique, clone de Saleae, à 8€ sur Ebay ou Ali.

hello
je m'étais amusé à faire ceci: generateur de signaux sur D8 de UNO

//pour UNO
//mesure la période d'un signal sur l'entrée D8
//143KHz maxi. periode mesurée = 7µS
//144.3 => periode mesurée =6.93µS d'ou un pulse => 1/2 periode =>6.93/2=3.46µ
//146.5 => periode mesuree = 6.81µS d'ou pulse=3.405µS

#define debut_evenement 8//entree pour debut evenement à chronometrer
//#define   fin_evenement 6//entree pour fin evenement à chronometrer
//#define evenement 8//entree pour evenement à chronometrer

byte flag_impression = true; //pour un seul serial print
volatile unsigned long nombre_cycles      = 0;//avec le prescaler du timer1 à 1, un cycle dure 4096 µ
//volatile float  duree_propagation = 0.0;//
volatile byte compteur = 0;
//volatile float date_evenement = 0.0;
//volatile float memo_evenement = 0.0;
int seuil = 10;
unsigned long chrono[100][2];
unsigned long duree_[100];
void setup() {
  pinMode(debut_evenement, INPUT_PULLUP);
//  pinMode(fin_evenement, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println(__FILE__); Serial.println("");// chemin
  Serial.println("systeme acquisition en one shoot par arret sur while(1)");


  cli();
  TCCR1A = 0;
  TCCR1B = 0b00000001;//le timer1 démarre, il sera lu à la volée. prescaler 1, ICES1 bit6 evenement falling sur D8
  TIMSK1 = 0b00100001;//autorise l'interruption de capture sur ICP1 (PB0 soit D8)sur flanc descendant
  TCNT1 = 0;          //tampon de comptage est razé
  ICR1 = 0;           //valeur du tampon de comptage sur arret du timer1
  sei();
}

ISR(TIMER1_OVF_vect)//à chaque debordement du timer1
{
  nombre_cycles++;
}
ISR(TIMER1_CAPT_vect) // capture ( recopie) TCNT1 dans ICR1 sur evenement en PB0 ( D8)
{
  
  chrono[++compteur][0] = ICR1;
  chrono[compteur][1] = nombre_cycles;
  //TCCR1B = 0b01000001; //declenchera sur flanc montant
}
void loop()
{
  if ((compteur >= seuil) && (flag_impression))
  { TCCR1B = 0b00000000;//arret du timer
    for (int f = 0; f <=seuil; f++)
    { Serial.print((chrono[f][0]));Serial.print("\t");Serial.print((chrono[f][1]));
    Serial.println("");}
    for (int f = seuil - 1; f > 0; f--)
    {
      Serial.print((((chrono[f + 1][0] * 62.5 + chrono[f + 1][1] * 4096000) - (chrono[f ][0] * 62.5 + chrono[f][1] * 4096000)) / 1000000),4);Serial.print("milli secondes");Serial.print("\t");
      Serial.print(((chrono[f + 1][0] * 62.5 + chrono[f + 1][1] * 4096000) - (chrono[f ][0] * 62.5 + chrono[f][1] * 4096000)) / 1000);Serial.print("micro secondes");Serial.print("\t");
      Serial.print(((chrono[f + 1][0] * 62.5 + chrono[f + 1][1] * 4096000) - (chrono[f ][0] * 62.5 + chrono[f][1] * 4096000)) / 1);Serial.println("nano secondes");
      Serial.flush();
      while(1);
      flag_impression = false; //flag1 = false;
    }
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.