Arduino DUE parasites sur les pins digitales 22 a 53

Bonjour à tous,

Dans le cadre de mon projet de comptage des entrées sorties d'abeilles pour une ruche, j'utilise les E/S 22 a 53 d'un Arduino DUE auxquelles j'attache une interruption en RISING
sans raccordement à mon schield capteurs (donc DUE nue) malgré la mise en service des pull-up internes j'ai des interruptions parasites au démarrage

 demarrage
..........
port : 22
port : 23
port : 25
port : 33
Irq2

si je force a 0 ces entrées et que je redémarre le programme j'ai d'autres entrées qui passent en interruption

 demarrage
..........
port : 24
port : 26
port : 34
port : 36
Irq2

la DUE est made in Chine et je pense à des parasites du step-down sur les pistes de ces E/S,
raccordée a mon schield capteurs j'ai des phénomènes de rebond sur certaines entrées malgré que les signaux sortent d'un comparateur LM393 avec un 100nF à la masse (cela provoque parfois le plantage du DUE d'ou le chien de garde)

je joint mon code de test si certains veulent faire ce test sur d'autres cartes ...

#include <DueTimer.h> // inclusion de la librairie DueTimer pour interruption temporelle

volatile int Irq2 = 0;
const unsigned int periode = 10000000; // 10s pour les test 60s après

// --------------------------------------------------------------------

void watchdogSetup(void)
{
  //obligatoire pour que le chien de garde fonctionne.
}

void setup() {
  Serial.begin(57600);
  Serial.println("");
  Serial.println(F("demarrage"));

  for (int i = 22; i <= 53; i++) {
    pinMode(i, INPUT_PULLUP); // mise en service pull-up interne
  }
  for (int i = 0 ; i < 10 ; i++) { // délais pour stabilisation des entrées
    Serial.print(F("."));
    delay(1000);
  }
  Serial.println();

  attachInterrupt(digitalPinToInterrupt(22), Irq22, RISING);
  attachInterrupt(digitalPinToInterrupt(23), Irq23, RISING);
  attachInterrupt(digitalPinToInterrupt(24), Irq24, RISING);
  attachInterrupt(digitalPinToInterrupt(25), Irq25, RISING);
  attachInterrupt(digitalPinToInterrupt(26), Irq26, RISING);
  attachInterrupt(digitalPinToInterrupt(27), Irq27, RISING);
  attachInterrupt(digitalPinToInterrupt(28), Irq28, RISING);
  attachInterrupt(digitalPinToInterrupt(29), Irq29, RISING);
  attachInterrupt(digitalPinToInterrupt(30), Irq30, RISING);
  attachInterrupt(digitalPinToInterrupt(31), Irq31, RISING);
  attachInterrupt(digitalPinToInterrupt(32), Irq32, RISING);
  attachInterrupt(digitalPinToInterrupt(33), Irq33, RISING);
  attachInterrupt(digitalPinToInterrupt(34), Irq34, RISING);
  attachInterrupt(digitalPinToInterrupt(35), Irq35, RISING);
  attachInterrupt(digitalPinToInterrupt(36), Irq36, RISING);
  attachInterrupt(digitalPinToInterrupt(37), Irq37, RISING);
  attachInterrupt(digitalPinToInterrupt(38), Irq38, RISING);
  attachInterrupt(digitalPinToInterrupt(39), Irq39, RISING);
  attachInterrupt(digitalPinToInterrupt(40), Irq40, RISING);
  attachInterrupt(digitalPinToInterrupt(41), Irq41, RISING);
  attachInterrupt(digitalPinToInterrupt(42), Irq42, RISING);
  attachInterrupt(digitalPinToInterrupt(43), Irq43, RISING);
  attachInterrupt(digitalPinToInterrupt(44), Irq44, RISING);
  attachInterrupt(digitalPinToInterrupt(45), Irq45, RISING);
  attachInterrupt(digitalPinToInterrupt(46), Irq46, RISING);
  attachInterrupt(digitalPinToInterrupt(47), Irq47, RISING);
  attachInterrupt(digitalPinToInterrupt(48), Irq48, RISING);
  attachInterrupt(digitalPinToInterrupt(49), Irq49, RISING);
  attachInterrupt(digitalPinToInterrupt(50), Irq50, RISING);
  attachInterrupt(digitalPinToInterrupt(51), Irq51, RISING);
  attachInterrupt(digitalPinToInterrupt(52), Irq52, RISING);
  attachInterrupt(digitalPinToInterrupt(53), Irq53, RISING);

  Timer2.attachInterrupt(IrqT2).setPeriod(periode).start(); //10s
  watchdogEnable(8000); // active le chien de garde avec un timeout de 8s.
}


// ----------------------------------------------------------------
void loop() {

  watchdogReset(); // raz du chien de garde.
  if (Irq2 == 1) {
    Serial.println("Irq2 ");
    Irq2 = 0;
  }
}
// ----------------------------------------------------------------

void detectI(int i) { // détection passage opto Intérieur
  Serial.print("port : "), Serial.println(i+22);

}
// ---------------------------------------------------------------
void detectE(int i) { // détection passage opto Extérieur
  Serial.print("port : "), Serial.println(i+22);
}
// -----------------------------------------------------
void IrqT2()  { // toutes les minutes
  Irq2 = 1;
}
// -------------------------------------

// ---------------------------------------------------------
void Irq22() {
 // noInterrupts();
  detectI(0);
 // interrupts();
}
void Irq23() {
 // noInterrupts();
  detectI(1);
 // interrupts();
}
void Irq24() {
  //noInterrupts();
  detectI(2);
  //interrupts();
}
void Irq25() {
 // noInterrupts();
  detectI(3);
 // interrupts();
}
void Irq26() {
  //noInterrupts();
  detectI(4);
  //interrupts();
}
void Irq27() {
 // noInterrupts();
  detectI(5);
 // interrupts();
}
void Irq28() {
 // noInterrupts();
  detectI(6);
 // interrupts();
}
void Irq29() {
 // noInterrupts();
  detectI(7);
 // interrupts();
}
void Irq30() {
 // noInterrupts();
  detectI(8);
 // interrupts();
}
void Irq31() {
 // noInterrupts();
  detectI(9);
 // interrupts();
}
void Irq32() {
 // noInterrupts();
  detectI(10);
 // interrupts();
}
void Irq33() {
 // noInterrupts();
  detectI(11);
 // interrupts();
}
void Irq34() {
  //noInterrupts();
  detectI(12);
  //interrupts();
}
void Irq35() {
 // noInterrupts();
  detectI(13);
 // interrupts();
}
void Irq36() {
 // noInterrupts();
  detectI(14);
 // interrupts();
}
void Irq37() {
 // noInterrupts();
  detectI(15);
 // interrupts();
}

void Irq38() {
 // noInterrupts();
  detectE(0);
 // interrupts();
}
void Irq39() {
 // noInterrupts();
  detectE(1);
 // interrupts();
}
void Irq40() {
 // noInterrupts();
  detectE(2);
 // interrupts();
}
void Irq41() {
 // noInterrupts();
  detectE(3);
 // interrupts();
}
void Irq42() {
 // noInterrupts();
  detectE(4);
 // interrupts();
}
void Irq43() {
 // noInterrupts();
  detectE(5);
 // interrupts();
}
void Irq44() {
 // noInterrupts();
  detectE(6);
 // interrupts();
}
void Irq45() {
 // noInterrupts();
  detectE(7);
 // interrupts();
}
void Irq46() {
 // noInterrupts();
  detectE(8);
 // interrupts();
}
void Irq47() {
 // noInterrupts();
  detectE(9);
 // interrupts();
}
void Irq48() {
 // noInterrupts();
  detectE(10);
 // interrupts();
}
void Irq49() {
 // noInterrupts();
  detectE(11);
 // interrupts();
}
void Irq50() {
 // noInterrupts();
  detectE(12);
 // interrupts();
}
void Irq51() {
 // noInterrupts();
  detectE(13);
 // interrupts();
}
void Irq52() {
 // noInterrupts();
  detectE(14);
 // interrupts();
}
void Irq53() {
 // noInterrupts();
  detectE(15);
 // interrupts();
}

// ------------------------------------------------------
void reset() {
  while (1) {}; // blocage pour reset sur déclenchement du chien de garde.
}
// ----------------------------------------------------

si vous avez des suggestions .....

Salut, j'ai également une DUE "low cost", je vais tenter ça en fin d’après midi et t'exposerais mes résultats.

malgré la mise en service des pull-up internes j'ai des interruptions parasites au démarrage

Les pullups font entre 50k et 150k. Cela ne protège pas beaucoup les entrées.
Dans la doc du processeur, il est indiqué que l'on peut activer un filtrage sur les entrées (glitch input filter).

les signaux sortent d'un comparateur LM393 avec un 100nF à la masse

Un condensateur sans résistance ne filtre pas grand chose.

fdufnews:
Les pullups font entre 50k et 150k. Cela ne protège pas beaucoup les entrées.
Un condensateur sans résistance ne filtre pas grand chose.

il y a donc la résistance de pull-up au + (j'avais lu 100k) et le condo au -, sachant que je filtre aussi a l'entrée des comparateurs (470K + 0.33µF) le front devrait être propre ...

Bonjour,

Peux-tu joindre le schéma de principe des circuits d'entrées avec tes comparateurs ?

désolé pour la qualité, c'est un document de travail ...
mais ça fonctionne très bien sur certaines entrées et moins bien sur d'autres ...

Tests effectués:

1er test:
demarrage
..........
port : 22
port : 23
port : 25
port : 33
Irq2

2eme essais:
demarrage
..........
port : 22
port : 23
port : 25
port : 33
Irq2

3éme essais:
demarrage
..........
port : 22
port : 23
port : 25
port : 33
Irq2

merci bcp
ça semble confirmer un défaut de conception ....
reste a savoir comment faire avec ....

Bonjour,
ce qui t'arrive est "normal"
au démarrage du mcu, les pull up chargent les capas, très lentement compte tenu des valeurs
ton signal se trouve donc un bon moment dans la zone de basculage des entrés de la mcu, zone dans laquelle et période pendant laquelle il est particulièrement sensible aux parasites !
ce qu'il faut faire :
diminuer les pull up et les capas pour raidir le flanc
choisir (si tu peux) les entrées ayant le meilleur hystérésis
actionner (cf fdufnews) le filtre digital

Je pense aussi au lm393 a-t-il de l'hystérésis ?

trimarco232:
ce qui t'arrive est "normal"
au démarrage du mcu, les pull up chargent les capas, très lentement compte tenu des valeurs
ton signal se trouve donc un bon moment dans la zone de basculage des entrés de la mcu, zone dans laquelle et période pendant laquelle il est particulièrement sensible aux parasites !

j'avais pensé a cela c'est pour ça qu'il y a une tempo de 10s entre la mise en service de pull-up et l'attachement des inter

ce qu'il faut faire :
diminuer les pull up et les capas pour raidir le flanc
choisir (si tu peux) les entrées ayant le meilleur hystérésis

je viens de faire un essai sur une pin "sensible" avec un pull-up externe de 47K (en plus de l'interne) ça améliore le filtrage

actionner (cf fdufnews) le filtre digital

je suis entrain de consulter le datasheet ch 31.5.9 "input Glitch and Debouncing Filters", ça semble être la solution mais mon anglais et mes connaissances de l'assembleur laissent à désirer ....
je veux quand même garder un système réactif, une abeille peux traverser les 2 fourches en moins de 1/10 de s, je dois déterminer le sens de passage et il y a 12 "portes" d'E/S

un pull-up externe de 47K

pas de quartier : 1k et 1nF !

mes connaissances de l'assembleur laissent à désirer

tu peux écrire directement dans le registre en c

une abeille peux traverser les 2 fourches en moins de 1/10 de s,

raison de + pour une constante rc réactive
bonne réflexion, mais je pense (pas vérifié) que la puce est bien plus rapide que l'abeille !

bonne réflexion, mais je pense (pas vérifié) que la puce est bien plus rapide que l'abeille !

ça voudrai mieux pour la DUE .... sinon elle va valser à la poubelle .... lol :slight_smile:

68tjs:
Je pense aussi au lm393 a-t-il de l'hystérésis ?

oui tu as raison 1mv !!! j'ai filtré mais pas mis d'hystérésis, ce sera surement mes futurs problèmes ....

trimarco232:
pas de quartier : 1k et 1nF !

tu y vas fort certains ports supporte seulement 3mA

tu peux écrire directement dans le registre en c

je pense avoir compris 2 modes de filtrage :
Input Glitch Filter : il faut au moins que l'entrée passe a 1 pendant 2 cycles d'horloge (au lieu de 1)
Input Deboucing Filter : on affecte un diviseur d'horloge au port d'E/S et on valide le filtrage pour les différentes E/S du port
mais pour faciliter la tache les Pins digitales 22 a 53 ne se trouvent pas sur le même port (A, B, C et D) et pas de façon contigüe donc il faut traduire ça en masque hexa
je pense me lancer sur le Glitch dans un premier temps (j'ai trouve des posts dans la partie anglaise qui en parle)

pour ceux qui jouent avec un DUE j'ai trouvé une personne qui a écrit une fonction debounce

void setDebounce(int pin, int usecs) { // reject spikes shorter than usecs on pin
  if (usecs) {
    g_APinDescription[pin].pPort -> PIO_IFER = g_APinDescription[pin].ulPin;
    g_APinDescription[pin].pPort -> PIO_DIFSR |= g_APinDescription[pin].ulPin;
  }
  else {
    g_APinDescription[pin].pPort -> PIO_IFDR = g_APinDescription[pin].ulPin;
    g_APinDescription[pin].pPort -> PIO_DIFSR &= ~ g_APinDescription[pin].ulPin;
    return;
  }
  int div = (usecs / 31) - 1; if (div < 0)div = 0; if (div > 16383) div = 16383;
  g_APinDescription[pin].pPort -> PIO_SCDR = div;
}

ça fonctionne très bien, même trop bien, on peut mettre au max 500000µs soit 0.5s !!!
c'est une bonne solution quand on utilise des capteurs attachés a des interruptions plutôt que d'utiliser millis
mais ça ne corrige pas les défaut constatés au départ