Interruption sur un ESP32S2 [Résolu]

Bonjour,

Je veux me faire un compteur de rotation sur un axe, j'ai un capteur à effet hall, un aimant avec 6 pôles et un ESP32-S2
Je lui donne ceci avec arduino 1.8.19

 /*
 * esp          Capteur Hall
 * 3.3V           1
 * Gnd            2
 * 4                 3            10k    3.3v
 * 
 * 15      led interne
 * 
*/
#define pinSensor 4
const byte PulsesPerRevolution = 6;  // Définit le nombre d'impulsions à chaque révolution. 
const unsigned long ZeroTimeout = 200000;        // For high response time, a good value would be 100000.
                                                 // For reading very low RPM, a good value would be 300000.
volatile unsigned long LastTimeWeMeasured;       // Stocke la dernière fois que nous avons mesuré une impulsion afin que nous puissions calculer la période.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout+1000;      // Stocke la période entre les impulsions en microsecondes.
                                                 // Il a un grand nombre donc il ne commence pas par 0 qui serait interprété comme une fréquence élevée.
volatile unsigned long PeriodAverage = ZeroTimeout+1000;  // Stocke la période entre les impulsions en microsecondes au total, si nous prenons plusieurs impulsions.
                                                 // Il a un grand nombre donc il ne commence pas par 0 qui serait interprété comme une fréquence élevée.
unsigned long FrequencyRaw;                      // Fréquence calculée, basée sur la période. Cela a beaucoup de décimales supplémentaires
unsigned long FrequencyReal;                     // Frequency without decimals.
unsigned long RPM;                               // RPM brut sans aucun traitement.
unsigned int PulseCounter = 1;                   // nb de ticks prises afin que nous puissions faire la moyenne de plusieurs impulsions avant de calculer la période.
unsigned long PeriodSum;                         //Stocke la somme de toutes les périodes pour faire la moyenne.
unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;  
unsigned long CurrentMicros = micros();          
unsigned int AmountOfReadings = 1;
unsigned int ZeroDebouncingExtra;                
const int pinLed=15;
bool ledOut=0;


void setup() 
{  delay(5000);
   Serial.begin(115200);
   Serial.println("========================");
   Serial.println(__FILE__);
   attachInterrupt(digitalPinToInterrupt(pinSensor), Pulse_Event, RISING);  
   delay(1000);                                      // être suffisamment élevé pour les premiers cycles.
   pinMode(pinSensor, INPUT);
   pinMode(pinLed, OUTPUT);  } 

void loop()  
{ LastTimeCycleMeasure = LastTimeWeMeasured;         // Store the LastTimeWeMeasured in a variable.
  CurrentMicros = micros();                          // Store the micros() in a variable.              
  if(CurrentMicros < LastTimeCycleMeasure)
  {     LastTimeCycleMeasure = CurrentMicros;  }     // Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;        // Calculate the frequency using the period between pulses
  if(PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {     FrequencyRaw = 0;                            // Set frequency as 0.
        ZeroDebouncingExtra = 2000;      }           // Changez un peu le seuil pour qu'il ne rebondisse pas.
  else { ZeroDebouncingExtra = 0;   }
  FrequencyReal = FrequencyRaw / 10000;              // Obtient la fréquence sans décimales.
  RPM = FrequencyRaw / PulsesPerRevolution * 60;     // Frequency divided by amount of pulses per revolution multiply by
  RPM = RPM / 10000;                                 // Remove the decimals.
  
  Serial.print("\tRPM: ");
  Serial.println(RPM);
  ledOut = ! ledOut,
  digitalWrite(pinLed,ledOut);} 
 
void Pulse_Event()                   
{   PeriodBetweenPulses = micros() - LastTimeWeMeasured;   
    LastTimeWeMeasured = micros();                         
    if (PulseCounter >= AmountOfReadings)                  
     {     PeriodAverage = PeriodSum / AmountOfReadings;       
           PulseCounter = 1;                     
           PeriodSum = PeriodBetweenPulses;                
           int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);     
           RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);             
           AmountOfReadings = RemapedAmountOfReadings;   }
    else
     {     PulseCounter++;                                                   
           PeriodSum = PeriodSum + PeriodBetweenPulses;        }  }

L'esp32S2 en mode internal USB a besoin d'un certain temps pour que windows le reconnaisse donc que le moniteur série soit possible

Si le capteur est branché au démarrage l'ESP reboote éternellement et je ne peux rien voir
Si le capteur n'est pas branché au démarrage puis connecté tout fonctionne

Une explication de ceci ?

Cdlt
fr

fais gaffe il y a des pin destiné au reset de la carte et je crois que c'est la pin 15 qui effectue ça sur ta carte et tu l'utilise, change la a une autre pin ça sera good. check sur google "ESP32S2 pin"

Bonjour @fr

Si tu ne trouves pas de solution satisfaisante tu pourrais éviter de passer par des interruptions mais utiliser le module hardware PCNT (Pulse Counter) dédié intégré dans les ESP32 . les signaux font évoluer un compteur physique qui ne produit une interruption que lors de son débordement, interruptions beaucoup moins fréquentes...

