volatile uint8_t nbP50Hz = 100; // Intervale de temps entre chaque mesure en nombre de périodes de 50 Hz
volatile uint8_t depMesure; // Comptage du nombre de périodes
void IRAM_ATTR lanceMesure() {
depMesure += 1;
if (depMesure == nbP50Hz) {
depMesure = 0;
ets_printf("depMesure\n");
}
}
void setup() {
attachInterrupt(26, lanceMesure, RISING);
}
void loop() {
}
L'entrée 27 est alimentée par du 50 Hz tout beau tout propre écrêté à 0 V et 3.3 V.
Et bien, au lieu d'avoir un résultat toutes des 2 secondes, j'ai un résultat qui tourne autour de 1.5 secondes avec des variations de ± 100 mS.
A l'oscillo, mon signal est très propre : pas de rebondissement visible. Les fronts ne sont pas très raides : 3 V pour 10 mS. Est-ce cela qui pourrait être la cause ?
Tu as mis ton code d'interruption est en IRAM (RAM Instructions), parfait.
.......mais il fait appel à une fonction qui , sauf erreur de ma part (je ne connais pas ses particularités), est exécutée , comme tout le reste, 'sur place' en mémoire Flash SPI, sans être chargé préalablement en totalité en RAM.
j'ai un doute sur les conséquences de cette acrobatie RAM/Flash SPI pour le code d'une fonction.
Il vaudrait mieux placer un buffer à trigger de Schmitt sur l'entrée pour éviter les problèmes.
Attention aussi à ce que tu utilises pour faire l'écrêtage. Certain montages/composants mettent du temps à récupérer s'il sont fortement saturés. Cela peut entrainer des dissymétrie sur le signal extrait. Ceci dit, comme tu ne comptes que les fronts montant tu devrais être à l'abris de ce problème.
You can use ets_printf() which is the alternative function (in ESP32 ROM) which is ISR-safe. But generally it's good to avoid things like printing to serial in interrupts at all, if you can.
Stockée en ROM elle ne poserait donc pas le pb d'accès a du code en Flash SPI à partir d'un code en RAM
Les ESP32 ont qq fonctions utilitaires à demeure dans leur petite ROM, en particulier pour le Bootloader
(petit driver SPI, petit driver UART...)
Un signal de 50Hz 0-3V avec un temps de montée de 3V en 10ms, ça me perturbe un peu !
La période du 50Hz est de 20ms.
En 20ms, le signal doit faire
0-->3V = 10ms selon les données
3V-->0V = 10ms
Es tu sûr de ton temps de montée?
Un front qui dure 1/2 période, ça me semble trop long, à voir!
Quel est le rapport cyclique de ce signal périodique ?
Quelle est la durée du front descendant?
Il faut conserver le montage et mettre le trigger de Schmitt après. Le trigger ne va pas faire l'écrêtage et il ne va pas apprécier de voir 30V alternatif sur son entrée.
Éventuellement tu pourrait peut-être t'en tirer en diminuant la 33k et/ou le condo de 10nF. C'est sans doute eux qui coupent la bande.
Cette fois, j'ai des temps de commutation de 4 µS et j'ai bien "environ" 2 S.
Que je place le morceau de code dans la loop() ou que je le laisse dans l'interruption ou encore que je mette IRAM_ATTR en en-tête de l'interruption ne change strictement rien.
Pour autant, en me basant sur le temps affiché par le moniteur série de l'IDE Arduino, la récurrence n'est pas stable :
Le traitement des données maj dans une interruption doivent être protégées d'un accès concurrent à l'extérieur ... et donc peut-être que le code suivant améliora la chose; à savoir (code non optimisé pour plus de pédagogie):
Ton montage ressemble plus à un filtre passe-bas qu'à un trigger de Schmitt.
Je ne suis pas certain que l'on puisse s'appuyer sur cette information pour vérifier la stabilité des mesures. Il y a trop d'intermédiaires entre la mesure et l'arrivée des données dans l'IDE.
Il faudrait envoyer la valeur de millis() avec ton échantillon pour vérifier cela.
Ce serait vrai si la capacité avait son retour sur l'entrée"-", mais elle revient sur l'entrée"+".
Avec une capacité à la place d'un résistance, je crée une hystérésis dynamique au lieu de statique.
En ce qui concerne la référence à millis(), ce n'est pas mieux . Ce à quoi il faut que je réfléchisse est que ces deux erreurs ne semblent pas vraiment corrélées. Ce qui voudrait dire, a priori, que le problème ne vient pas de l'interruption mais du système de mesure employé. Ce qui n’exclut pas d'ailleurs une propre imprécision de l'interruption ; il y a quand même une faible corrélation entre ces deux signaux (courbe que j'ai tracée en jaune).
Dans le cas présent, pour lever le doute entre le matériel et le logiciel, j'adopte la stratégie qui consiste à faire générer par l'esp32 le même joli signal carré ou rectangulaire (fréquence et rapport cyclique) qui sera injecté dans un 1st temps directement sur la pin d'acquisition et dans un 2nd temps et si le résultat attendu est correct, l'injecter en entrée de l'électronique
NB: Par expérience, l'acquisition du 50 Hz n'est pas simple car celui-ci peut présenter un bruit indétectable à l'oscilloscope avec en général des harmoniques également indétectables...
Cela paraît évident, mais ce 50Hz provient bien de ERDF ?
Si il y avait des harmoniques, il pourrait y avoir effectivement des fronts montants supplémentaires, d'où une mesure inférieure. Par contre lorsque le temps de mesure est supérieur à 2s, cela voudrait dire qu'il y a des pertes.
Autre remarque, il me semble qu'ERDF envoi des trames EC/EP et peut être EJP tous les jours sur le réseau. Il me semble qu'un filtre passe bas serait une bonne chose pour que votre montage ne compte pas ses trames.