Arduino Forum

International => Français => Topic started by: inryjo on Feb 18, 2016, 04:04 pm

Title: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 18, 2016, 04:04 pm
Bonjour à tous,
Je galère un peu sur mon projet de tableau de bord moto avec le traitement des impulsions de ma vitesse de roue et des impulsons de l'allumage.
J'arrive à avoir soit l'un soit l'autre mais pas les 2 en même temps ou alors avec des affichages farfelus.
Il semblerait que ce soit un problème récurrent d'après mes multiples recherches sur le forum.
Vu les prises de tête successives de ceux qui ont essayé, j'envisage d'ajouter un arduino mini pro et le dédier à l'une des deux tâches pour renvoyer les données à mon arduino principal.
Dans ce cas-là conseillerez-vous de lui attribuer la lecture de la vitesse ou du régime moteur ?
Etant donné que dans mon loop principal j'ai 0.2 secondes de delay pour un attachinterrupt, il me semble plus approprié de le dédier au régime moteur, qui donnera forcément beaucoup plus d'impulsions dans ce laps de temps.
A moins que quelqu'un ait déjà essayé et réussi à faire sans...
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: dfgh on Feb 19, 2016, 09:47 am
hello
intéressant
quel est le régime maxi moteur et la fréquence maxi pour le capteur roue?
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 11:08 am
Salut,
Régime maxi environ 470 Hz (moteur 2 temps à 2 étincelles par tour).
Capteur roue maxi 16Hz.
Je n'ai encore pas testé en vrai.
J'utilise un bouton poussoir pour tester pour l'instant (et oui j'ai bien pensé à faire un front montant).
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: dfgh on Feb 19, 2016, 02:22 pm
hello
explique

470*60=28200 étincelles pour un bicylindres cela nous ramène à 14100 tr/mn

tu confirmes?

tu ne peux pas prélever les étincelles pour un seul cylindre?


pour la roue tu simules avec un BP, et tu as déjà des problème alors que tu n'arrive pas à la fréquence réelle de la roue!!!

ton afficheur, c'est quoi ?

Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: kamill on Feb 19, 2016, 02:36 pm
Bonjour,

Personnellement je ne comprends pas le problème et en particulier ça:
Quote
Etant donné que dans mon loop principal j'ai 0.2 secondes de delay pour un attachinterrupt
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 03:19 pm
hello
explique

470*60=28200 étincelles pour un bicylindres cela nous ramène à 14100 tr/mn

tu confirmes?

tu ne peux pas prélever les étincelles pour un seul cylindre?


pour la roue tu simules avec un BP, et tu as déjà des problème alors que tu n'arrive pas à la fréquence réelle de la roue!!!

ton afficheur, c'est quoi ?


Monocylindre qui prend 14000 rpm oui c'est une 80cc de course donc forcément ça prend un peu plus de tours qu'une moto classique...

Afficheur classique 2x16 utilisé partout.

Bonjour,

Personnellement je ne comprends pas le problème et en particulier ça:
Je précise que je suis débutant dans le domaine, d'après mes lectures, pour pouvoir faire deux choses à la fois il faut utiliser la fonction attachinterrupt. D'après ce que j'ai compris, on laisse un certain laps de temps pour lire le nombre d'impulsions, non ?
Dans tout les cas, avec ou sans ce delay, ça ne fonctionne pas et c'est un problème que d'autres ont rencontré, malgré les très nombreux exemples dispos sur le web, je n'ai encore rien trouvé avec une mesure de fréquence qui fonctionne pour 2 entrées simultanées.
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: kamill on Feb 19, 2016, 05:08 pm
Plutôt que de nous forcer à spéculer, si tu mettais ton code.
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: akuma8 on Feb 19, 2016, 05:24 pm
Bonjour,

Je rejoins _pepe_ sur ça :
A priori, pour mesurer et afficher plusieurs fréquences inférieures au kilohertz, les petits Arduinos sont déjà largement surdimensionnés. Si cela ne paraît pas possible, c'est sûrement qu'on doit mal s'y prendre.

Si l'on n'utilise pas de périphérique susceptible de bloquer durablement l'exécution du programme, alors les fréquences en jeu sont tellement faibles qu'on pourrait le faire sans recourir aux interruptions.
Les uC des Arduino sont très largement surdimensionnés pour ces types de fréquences (16MHz vs quelques KHz)

Personnellement dans mes différents projets où je lis 4 codeurs différents, je le fais sans utiliser les interruptions et tout se passe très bien.

C'est vrai que attachInterrupt() donne une facilité en programmation et demande moins de lignes de codes mais perso je pense qu'on maitrise plus ce qu'on fait en le codant soi-même.


Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 05:56 pm
Merci beaucoup pour vos réponses, pour être franc, je n'ai pas tout à fait le principe du attach interrupt (c'est pourtant pas faute d'avoir lu des cours dessus)...
Si par exemple on utilise (comme je l'ai déjà vu) les fonctions attachInterrupt()/detachInterrupt() pour traiter les rebonds des signaux d'entrée, je pense qu'on frise l'erreur de conception.
effectivement, ça frise l'erreur de conception  :)

voilà pour mon code:

Code: [Select]

#include <Wire.h>
#include "Sodaq_DS3231.h"
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>


#define ONE_WIRE_BUS 10


volatile byte rpmcount;
unsigned int rpm;
unsigned int rpmroue;
unsigned long timeold;
volatile byte kmhcount;
unsigned int kmh;
unsigned int kmh1;
unsigned long kmhtimeold;
const int potar = 0;
int valeurLue;
float tension;
float temp;
uint32_t old_ts;

LiquidCrystal lcd(12,11,9,8,7,6);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);


void LCDPrint();
 
void setup()
{
Serial.begin(115200);
while (!Serial);
lcd.begin(16,2);
sensors.begin();
Wire.begin();
rtc.begin();
attachInterrupt(1, rpm_pulse, FALLING);
attachInterrupt(0, kmh_pulse, FALLING);
digitalWrite(2,HIGH);/*pullup interne*/
digitalWrite(3,HIGH);/*pullup interne*/
}

void loop()
{
detachInterrupt(1);
rpm = (60*1000ul)/(millis() - timeold)*rpmcount;
timeold = millis();
rpmcount = 0;
attachInterrupt(1, rpm_pulse, FALLING);
Serial.print("Compte-tours:");
Serial.println(rpm);
delay(200); 

detachInterrupt(0);
kmh = (60*1000ul)/(millis() - kmhtimeold)*kmhcount;
kmh = kmh*0.0017*3600ul;
kmhtimeold = millis();
kmhcount = 0;
attachInterrupt(0, kmh_pulse, FALLING);
Serial.print("Vitesse");
Serial.println(kmh);
delay(200);

valeurLue = analogRead(potar);
tension = valeurLue * 5.0 / 1023;
Serial.print("Tension = ");
Serial.println(tension,2);

sensors.requestTemperatures();
float temp = sensors.getTempCByIndex(0);
Serial.print("Temperature de la sonde: ");
Serial.println(temp);


DateTime now = rtc.now(); //get the current date-time   
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.println();

LCDPrint();
}

void rpm_pulse()
{
  rpmcount++;
}

void kmh_pulse()
{
  kmhcount++;
}

void LCDPrint()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(kmh);
lcd.setCursor(2,0);
lcd.print("kmh");
lcd.setCursor(0,1);
lcd.print(rpm);
lcd.setCursor(5,1);
lcd.print("RPM");
lcd.setCursor(11,0);
lcd.print(tension);
lcd.setCursor(15,0);
lcd.print("V");
lcd.setCursor(10,1);
float temp = sensors.getTempCByIndex(0);
lcd.print(temp,1);
lcd.setCursor(15,1);
lcd.print((char)223);
lcd.setCursor(5,0);
lcd.print("16");
lcd.setCursor(7,0);
lcd.print(":");
lcd.setCursor(8,0);
lcd.print("23");

return;
}
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: kamill on Feb 19, 2016, 06:01 pm
Pourquoi les detachInterrupt attachInterrupt dans la loop?
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: marcus_95 on Feb 19, 2016, 06:23 pm
Bonjour, a ta place j'utiliserais une interruption pour le RPM et la vitesse dans le loop, le LCD est très lent 1/2 seconde.
Le dallas temperature ralenti le programme.
Cdt.
Marcus.
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: marcus_95 on Feb 19, 2016, 06:32 pm
Va voir la: http://www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ArduinoInitiationEntreesOnOffOptoFourcheCompteTourTerminal
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 06:34 pm
Pourquoi les detachInterrupt attachInterrupt dans la loop?
parce que j'ai trouvé un programme de simple mesure rpm de ventilateur et que j'ai bêtement recopié :)

