Compteur d'impulsions

Hello,

Dans le cadre de l'analyse de données en sortie d'un calculateur automobile je cherche à compter le nombre d'impulsions avec mon Arduino Uno.

J'ai simplifié au maximum la chose et simule actuellement les impulsions avec un simple bouton.
Signal tiré à la masse par défaut et +5V lorsque j'appuie.

J'utilise le timer1 et la broche D8 en entrée pour compter.

Je n'utilise pas d'interruption, je veux simplement qu'à chaque fois que j'appuie sur mon bouton, le compteur s'incrémente. Je lirai la valeur du compteur/le remettrai à 0 de manière régulière par la suite.

J'initialise avec ça :

  TCCR1A = 0b00000000;
  TCCR1B = 0b01000000;
  TCNT1 = 0x0000;

Je lis la valeur TCNT1 qui malheureusement dans mon cas reste bloquée à 0.

Est-ce une erreur de raisonnement ou simplement de code ?

Bonjour,

Pourquoi ne pas utiliser d’interruption ? C’est pourtant, à mon avis, la meilleure méthode ?

ça va générer énormément d'interruptions pour simplement compter des impulsions

Si tu as énormément d'impulsions, tu n'as aucune chance de les lire toutes si tu n'utilises pas d'interruption.
Et puis, c'est quoi "énormément" ?

Comme souvent, dès que je poste, je trouve la réponse par moi même :slight_smile:
C’était tout simple, mauvais paramétrage du registre de contrôle B.

J’étais parti sur CS10, CS11 et CS12 à 0 pour avoir : No clock source (Timer/Counter stopped).
Sous entendu que je pourrai envoyer des impulsions sur ICP1 (port D8) mais mauvaise interprétation de la doc de ma part.

TCCR1A = 0b00000000;
  TCCR1B = 0b01000111; //CS10, CS11, CS12 à 1 : External clock source on T1 pin. Clock on rising edge.
  TCNT1 = 0x0000;

T1 pin sur l’Arduino Uno correspond au port D5

Du coup, je compte mes impulsions sans aucune interruptions :wink:

C'est possible de voir la totalité de ton code ?

Le voilà.
Rien d’extraordinaire pour l’instant :wink:

#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <MsTimer2.h>

SoftwareSerial mySerial(3,2); // Port série pour LCD : pin 2 = TX, pin 3 = RX (non utilisé)

int rpm;
int rpmcount;
char rpmstring[5];

int brakePin = 6;
bool brake = 0;

int throttlePin = 1;
int throttle;
char throttlestring[5];

int rpmPin= 5;

const int chipSelect = 7; // CS : port 7, /!\ modif PCB Sparkfun
char filename[10];

unsigned int tcnt = 0;
char tcntstring[6];

void setup()
{
  /*
   * Initialisation variables locales
   */
  int filenameNum = 1;
  char filenameBase[] = "log";
  char filenameExt[] = ".txt";
  
  mySerial.begin(9600); // Init port série 9600 bauds
  delay(500); // Temporisation pour démarrage LCD
  pinMode(4, OUTPUT); // Sortie LED controle
  pinMode(brakePin, INPUT);
  pinMode(throttlePin, INPUT);
  pinMode(rpmPin, INPUT);
  digitalWrite(rpmPin, 0);   
  
  // initialize timer1 
  noInterrupts();
  TCCR1A = 0b00000000;  // Doc p.131
  TCCR1B = 0b01000111;
  TCNT1 = 0x0000; // Compteur à 0
  interrupts();

  // initialize timer2
  MsTimer2::set(1, isrFunction); // Timer2 : Interruption toutes les 1ms
  MsTimer2::start();
  
  mySerial.write(254); // Déplacement curseur
  mySerial.write(128); // Première ligne
  mySerial.write("                "); // Clear
  mySerial.write("                ");
  mySerial.write("SD:");

  /*
   * Test présence carte SD
   */
  if (!SD.begin(chipSelect)) {
    mySerial.write("FAILED");
    delay(1000);
    return;
  }
  mySerial.write("OK");
  mySerial.write(254); // Déplacement curseur
  mySerial.write(192); // 2ème ligne
  mySerial.write("FILE:");

  /*
   * Génération du nom du fichier
   */
  sprintf(filename,"%s%i%s", filenameBase, filenameNum, filenameExt); // Génération nom du fichier
  while(SD.exists(filename)) {
    filenameNum++;
    sprintf(filename,"%s%i%s", filenameBase, filenameNum, filenameExt); // Génération nom du fichier (on incrémente si le fichier existe déjà)
  }

  /*
   * Ouverture du fichier sur la carte SD
   */
  File dataFile = SD.open(filename, FILE_WRITE);
  if (dataFile) {
    mySerial.write(filename);
    dataFile.println("plop");
    dataFile.close();
  } else {
    mySerial.write("FAILED");
  }
  delay(1000);
}

void isrFunction()
{
  digitalWrite( 4, digitalRead( 4 ) ^ 1 ); // Toggle LED
  rpm = random(1000);
  brake = digitalRead(brakePin);
  throttle = analogRead(throttlePin);
}

void loop()
{
  sprintf(rpmstring,"%4d", rpm);
  sprintf(throttlestring,"%4d", throttle);
  tcnt = TCNT1;
  sprintf(tcntstring,"%7d", tcnt);
    
  mySerial.write(254); // move cursor to beginning of first line
  mySerial.write(128);
  mySerial.write("                "); // clear display
  mySerial.write("                ");
  mySerial.write(254); // move cursor to beginning of first line
  mySerial.write(128); 
  mySerial.write("RPM:");
  mySerial.write(254); 
  mySerial.write(192);
  mySerial.write("FILE:");
  mySerial.write(254); 
  mySerial.write(132);
  mySerial.write(tcntstring); //rpmstring
  mySerial.write(254); 
  mySerial.write(198);
  mySerial.write(throttlestring);
  mySerial.write(254); // move cursor to beginning of first line
  mySerial.write(138);
  if(brake == HIGH) {
    mySerial.write("BRK");
  }
  delay(100);
}

A noter que je récupère les signaux "bruts" du calculateur et non via la prise diagnostic OBD.

Du coup ce sont des signaux carrés à fréquence variable ou des signaux analogiques (tension variable) mais pas de protocole de communication spécifique comme certains l'ont déjà (bien) fait.

quichedood:
Du coup, je compte mes impulsions sans aucune interruptions :wink:

Et là, tu fais quoi, d'après toi ?

  // initialize timer2
  MsTimer2::set(1, isrFunction); // Timer2 : Interruption toutes les 1ms
  MsTimer2::start();

Franchement, je comprends pas pourquoi tu t'évertues à ne pas utiliser les interruptions sur entrée externe.

3Sigma:
Franchement, je comprends pas pourquoi tu t'évertues à ne pas utiliser les interruptions sur entrée externe.

Quand tu veux juste compter des fronts, ce serait dommage d'utiliser des interruptions, alors que tout est là en hardware...

Pour le nombre d'impulsions, ça varie de 40 à 100 par tour de vilebrequin suivant le moteur (essence, diésel...).

Après, comme on ne sait pas ce qu'il veut en faire, je dirais qu'il a résolu son problème :wink:

Sur le timer2, oui j'ai une interruption par milliseconde, c'est volontaire et c'est grâce à elle que je vais baser mes différents calculs.

Après si je peux éviter au prix d'un changement de configuration de registre plus d'une centaine d'interruptions/seconde autant en profiter et optimiser le code ... surtout sur ce genre de µproc.

Pour ma part, problème résolu.

Superb use of the timer in the registers