[Conseil] création d'une interuption déclanché par le programme

Bonjour,
Je suis entrain de fabriquer un compteur Geiger, et j’aurai besoin de créer une boucle de comptage la plus efficace possible :
-compter un maximum d’impulsion/seconde en en loupant le moins possible).

J’aimerai que la boucle de comptage tourne seule 5 secondes, puis que le reste du programme face un cycle puis retourne à la boucle de comptage, etc.

Mais je ne trouve pas comment coder le comptage le plus simplement possible pour que la vitesse d’enregistrement soit la plus rapide et efficace possible.

Si quelqu’un à une idée, je suis preneur :slight_smile:

Merci :slight_smile:

PS :
Pour le moment, le mieux que j'ai trouvé (merci Vileroi pour le conseil :wink: ) serait d'utiliser la fonction milis.
Quelque chose du genre :

if( millis() - previousMillis >= interval)
{
previousMillis = millis();
programme compteur ;
}
else
{
programme affichage et menu
}

Bonsoir,
il suffit de rentrer les "top" sur une entrée positionnée en interruption et dans la routine d'interruption de compter les "top" sur la période voulue puis de faire une moyenne glissante

dans la loop il suffit d'aller rechercher cette valeur pour l'afficher

vu que au max ca doit être 5000 top seconde ca devrait rien rater

y a de nombreux exemple de comptage et d'affichage a partir d'une interruption partout.

Merci, je recherche depuis que tu m'as donné l'info, mais je ne trouve pas d'exemple simple. Pourrais tu me conseiller?

En enlevant tout le reste du programme pour que ce soit plus lisible, j'ai fait ceci qui fonctionne, mais je ne sais pas si c'est le plus optimum?

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

int boutonPin  = 2 ;
int compteur = 0 ;
volatile boolean changed = false;

void doContact() {
  changed = true;
  compteur++;
}


void setup() { 
  
Serial.begin(9600);
  lcd.init();       
  lcd.backlight();
  lcd.clear ();


 

  pinMode(boutonPin, INPUT);
  attachInterrupt(0, doContact, FALLING);

} 


void loop() {

  if ( changed ) {

    changed = false;
lcd.setCursor (0,0);
   lcd.print(compteur);
  
       }

  delay(2000);
  

}

Salut. Je trouve que l’interruption que tu as trouvé est bien et il faudrait un oscilloscope pour comparer des codes à ce niveaux (tu as parlé de compteur geiger, ça ne se trouve pas à tous les coins de rue, tu peux peut être dégotter ca)
Tu peux optimiser selon la carte que tu utilise pour assurer la lecture la plus rapide d'un changement sur la pin. J'aime bcp faire ça mais ça demande de lire le manuel du fabricant et pas mal d'essais à l'aveugle.
Des reglages encore plus subtils peuvent se jouer sur l’hysteresie, c'est la pente que fait le voltage en passant de 0 à 5V mais là il faut vraiment un oscilloscope (et qu'un qui s'y connaîtra mieux que moi).