Je les retire tout simplement ?

J'imagine que les initiés doivent voir de nombreuses aberrations dans mon code...
Bonjour, a ta place j'utiliserais une interruption pour le RPM et la vitesse dans le loop, le LCD est très lent 1/2 seconde.
Le dallas temperature ralenti le programme.
Cdt.
Marcus.
Pour le dallas oui il ralentit le programme ça ne fait aucun doute (ça avait fait l'objet de l'un de mes autres topics). Pour la latence du lcd, on ne peut rien y faire, non ? en tout cas un refresh de vitesse et rpm tous les 0.5 sec maxi me va tres bien.
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: kamill on Feb 19, 2016, 06:37 pm
Oui, tu enlève simplement les attach/detach Interrupt dans la loop

Supprime aussi les delay(200), la loop est déjà assez longue
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: marcus_95 on Feb 19, 2016, 06:41 pm
pour les interruption un peut de lecture et très bien fait.
http://forum.arduino.cc/index.php?topic=100906.0
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 07:23 pm
Sans parler de refaire une conception adaptée à la situation, tu pourrais déjà tenter de corriger le fonctionnement actuel en modifiant le code du début de loop() comme suit :
Avec cette modif, j'obtiens toujours des résultats bizarres, c'est à dire que si je donne des impulsions à un rythme constant, ma vitesse va afficher un truc du genre 23 /43/64/97 kmh successivement.
(même chose pour le compte-tours)
Est-ce le reste du code qui interfère ?
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: kamill on Feb 19, 2016, 07:42 pm
Tu es sur de la fréquence de test impulsions? Tu les génère avec quoi?
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 19, 2016, 07:56 pm
Tu es sur de la fréquence de test impulsions? Tu les génère avec quoi?
bouton poussoir et je mets un métronome pour être sûr, je ne devrais pas avoir autant de variations !
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: rjnc38 on Feb 19, 2016, 08:47 pm
bouton poussoir et je mets un métronome pour être sûr, je ne devrais pas avoir autant de variations !
avec un bouton poussoir il faut au minimum un circuit anti-rebond entre l'inter et l'arduino
une autre solution si tu as un autre arduino tu lui fais généré un signal carre a fréquence variable
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 20, 2016, 11:32 am
avec un bouton poussoir il faut au minimum un circuit anti-rebond entre l'inter et l'arduino
une autre solution si tu as un autre arduino tu lui fais généré un signal carre a fréquence variable
Bonne idée, j'utilise maintenant la sortie pwm d'un raspberry pour tester les rpm sauf qu'en programmant 470Hz, j'obtiens 25600 RPM (avec des fluctuations) alors qu'en théorie je devrais avoir 28200 RPM, à quoi est-ce dû ?