En effet la GPIO 15 est indiquée comme 'outputs PWM signal at boot, strapping pin'

Difficile d'utiliser un ESP32 sans ce document à portée de vue !!

Bonsoir déjà une erreur que le compilateur ne trouve pas

Après la io15 c'est pour la led donc pas d'importance

Je peux avoir des détails, où trouver des renseignements ?

Je pensais en trouvant la virgule que c'était cela ! Pas du tout.

J'ai donc recherché où j'avais trouvé le bout de code : https://forum.arduino.cc/t/advice-needed-on-reading-30-000-rpm/644821

J'y mets un delay au début pour attendre que windows a reconnu l'esp32S2 mais c'est pas encore cela.... Doit y avoir une raison relative à la S2 car sur un esp cela a fonctionné, je vais d'ailleurs refaire le montage

Charger sur un wemos lolin32 lite avec la pin 18 pour l'interruption il affiche sur le moniteur série

C:\Users\admin\Desktop\arduino-1.8.19 sd\portable\sketchbook_projets_projet Anémomètre\Tachometer_Using_micros_c\Tachometer_Using_micros_c.ino
Period: 101000 Readings: 1 Frequency: 0 RPM: 0 Tachometer: 0

ETC.... et si je fais tourner l'axe il resete !

Period: 101000 Readings: 1 Frequency: 0 RPM: 0 Tachometer: 0
Period: 101000 Readings: 1 Frequency: 0 RPM: 0 Tachometer: 0
Guru Meditation Error: Core 1 panic'ed (IntegerDivideByZero). Exception was unhandled.

Core 1 register dump:
PC : 0x4000cb55 PS : 0x00060630 A0 : 0x800d11f4 A1 : 0x3ffb27e0
A2 : 0x540be400 A3 : 0x00000002 A4 : 0x00000000 A5 : 0x00000000
A6 : 0x00000001 A7 : 0x00000000 A8 : 0x00000001 A9 : 0x00000000
A10 : 0x540be400 A11 : 0x00000002 A12 : 0x0000000a A13 : 0x3ffc1594
A14 : 0x00000003 A15 : 0x00060023 SAR : 0x00000011 EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x4008410d LEND : 0x40084115 LCOUNT : 0x00000027

Backtrace:0x4000cb52:0x3ffb27e00x400d11f1:0x3ffb2800 0x400d1d1d:0x3ffb2820

ELF file SHA256: 0000000000000000

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13160
load:0x40080400,len:3036
entry 0x400805e4

C:\Users\admin\Desktop\arduino-1.8.19 sd\portable\sketchbook_projets_projet Anémomètre\Tachometer_Using_micros_c\Tachometer_Using_micros_c.ino
Period: 101000 Readings: 1 Frequency: 0 RPM: 0 Tachometer: 0
etc...

Avec l'esp32

// https://forum.arduino.cc/t/advice-needed-on-reading-30-000-rpm/644821/8


#include<Chrono.h>

int passcount=-1;
int ledstate = 0;
const int bladecount = 2;
const int irpin =18;
const int ledpin = 15;
const int sample = 100;
unsigned long rpm;
unsigned long freq;
unsigned long period;
volatile unsigned long firstpass;
volatile unsigned long lastpass;
unsigned long t;

Chrono sampletimer;

void passdetect(){
  passcount++;
  if(passcount==1){
    firstpass = micros();
  }
  lastpass = micros();
}

void setup() {
   delay(5000);
   Serial.begin(115200);
   Serial.println("========================");
   Serial.println(__FILE__);  
  attachInterrupt(digitalPinToInterrupt(irpin), passdetect, RISING);
  pinMode(irpin, INPUT);
  pinMode(ledpin, OUTPUT);
  passcount = 0;
  delay(1000);  
}

void loop() {
  
  if(sampletimer.hasPassed(sample) && passcount > 0){
    
    t = lastpass - firstpass;
    Serial.print("lastpass : ");Serial.println(lastpass);
    Serial.print("firstlastpass : ");Serial.println(firstpass);
    firstpass = 0;
    lastpass = 0;
    Serial.print("t : ");Serial.println(t);
    Serial.print("passcount : ");Serial.println(passcount);
    Serial.print("bladecount : ");Serial.println(bladecount); 
    period = (t/passcount)*bladecount;
    
    Serial.print("period : ");Serial.println(period);
    freq = 1000000/period;
    rpm = freq*60; 
    
    
    passcount = 0;

    Serial.print(rpm);
    Serial.println(" RPM");
    digitalWrite(ledpin, ledstate);
    ledstate = !ledstate;
    sampletimer.restart();
  }
}

il reboote au second pulse car pas le temps de d'incrémenter la durée lastpass

Dans le programme du début du fil [quote="fr, post:1, topic:1057184"]
unsigned long PeriodSum;
[/quote]

Il faut initialiser à 1 car le reboot est dû à une division par zéro dans la routine d'interruption