En tout cas, ton interruption va se déclencher très rapidement dès que la carte verra un basculement de tension depuis ton compteur, et rapidement rendre la main en ne traitant que 2 variables (c'est judicieux, un expert en codage proposerait sans doute que les valeurs modifiées se suivent par la position d’un pointeur) pour ne pas rater un second signal très rapproché du 1er.

Merci :slight_smile:
J'ai bien un oscilloscope, mais je pensai tout d'abord coder quelque chose de propre avant de fignoler ;p

(tu as parlé de compteur geiger, ça ne se trouve pas à tous les coins de rue, tu peux peut être dégotter ca)

Si tu savais tout ce que l'on trouve ne serait ce que sur E*ay, du capteur Geiger à la source radioactive de ton choix : de la roche au générateur à rayonX haute tension (en passant par des soit disant autocollant anti onde pour téléphone qui sont très radioactif!!!)...
Mon montage sera pour la détection de faible dose sur les aliments, colis, roche...
Par exemple, je suis allé ramasser des fossiles de plantes dans une ancienne mine de charbon, et à mon retour j'ai découvert qu'ils étaient radioactif (10x le bruit de fond). Du coup ils restent dehors!

Niveau manuel, c'est du matos Russe de la guerre froide (SBT10-A), la "notice" est plutôt succincte et en cyrillique...
Jusqu'à maintenant, j'ai fait tout les réglages par tâtonnement pour optimiser un maximum la sensibilité à faible dose (changement de tension d'alimentation, avec tout le bazar d'une prise de mesure sur du 500V DC et la chute de tension associée (j'utilise un pont de résistance à 100Mohms)).

un expert en codage proposerait sans doute que les valeurs modifiées se suivent par la position d'un pointeur

Cette idée m'intéresse, pourrais tu m'expliquer en quoi cela consisterait?

Merci :slight_smile:

Hop: dégoté sur le bloc arduino. Le commentaire général du gars est de traiter les variables internes d'une boucle avec un pointeur unique (l’incrementation du pointeur fera passer le code à la variable suivante) ce qui serait intéressant si tu lisais plus d'une valeur à la fois.
En relisant ta boucle, le format ne s'y prête pas, à moins de traiter le boolean ”changed” en int comme le compteur.

// dans le setup; tableau a 2 valeurs pour compter les resultats
Int Resultat[2] = {0} ;
Int *p = Null;
P = Resultat; // pointeur de int vers la 1ere valeur du tableau 

//dans l'interruption :
*p =1; // équivalent au boolean: 1 mesure prise au moins
*(p+1) = *(p+1) + 1; // incremente de 1 le compteur

Vu la simplicité de ton code, tu n'y gagnerai pas plus qu'une fierté de programmeur

Bonjour,

Ton programme est opérationnel, mais il peut être amélioré

  • la variable 'changed' ne sert à rien et est même nuisible car si tu n'as aucune impulsion il faut quand même afficher 0
  • il vaut mieux utiliser millis() que delay car ça prend en compte le temps d'exécution des instructions, de plus ça ne bloque pas le programme.
  • il faut masquer les interruptions pour lire le compteur et le lire le plus rapidement possible pour éviter qu'il se modifie pendant la lecture
  • si tu veux afficher le nombre d'impulsions toutes le n secondes il faut remettre le compteur à 0 (ou soustraire le compteur précédent).

Ca donne un programme comme ça par exemple

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

const byte boutonPin  = 2 ;
unsigned compteur = 0 ;

void doContact() {
  compteur++;
}


void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.clear ();

  attachInterrupt(digitalPinToInterrupt(boutonPin), doContact, FALLING);
}


void loop() {
  static u32 lastMillis = millis();
  if (millis() - lastMillis >= 2000)
  {
    noInterrupts();
    unsigned cpt = compteur;  // mémorise le compteur
    compteur = 0;
    lastMillis = millis();
    interrupts();
    lcd.setCursor (0, 0);
    lcd.print(cpt);
    lcd.print("   "); // efface les éventuels chiffres précédents
  }
}

Bonjour

rien a ajouter ... j'aurais utilisé cli() et sei() mais c'est la même chose.

projet complet ici

la gestion des interruptions est un peu plus "hard" a comprendre mais il suffit de s'y mettre et ça roule...

Merci pour toutes ces réponses :slight_smile:

Mon code est un petit peut plus complexe dans son ensemble que la version épurée si dessus, d’où l'idée de faire une interruption pour ne pas perdre d’impulsion.

Dans le code si dessous, je n'ai pas encore codé :
-menu de réglage alarme
-affichage moyenne 5''
-affichage moyenne 1'
-affichage max sur moyenne 5''

Et j'avais super envie de faire mon code plutot que d'en prendre un tout fait que je ne comprendrai pas forcément :slight_smile:

//Library version:1.1 arduino_499745
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display


int geigerPin  = 2 ;
unsigned long x = 1; // Bq
volatile boolean changed = false;

void doContact() {
  changed = true;
  x++;
}





void setup()
{
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd
  lcd.backlight(); // retroéclérage
  lcd.clear ();




 pinMode(geigerPin, INPUT);
  attachInterrupt(0, doContact, FALLING);
 




}
void loop()
{


 


  
  unsigned int a = 0 ; // clode de x pour factorisation k M G dans total CPM
  unsigned int b = 0 ; // clode de x pour factorisation k M G dans total Sv/h   ; int pour suprimer les chiffres apres la virgules
  float c = 0.88 ; // 0.88 facteur de convertion affichage nano Sv/h, etalonage SBT10-A 220cpm vs radex 0.25µSv/h, 
  

 




 




    
    



    // BQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBQB
    // BQ          BQBQBQB          QBQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQBQBQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQBQBQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQBQBQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ          BQBQBQ  BQBQBQBQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQBQBQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQ  BQ  BQBQBQBQBQBQBQBQBQBQBQB
    // BQ  BQBQBQB  QBQBQ  BQBQBQ    BQBQBQBQBQBQBQBQBQBQBQB
    // BQ          BQBQBQB        QB   BQBQBQBQBQBQBQBQBQBQB
    // BQBQBQBQBQBQBQBQBQBQBQBQBQBQBQBBQQBQBQBQBQBQBQBQBQBQB

    lcd.setCursor(0, 3);
    lcd.print (F("TT")) ;

    // debut comptage Bq

    //comptage Bq jusqu'à 1000
    if ( (x > 0) && (x < 10000) )  // si x est compri entre bidule et machin alors blabla
    {


      if (x < 10)
      {
        lcd.setCursor(6, 3);
        lcd.print (x) ;
      }

      if ( (x >= 10) && (x < 100) )
      {
        lcd.setCursor(5, 3);
        lcd.print (x) ;
      }

      if ( (x >= 100) && (x < 1000) )
      {
        lcd.setCursor(4, 3);
        lcd.print (x) ;
      }

      if ( (x >= 1000) && (x < 10000) )
      {
        lcd.setCursor(3, 3);
        lcd.print (x) ;
      }

      lcd.setCursor (7, 3);
      lcd.print (F(" Bq")) ;
    }


    //+++++++++++++++++++++++++++++++++++++++++
    //comptage entre 10 000 et 10 000 000


    if ( (x >= 10000) && (x < 10000000) )  // si x est compri entre bidule et machin alors blabla
    {


      a = x / 1000 ;
      
        
      if (a < 11)
      {
        //efface ancien texte
       lcd.setCursor(3, 3);
        lcd.print (F("     ")) ;

        //affichage CPM
        lcd.setCursor(5, 3);
         lcd.print (a) ;


       
      }

      if ( (a >= 11) && (a < 100) )
      {
        lcd.setCursor(5, 3);
         lcd.print (a) ;

      }

      if ( (a >= 100) && (a < 1000) )
      {
        lcd.setCursor(4, 3);
         lcd.print (a) ;

      }

      if ( (a >= 1000) && (a < 10000) )
      {
        lcd.setCursor(3, 3);
         lcd.print (a) ;

      }


      lcd.setCursor (7, 3);
      lcd.print (F("kBq")) ;

    }


    //+++++++++++++++++++++++++++++++++++++++++
    //comptage entre 10 000 et 10 000 000


    if ( (x >= 10000000) && (x < 10000000000) )  // si x est compri entre bidule et machin alors blabla
    {


      a = x / 1000000 ;
      if (a < 11)
      {
        //efface ancien texte
        lcd.setCursor(3, 3);
        lcd.print (F("    ")) ;

        //affichage CPM
        lcd.setCursor(5, 3);
        lcd.print (a) ;


        // delay(100); // permet affichage stable suite à l'affichage "   "
      }

      if ( (a >= 11) && (a < 100) )
      {
        lcd.setCursor(5, 3);
        lcd.print (a) ;

      }

      if ( (a >= 100) && (a < 1000) )
      {
        lcd.setCursor(4, 3);
        lcd.print (a) ;

      }

      if ( (a >= 1000) && (a < 10000) )
      {
        lcd.setCursor(3, 3);
        lcd.print (a) ;

      }


      lcd.setCursor (7, 3);
      lcd.print (F("MBq")) ;

    }
    //+++++++++++++++++++++++++++++++++++++++++
    //comptage entre 10 000 000 et 10 000 000 000


   /* if ( (x >= 10000000000) && (x < 10000000000000) )  // si x est compri entre bidule et machin alors blabla
    {


      a = x / 1000000000 ;
      if (a < 11)
      {
        //efface ancien texte
        lcd.setCursor(3, 3);
        lcd.print (F("    ")) ;

        //affichage CPM
        lcd.setCursor(5, 3);
        lcd.print (x / 100000000) ;



      }

      if ( (a >= 11) && (a < 100) )
      {
        lcd.setCursor(4, 3);
        lcd.print (x / 100000000) ;

      }

      if ( (a >= 100) && (a < 1000) )
      {
        lcd.setCursor(3, 3);
        lcd.print (x / 100000000) ;

      }

      if ( (a >= 1000) && (a < 10000) )
      {
        lcd.setCursor(2, 3);
        lcd.print (x / 100000000) ;

      }


      lcd.setCursor (7, 3);
      lcd.print (F("GBq")) ;

    }
*/



    //MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
    //MMMMMM     MMMM MMMMM MMMMMMMMMMMMMMMMMMMMM
    //MMMMMM MMMMMMMM MMMMM MMMMMMMMMMMMMMMMMMMMM
    //MMMMMM MMMMMMMMM MMM MMMMMMMMMMMMMMMMMMMMMM
    //MMMMMM     MMMMM MMM MMMMMMMMMMMMMMMMMMMMMM
    //MMMMMMMMMM MMMMMM M MMMMMMMMMMMMMMMMMMMMMMM
    //MMMMMMMMMM MMMMMM M MMMMMMMMMMMMMMMMMMMMMMM
    //MMMMMM     MMMMMMM MMMMMMMMMMMMMMMMMMMMMMMM
    //MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
    //comptage µSh/h

    //float u = x ; //clonde de x pour camcule µSv/h
    //(x*c) ; //u clone de x, x entrée geiger cpm, c facteur de conversion

    //++++++++++++++++++++++++++++++++++++++++++++++++++
    //comptage Sv/h jusqu'à 10000nSv/h
    if ( (x * c > 0) && (x * c < 10000) ) // si x est compri entre bidule et machin alors blabla
    {


      if (x * c < 10)
      {
        lcd.setCursor(16, 3);
        lcd.print (round(x * c)) ;
      }

      if ( (x * c >= 10) && (x * c < 100) )
      {
        lcd.setCursor(15, 3);
        lcd.print (round(x * c)) ;
      }

      if ( (x * c >= 100) && (x * c < 1000) )
      {
        lcd.setCursor(14, 3);
        lcd.print (round(x * c)) ;
      }

      if ( (x * c >= 1000) && (x * c < 10000) )
      {
        lcd.setCursor(13, 3);
        lcd.print (round(x * c)) ;
      }

      lcd.setCursor (17, 3);
      lcd.print (F("nSv")) ;
    }

    //++++++++++++++++++++++++++++++++++++++++++++++++++
    //comptage Sv/h jusqu'à 10 000 000uSv/h
    if ( (x * c > 10000) && (x * c < 10000000) ) // si x est compri entre bidule et machin alors blabla
    {
      lcd.setCursor (17, 3);
      lcd.print (F("uSv")) ;
      b = x / 1000 * c ;
      if (b < 11)
      {
        lcd.setCursor (13, 3) ;
        lcd.print (F("     ")) ;
        lcd.setCursor(15, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 11) && (b < 100) )
      {
        lcd.setCursor(15, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 100) && (b < 1000) )
      {
        lcd.setCursor(14, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 1000) && (b < 10000) )
      {
        lcd.setCursor(13, 3);
        lcd.print (round(b)) ;



      }

      lcd.setCursor (17, 3);
      lcd.print (F("uSv")) ;
    }

    //++++++++++++++++++++++++++++++++++++++++++++++++++
    //comptage Sv/h jusqu'à 10000uSv/h
    if ( (x * c > 10000000) && (x * c < 10000000000) ) // si x est compri entre bidule et machin alors blabla
    {

      b = x / 1000000 * c ;
      if (b < 11)
      {
        lcd.setCursor (13, 3) ;
        lcd.print (F("     ")) ;
        lcd.setCursor(15, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 11) && (b < 100) )
      {
        lcd.setCursor(15, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 100) && (b < 1000) )
      {
        lcd.setCursor(15, 3);
        lcd.print (round(b)) ;
      }

      if ( (b >= 1000) && (b < 10000) )
      {
        lcd.setCursor(14, 3);
        lcd.print (round(b)) ;
      }

      lcd.setCursor (17, 3);
      lcd.print (F("mSv")) ;
    }

  }

g_u_i_l_la_u_me:
Et j'avais super envie de faire mon code plutot que d'en prendre un tout fait que je ne comprendrai pas forcément :slight_smile:

Oh yeah !

Serial.begin(9600);

On conseille sur ce forum de passer en 115200 bauds, il faut changer la console une fois pour toutes. Si personne ne teste ton code, pas de problèmes, tu peut mettre ce que tu veux, Mai cela décourage ceux qui veulent tester ton code car il faut que ce soit eux qui changent deux fois leur console.


lcd.print (x) ;
      lcd.print (F(" Bq")) ;

Les Bq c'est pas désintégrations par secondes? Auquel cas il faut afficher et remettre x à 0 toutes les secondes
Dans cas, c'est un peu plus compliqué de mettre x à 0.


Au lieu de
si x<10 ....;
si 10<=x<100 ....;
si 100<=x<1000 ...;
si 1000<=x<10000 ...;
si 10000<=x<100000 ...;
on peut faire
si x<10 ....;
sinon si x<100 ....;
sinon si 100<=x<1000 ...;
sinon si x<10000 ...;
sinon si x<100000 ...;
Cela fait moins de tests


  if ( (x >= 100) && (x < 1000) )
      {
        lcd.setCursor(4, 3);
        lcd.print (x) ;
      }

Ce genre est répété souvent. On fait alors une fonction

void affiche(uint8_t ligne, uint8_t colonne, unsigned long nb)
{
  if (nb<10) 
  {
   lcd.setCursor(colonne+4, ligne);
   lcd.print (nb) ;
 }
 else if (nb<100) 
 {
   lcd.setCursor(colonne+3, ligne);
   lcd.print (nb) ;
 }
 else if (nb<1000) 
 {
   lcd.setCursor(colonne+2, ligne);
   lcd.print (nb) ;
 }
 else if (nb<10000) 
 {
   lcd.setCursor(colonne+1, ligne);
   lcd.print (nb) ;
 }
 else if (nb<100000) 
 {
   lcd.setCursor(colonne, ligne);
   lcd.print (nb) ;
 }
}

On peut aussi faire une fonction

void affiche1((uint8_t ligne, uint8_t colonne, unsigned long nb)
{
 lcd.setCursor(colonne, ligne);
 lcd.print (nb) ;
}

et ainsi:

void affiche(uint8_t ligne, uint8_t colonne, unsigned long nb)
{
 if (nb<10) affiche1(ligne, colonne+4, nb);
 else  if (nb<100) affiche1(ligne, colonne+3, nb);
 else  if (nb<100) affiche1(ligne, colonne+2, nb);
 else  if (nb<100) affiche1(ligne, colonne+1, nb);
 else  if (nb<100) affiche1(ligne, colonne, nb);
}

attention 1000 est un entier 16 bits. Pour avoir un unsigned long il faut mettre UL derrière, sinon le nombre est tronqué
x<10000000 // non
x<10000000UL // oui


Pour afficher BQ, kBQ ou MBq, au lieu de tout répéter, on peut faire

if (x>10000000000UL) then 
  {
    unite=F("GBq");
    x/=1000000000UL
  }
else if (x>10000000UL) then 
  {
    unite=F("GBq");
    x/=1000000UL
  }
else if (x>10000UL) then 
  {
    unite=F("GBq");
    x/=1000UL
  }
else unite=F("Bq");

et afficher les nombres x qui sont entre 1 et 10000 avec comme unité "unite"


Il en est de même pour l'autre unité de mesure. on peut faire comme au dessus utiliser deux variables, l'une prefixe qui contient 0, 1, 2, 3, ou 4 et unite qui contient "Bq" ou "Sv" puis:

if (unite=="Bq")
  case (prefixe)
  {
    //0: unite="Bq";
    //    break
    1: unite="kBq";
        break
    2: unite="MBq";
        break
    3: unite="GBq";
        break
  }
else // (unite=="Sv")
  case (prefixe)
  {
    0: unite="nSv";
        break
    1: unite="µSv";
        break
    2: unite="mSv";
        break
    //3: unite="Sv";
    //    break
    4: unite="kSv";
        break
  }

Ce sont des idées. Rien n'est testé, et je n'ai pas défini les variables

hello
je regarde ton code et je voie que tu as prévu des valeurs énormes

chez moi le µ sature à 136.9KHz ==>136900 impulsions /seconde, nous sommes loin du méga prévu dans ton code

attention, j'ai changé l'adresse du lcd, la vitesse de la liason serie et l'init lcd

geiger.zip (1.78 KB)

je regarde ton code et je voie que tu à prévu des valeurs énormes

Les valeurs proviennent du post #8


chez moi le µ sature à 136.9KHz ==>136900 impulsions /seconde

Attention 140kHz et 140.000 impulsions/s ce n'est pas pareil. Les impulsions sont aléatoires et elles peuvent être séparées
par des temps beaucoup plus court que 1/140.000 s.


Et le rapport entre @g_u_i_l_la_u_me et @dfgh?


Attention aussi pour les fichiers joints. Pour le zip, il faut le télécharger, le dézipper, regarder dedans, l'effacer avec éventuellement le répertoire... Et je ne parle pas de le lire sur un téléphone portable.

Si tu veux avoir un maximum de visibilité, c'est à éviter. Le post indique 195 vues, le zip 0 (d'accord il est plus récent!)

hello Vileroi

en fait mon texte s'adressait à guillaume.
désolé, j'aurais du mettre "@"

pour le code en zip, il est en plusieurs onglets et ne peut être placé entre les balises "code" habituelles.

pour tester le code j'ai appliqué une fréquence, 140 KHz, c'est déjà beaucoup.

oui, jles pulses peuvent être aléatoires, mais il faut bien fixer une base de temps, sinon, cela n'a pas de sens .

ceci dit, je ne peux étoffer le débat, car je n'y connais rien en détection de radiations.

Et le rapport entre @g_u_i_l_la_u_me et @dfgh?

pas compris la question

Et le rapport entre @g_u_i_l_la_u_me et @dfgh?

J'ai cru que c'était la même personne...

pour le code en zip, il est en plusieurs onglets et ne peut être placé entre les balises "code" habituelles.

Mettre plutôt 4 balises code si cela tient; Ainsi on peut voir sans télécharger. Je l'ai vu faire souvent.

pour tester le code j'ai appliqué une fréquence, 140 KHz, c'est déjà beaucoup.

Je trouve cela lent! Je me demande si ce n'est pas dû à la gestion de attachInterrupt. Je ne connais pas bien cette utilisation, mais j'ai l'impression qu'en passant directement par les registres on doit y gagner. Je gère des pas à pas avec des interruptions et cela peut aller jusqu'à 7µs. Si il n'y a qu'un simple comptage, on doit pouvoir atteindre 5µs soit 200kHz

Merci pour toutes ces réponses ! :slight_smile:

Je vais tenter de comprendre les nouvelles portions de codage et les intégrer.

La source la plus puissante que j’ai pour le calibrage (et je ne souhaite pas avoir plus à la maison) donne environ 20 000 coups par minutes.

attention 1000 est un entier 16 bits. Pour avoir un unsigned long il faut mettre UL derrière, sinon le nombre est tronqué

Tronqué dans la mémoire ? Je ne comprends pas car j’ai testé le programme et il reprend à 0 à la la fin du unsigned long soit un peut plus de 4.2G. C’est à quel endroit que c’est troqué ?

Les Bq c'est pas désintégrations par secondes?

Effectivement, au début, j’étais partit pour ça, mais j’ai changé la programmation en cour de route. Il faudra que change Bq par d (désintégration), en plus je gagne un caractère sur le LCD :slight_smile:

Au lieu de
si x<10 ....;
on peut faire
si x<10 ....;
Cela fait moins de tests

Merci, je vais ajouter les else.

chez moi le µ sature à 136.9KHz ==>136900 impulsions /seconde, nous sommes loin du méga prévu dans ton code

La variable X est un compteur d’impulsion total, du coup si je ne me suis pas trompé (le programme fonctionne jusqu’à attendre 4.2G dans X) ça doit fonctionner :slight_smile:
Niveau fréquence, je suis heureux d’apprendre que le code en l’état sature à 136 900 coups/s, c’est vraiment bien plus que la valeur max de mon capteur SBT10A (500 coups/s). Et en plus, si mon capteur pouvait monter aussi haut ça donnerait :
136900600.088=7228320µSv/h, soit 7mSv/h soit un endroit où l’on reçois par heure 7 fois la dose naturelle annuelle.
Et pour les doses plus hautes il y a le capteur SI3GB qui sature à 3Sv/h, ce qui donnerait s’il pouvait monter aussi haut :
136900600.48=3.9Sv/h soit la dose létale en une heure (sans compteur que sans blindage l’électronique lâchera avant).

Je ne sais pas si tu as vue, mais quand j’ai fait cette partie du code, je me suis laissé emporter jusqu’au G avant de désactiver cette partie-là ;p

Et le rapport entre @g_u_i_l_la_u_me et @dfgh?

Aucun, je suis un petit nouveau :slight_smile:

Le choix de la fonction interruption est justement dans le but d’accélérer le programme et de ne pas louper trop de coups. Si j’ai bien compris, en théorie je devrais avoir un comptage au plus toute les 8µs soit environs ce que tu as trouvé (7.3µs).

En autotest, avec une boucle de simulation dans le code et sans fonction d’interruption, la vitesse du programme est de 31ms/coups.

Mais je suis débutant en programmation et je me trompe peut-être totalement :stuck_out_tongue:

C'est à quel endroit que c'est troqué ?

Pas dans le comptage, mais dans:
if ( (x >= 10000) && (x < 10000000) )
if ( (x >= 10000000) && (x < 10000000000) )
a = x / 1000000 ;

Le choix de la fonction interruption est justement dans le but d'accélérer le programme et de ne pas louper trop de coups. Si j'ai bien compris, en théorie je devrais avoir un comptage au plus toute les 8µs soit environs ce que tu as trouvé (7.3µs).

Un programme d'interruption qui incrémente un long c'est au moins 4,25µs. C'est le temps si on utilise un timer, mis dans le cas d'attach interrupt, je suppose qu'Arduino doit faire le tri en début de routine pour aiguiller sur la bonne fonction car l'interruption est pour plusieurs broches. Dans ton cas, cela ne servirait à rien si 8µs mini suffit.

En autotest, avec une boucle de simulation dans le code et sans fonction d'interruption, la vitesse du programme est de 31ms/coups.

tout à fait possible car la boucle est plus longue et les fonction digitalRead et digitalWrite sont assez longues. Il faut voir le code, et on peut y gagner.

Si tu utilises digitalRead et digitalWrite, en les remplaçant par digitalReadFast et digitalWriteFast de la bibliothèque digitalReadFast.h, on peut gagner du temps.

La boucle de simulation va prendre du temps, l'affichage énormément (Serial.print), surtout si tu est resté à 9600 bauds. En interruption, la limite du temps c'est un programme qui ne fait qu'incrémenter un long. C'est un peu comme combien tu peux casser d’œufs à la minute si tu ne fait que ça et si en plus tu doit faire le gâteau?

le moment où on se dit "la fonction digitalWrite est peut être longue" il faut passer en code registre.

je fais bcp ça en ce moment sur ma nano, 33IOT et 33BLE.
si tu me passes le modèle de la carte que tu utilises, je peux dégoter la formule qui va bien.

l'idée est d'aller lire la partie du registre qui est le reflet direct de l'état des Pin. sur arduino , c'est une seule opération du microprocesseur, alors ça va vite.

sans aller raconter ma vie, je fais des boucles de com (rapide) uniquement avec du code registre plutôt que par interruption, avec lesquelles j ai encore du mal.

Sans trop s'embêter, il suffit de passer par la bibliothèque digitalWriteFast.h à condition qe la broche soit une constante. Sinon, il faut faire son code soi-même.

sans aller raconter ma vie, je fais des boucles de com (rapide) uniquement avec du code registre plutôt que par interruption, avec lesquelles j ai encore du mal.

Le mieux est les registres ET l'interruoption

hello
veux tu tester
Version avec interruption et registres, de 136KHz, on passe à 250KHz
attention changes l'adresse du LCD et la vitesse du moniteur

//pour 328P UNO, NANO
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); //27 set the LCD address to 0x27 for a 16 chars and 2 line display
volatile unsigned long pulse=0;
ISR(INT0_vect){pulse++;}

unsigned long x = 1; // Bq
unsigned int a = 0 ; // clode de x pour factorisation k M G dans total CPM
unsigned int b = 0 ; // clode de x pour factorisation k M G dans total Sv/h   ; int pour suprimer les chiffres apres la virgules
float c = 0.88 ; // 0.88 facteur de convertion affichage nano Sv/h, etalonage SBT10-A 220cpm vs radex 0.25µSv/h,
unsigned long chrono=0;
void setup()
{
  Serial.begin(1000000);
  //lcd.init();                      // initialize the lcd
  lcd.begin();
  lcd.backlight(); // retroéclérage
  lcd.clear ();
  chrono=millis();
  x=0;
EICRA = 0b00000011; // flanc montant
EIMSK = 0b00000001; // sur INT0
DDRD  = 0b00000010; // PD2 en entrée (sortie=1  et entrée =0) PD1 est TX
PORTD = 0b00000000; // pas de pullup sur port D (1=pullup si entrée)
sei();              // autorise les interruptions
}
void loop()
{
  if((millis()-chrono)>=1000)
  {
  Serial.print("x............");Serial.println(x);
  x=pulse;
  BQ();
  SV();
  chrono=millis();
  pulse=0; 
  }
}
// µµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµ
void BQ()
{
  lcd.setCursor(0, 3); lcd.print (F("TT      ")) ;
  if (x >= 10000000)  
  {
    a = x / 1000000 ;
    curseur(a,0);
    lcd.print (a) ; lcd.setCursor (7, 3); lcd.print (F("MBq")) ;
  }
  else {
    if (x >= 10000)
    {
      a = x / 1000 ;
      curseur(a,0);
      lcd.print (a) ; lcd.setCursor (7, 3); lcd.print (F("kBq")) ; 
    }
    else {
      if (x > 0)  
      {
        curseur(x,0);
        lcd.print (x); lcd.setCursor (7, 3); lcd.print (F(" Bq")) ;
      }
    }
  }
}
// µµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµ
void SV()
{
  lcd.setCursor (13, 3) ; lcd.print (F("     "));
  if ((x * c) > 10000000)              //++++++ comptage Sv/h jusqu'à 10000uSv/h
  {
    b = x / 1000000 * c ;
    curseur(b,10);
    lcd.print (round(b));lcd.setCursor (17, 3); lcd.print (F("mSv")) ;
  }
  else {                               //++++++ comptage Sv/h jusqu'à 10 000 000uSv/h
    if ((x * c) > 10000) 
    {
      b = x / 1000 * c ;
      curseur(b,10);
      lcd.print (round(b));lcd.setCursor (17, 3); lcd.write(228);lcd.print (F("Sv")) ;
    }
    else {                             //++++++ comptage Sv/h jusqu'à 10000nSv/h  
      if ( (x * c ) > 0) 
      {
        x=x*c;
        curseur(x,10);
        lcd.print (round(x * c)) ;lcd.setCursor (17, 3); lcd.print (F("nSv")) ;
      }
    }
  }
}

  //float u = x ; //clonde de x pour camcule µSv/h
  //(x*c) ; //u clone de x, x entrée geiger cpm, c facteur de conversion
// µµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµ
void curseur(unsigned long cur,byte sv)//sv=0 si BQ et 10 si SV
{
  if (cur >= 1000) {
    lcd.setCursor(3+sv, 3);
  }
  else {
    if (cur >= 100) {
      lcd.setCursor(4+sv, 3);
    }
    else {
      if (cur >= 10) {
        lcd.setCursor(5+sv, 3);
      }
      else {
        lcd.setCursor(6+sv, 3);
      }
    }
  }
}
void curseur_sv(unsigned long cur)
{
  if (cur >= 1000) {
    lcd.setCursor(13, 3);
  }
  else {
    if (cur >= 100) {
      lcd.setCursor(14, 3);
    }
    else {
      if (cur >= 10) {
        lcd.setCursor(15, 3);
      }
      else {
        lcd.setCursor(16, 3);
      }
    }
  }
}