Et comme tu as indiqué 16 Hz pour la fréquence maximale du capteur de roue, je crains qu'il ne renvoie qu'une seule impulsion par tour de roue. Ce n'est donc pas une mesure de fréquence instantanée qu'il convient de faire (comptage du nombre d'impulsions sur une période déterminée), mais une mesure de période (mesure du temps écoulé entre deux impulsions).
Merci beaucoup pour ces explications, je comprends bien mieux maintenant. Je vais donc voir comment modifier mon code. Pour toi, ça reste possible de compter le delta T entre chaque impulsion de roue et en même temps calculer la fréquence moteur ?
Title: Re: faire fonctionner 2 attach interrupt à la fois
Post by: inryjo on Feb 20, 2016, 05:01 pm
Tout-à-fait. Comme je l'ai indiqué, il s'agit de processus très lents comparés à la vitesse du microcontrôleur.

En revanche, il faut s'assurer qu'aucun traitement ne bloque le programme durablement. Il faut notamment veiller à traiter correctement les éventuels rebonds sur les entrées.

J'ai ajouté quelques lignes pour un anti rebond et changé la méthode de calcul des km/h. Ca m'a l'air de fonctionner.
Ou alors tu parlais d'un anti rebond physique, genre avec un condensateur ?
Par contre avec ces modifs, les fonctions noInterrupts/Interrupts dans mon loop ne risquent-elles pas d'affecter le interrupts des km/h ?
Autre chose, le compteur affiche la derniere vitesse enregistrée, comment faire en sorte qu'il se remette à 0 quand il n'a plus d'impulsions ?
Et aussi j'ai toujours le problème que ma vitesse moteur est légèrement erronnée, quand je mets mon PWM à par exemple 12000 RPM, j'ai 11400/11500.

En tout cas merci encore, j'ai pas mal avancé !

Code: [Select]

#include <Wire.h>
#include "Sodaq_DS3231.h"
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 10

volatile byte rpmcount;
unsigned int rpm;
unsigned int rpmroue;
unsigned long timeold;
volatile byte kmhcount;
unsigned int kmh;

unsigned long kmhtimeold;
const int potar = 0;
int valeurLue;
float tension;
float temp;
uint32_t old_ts;

long debouncing_time = 15; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;

float start, finished;
float elapsed, time;
float circMetric=1.7; // wheel circumference relative to sensor position (in meters)
float speedk ;
 
LiquidCrystal lcd(12,11,9,8,7,6);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void heure();
void LCDPrint();
 
void setup()
{
Serial.begin(115200);
while (!Serial);
lcd.begin(16,2);
sensors.begin();
Wire.begin();
rtc.begin();
start=millis();
attachInterrupt(1, rpm_pulse, FALLING);
attachInterrupt(0, debounceInterrupt, FALLING);
start=micros();
digitalWrite(2,HIGH);/*pullup interne*/
digitalWrite(3,HIGH);/*pullup interne*/
}

void loop()
{
noInterrupts(); // interdit les interruptions / la modification des compteurs
uint32_t t_now = micros();  // lit l'heure
// lit et réinitialise les compteurs
uint32_t rpmc = rpmcount;
rpmcount = 0;
interrupts(); // autorise les interruptions / la modification des compteurs
uint32_t delta_t = t_now-timeold; // calcule la durée du comptage effectué
timeold = t_now; // mémorise l'heure de départ du nouveau comptage
  // calcule et affiche les résultats
  Serial.print("Compte-tours:");
  Serial.println(rpmc*6.0e7/delta_t);
  rpm = rpmc*6.0e7/delta_t;
  delay(400); 
 
Serial.print("Vitesse");
Serial.println(int(speedk)); 

valeurLue = analogRead(potar);
tension = valeurLue * 5.0 / 1023;
Serial.print("Tension = ");
Serial.println(tension,2);

sensors.requestTemperatures();
float temp = sensors.getTempCByIndex(0);
Serial.print("Temperature de la sonde: ");
Serial.println(temp);


DateTime now = rtc.now(); //get the current date-time   
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.println();

LCDPrint();
}

void debounceInterrupt() {
   if((long)(micros() - last_micros) >= debouncing_time * 1000) {
     kmh_pulse();
     last_micros = micros();
   }
 }

void rpm_pulse()
{
  rpmcount++;
}

void kmh_pulse()
{
  elapsed=millis()-start;
  start=millis();
  speedk=(3600*circMetric)/elapsed; // km/h
}

void LCDPrint()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(speedk,1);
lcd.setCursor(2,0);
lcd.print("kmh");
lcd.setCursor(0,1);
lcd.print(rpm);
lcd.setCursor(5,1);
lcd.print("RPM");
lcd.setCursor(11,0);
lcd.print(tension);
lcd.setCursor(15,0);
lcd.print("V");
lcd.setCursor(15,1);
lcd.print((char)223);
lcd.setCursor(5,0);
lcd.print("16");
lcd.setCursor(7,0);
lcd.print(":");
lcd.setCursor(8,0);
lcd.print("23");
lcd.setCursor(13,1);
float temp = sensors.getTempCByIndex(0);
lcd.print(temp,0);
return;
}