Go Down

Topic: Commande automatique de groupe électrogène - machine à états et autres questions (Read 22025 times) previous topic - next topic

bricofoy

-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

bricofoy

Bon alors voila, pour détecter la rotation du moteur, j'ai rajouté un capteur de proximité qui compte les dents du ventilateur du moteur.

le nouveau scema de la carte V3.0 est le suivant :
http://sourceforge.net/p/groupe/code/ci/capteur_rota/tree/kicad/groupe2/groupe2.pdf?format=raw

J'ai connecté ce capteur sur l'entrée INT1 (pin D03), ma fonction associée à l'interruption mesure la période entre plusieurs tops et compte ces tops. Ensuite j'ai une fonction qui est appelée dans la boucle principale, qui calcule la vitesse de rotation du moteur à partir de cette période et du nombre de tops comptés.

Code: [Select]

unsigned int rpm_moteur; //vitesse de rotation moteur.

//variables utilisees en interruption (volatile = stockees en RAM)
volatile unsigned int rpm_cpt;                     //compteur de passage en interruption. Pour savoir cb de périodes sont utilisées pour le calcul de F
volatile unsigned long rpm_periode;                //periode des implulsion du capteur de rotation
volatile unsigned long rpm_tprecedent,rpm_tcourant;//temps utilisés pour calculer la période

void setup()
{
(...)
attachInterrupt(1, comptetour, RISING); //entree rotation moteur sur INT1
(...)
}

void calcule_rpm() {
  //calcul de la vitesse de rotation du moteur.
 
  //on calcule la fréquence avec 1*60*1000/période car la période est en ms (*1000), et que l'on veut la fréquence en tr/min et non en Hz ou tr/s (*60)
  //on divise ensuite le total par le nombre de dents comptées par le capteur sur 1 tour moteur
  //la periode est une moyenne des rpm_cpt periodes mesurees en interruption avant passage par ici
 
  //Serial.print(rpm_cpt);
  //Serial.println(" "); 
  if (rpm_cpt) {
    rpm_moteur = (unsigned int)(60000/(rpm_periode/rpm_cpt))/nbr_dents_capteur_rota;
    rpm_cpt = 0; //remise à zero du compteur pour les prochaines mesures
    rpm_periode = 0; //idem pour la periode
  }
  else if (rpm_tcourant<(temps_courant-300))
rpm_moteur = 0; //si pas de nouvelle mesure pdt plus de 300ms, alors le moteur est à l'arret ou le capteur est HS
//300ms de période correspond à 22trs minutes si nbr_dents_capteur_rota=9
  //Serial.print(rpm_moteur);
  //Serial.print(" ");
 
}

void comptetour(void) {
  //passage ici en interruption à chaque top capteur de vitesse.
  //On stocke juste la somme des période des impulsions, et un compteur du nombre de périodes additionnées 
  rpm_tprecedent = rpm_tcourant;
  rpm_tcourant = millis();
  rpm_cpt++;
  rpm_periode += (rpm_tcourant-rpm_tprecedent); 
}


le code complet est ici : http://sourceforge.net/p/groupe/code/ci/31e71b1ae87b4828ae862ed18880018b4c217bed/tree/groupe.ino

Tout ça fonctionne très bien, du moins tant que le système est en veille (machine à état en état et_attente).

En revanche, dès que je demande un démarrage du moteur, on dirais que le passage en interruption ne se fait plus. Je passe bien dans la fonction de calcul de vitesse à chaque boucle, comme en attestent les serial.print que j'ai collé dedans, mais le nombre de tops comptés est toujours 0, quelle que soit la fréquence des impulsions en entrée, ce qui semble vouloir dire que je ne passe pas dans l'interruption.

Le pire, c'est que une fois la séquence de démarrage (ratée !) finie, quand la machine à état repasse en attente, ben ça remarche.... arghhhh !

Qu'est-ce qui peut me bloquer l'interruption ? J'avoue que je m'arrache les cheveux, je sent bien que ça doit être une connerie énorme, mais j'y suis depuis 3h et je trouve pas...
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

Artouste

#107
Jul 03, 2013, 07:22 pm Last Edit: Jul 03, 2013, 07:24 pm by Artouste Reason: 1

Bon alors voila, pour détecter la rotation du moteur, j'ai rajouté un capteur de proximité qui compte les dents du ventilateur du moteur.

...
Qu'est-ce qui peut me bloquer l'interruption ? J'avoue que je m'arrache les cheveux, je sent bien que ça doit être une connerie énorme, mais j'y suis depuis 3h et je trouve pas...

Bonjour bricofoy
je ne suis pas un specialiste des interruptions, mais j'ai joué avec il n'y a pas longtemps
voir ici
http://forum.arduino.cc/index.php?topic=165087.msg1236504#msg1236504

suggestion : une fois en marche ton code ne voit plus jamais de rising ? (trop rapide ?)
juste pour test ça donne quoi avec change au lieu de rising , "une dent et un creux" c'est 3 "change"

bricofoy

alors en fait, c'est plus merdique que ça ! là j'attaque l'entrée avec un signal carré à 100Hz, ce qui devrait me donner une valeur de rpm à environ 667 trs/min, et en fait j'ai une valeur qui oscille entre zéro et 416 avec de temps en temps des pics à 7000, enfin bref c'est totalement n'importe-quoi.

donc en fait la fonction de calcul ou ma fonction de mesure ne marchent pas.

trop rapide, non, certainement pas, grand maximum mon entrée sera à 500Hz ça ne devrait pas poser trop de soucis...
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

Artouste


alors en fait, c'est plus merdique que ça ! là j'attaque l'entrée avec un signal carré à 100Hz, ce qui devrait me donner une valeur de rpm à environ 667 trs/min, et en fait j'ai une valeur qui oscille entre zéro et 416 avec de temps en temps des pics à 7000, enfin bref c'est totalement n'importe-quoi.

donc en fait la fonction de calcul ou ma fonction de mesure ne marchent pas.

trop rapide, non, certainement pas, grand maximum mon entrée sera à 500Hz ça ne devrait pas poser trop de soucis...


ça depend du temps que tu consomme en phase d'interruption
pour ne rien louper j'ai du deriver le calcul et me contenter de renseigner simplement un tableau (voir code commenté)
mais ceci n'est peut etre pas exploitable dans tons cas 

B@tto

Est-ce que tu es sûr que c'est software ? Est-ce que le code que tu post ici est juste un résumé du code qui est réellement exécuté ou bien ce code ci te pose réellement problème ?
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

bricofoy

ben justement, j'ai essayé d'en faire le moins possible en interruption, regarde la fonction void comptetour() elle est réduite à sa plus simple expression..

bon en fait, le calcul marche, c'est mon entrée qui merdait (tension de sortie du gbf intégré au DSO Quad trop basse ! j'ai bricolé un ampli et ça marche, j'ai bien mes 666 trs/min (avec de temps en temps un pic à 740, donc il reste un bug que je n'ai absolument aucune espèce d'idée de la manière de la trouver ! )

par contre je retrouve mon comportement du début : dès que l'état de la machine change, je mesure 0 !! donc c'est que ça ne passe plus en interruption...
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

bricofoy


Est-ce que tu es sûr que c'est software ? Est-ce que le code que tu post ici est juste un résumé du code qui est réellement exécuté ou bien ce code ci te pose réellement problème ?


je croyais être sûr que c'était un soucis soft (en tout cas il y en a un : les pics à 740tr/min) mais à vrai dire je ne suis plus sûr de rien, là :/

le code est bien un résumé du code actuellement executé par l'atmega
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

bricofoy

ARGHHH en fait quand j'ai les relais qui s'activent, l'alim baisse avec la conso des bobines, et les créneaux en sortie du pont diviseur R37/R32 sont trop bas (3,08V crète) et l'atmega ne les détecte plus !! en remontant l'alim, ça fonctionne... Pourtant d'après la donc de l'atméga, il me semblait qu'un niveau haut était pris en compte à partir d'une tension bien plus faible que ça ??

le schéma est là : http://sourceforge.net/p/groupe/code/ci/capteur_rota/tree/kicad/groupe2/groupe2.pdf?format=raw


Je vais modifier mon entrée, le pont diviseur foire, manifestement. Si d'ailleurs vous avez une idée à me suggérer ? par exemple ne pas faire un pont diviseur mais limiter la tension d'entrée avec une zéner ?

Le capteur que j'utilise fonctionne en 12V, avec une sortie collecteur ouvert PNP, d'où ce pont diviseur pour ne pas cramer l'entrée de l'atmega avec des pulse en 12V
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

Artouste



Je vais modifier mon entrée, le pont diviseur foire, manifestement. Si d'ailleurs vous avez une idée à me suggérer ? par exemple ne pas faire un pont diviseur mais limiter la tension d'entrée avec une zéner ?

Le capteur que j'utilise fonctionne en 12V, avec une sortie collecteur ouvert PNP, d'où ce pont diviseur pour ne pas cramer l'entrée de l'atmega avec des pulse en 12V


J'avais demerdé un probleme du genre capricieux comme le tiens  Vin 12 ---> Vcommut 5V
si les temps de recouvrement sont acceptable , essaye un petit 78L05 comme regulateur du signal d'entrée , (ne pas oublier de tirer un peu dessus )
ce n'est pas à priori fait pour, mais si F° est faible ça peut etre une bonne solution "à pas cher"  8)

bricofoy



Bonjour bricofoy
je ne suis pas un specialiste des interruptions, mais j'ai joué avec il n'y a pas longtemps
voir ici
http://forum.arduino.cc/index.php?topic=165087.msg1236504#msg1236504

suggestion : une fois en marche ton code ne voit plus jamais de rising ? (trop rapide ?)
juste pour test ça donne quoi avec change au lieu de rising , "une dent et un creux" c'est 3 "change"


je vois que tu stockes les valeurs dans un tableau, au lieu de les additionner comme moi. C'est plus rapide ainsi ?

Dans mon cas, en faisant des print avec la valeur du compteur, je constate qu'elle est majoritairement à 1 et n'a jamais dépassé 3, donc finlement le reste du code (machine à état, entrées/sorties, liaison série) que je pensais assez lent s'execute en fait assez rapidement.

Je n'ai aucun idée en revanche de la manière de débugger mon erreur occasionelle avec le pic à 740 au lieu des 666 theoriques...
En fait la seule explication que je vois à cette erreur c'est un passage en interruption avant la fin du traitement de la fonction calcule_rpm(), auquel cas j'ai alors un calcul fait avec une valeur de compteur erronée car elle n'a pas eu le temps d'être remise à zéro.
Peut-être que je devrait faire un detachInterrupt() a l'entrée dans la fonction, et à nouveau attachInterrup() à sa sortie ? ainsi je risque de rater un ou deux pulse, mais au moins e calcul restera juste avec les suivants ?
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

Artouste


...

- je vois que tu stockes les valeurs dans un tableau, au lieu de les additionner comme moi. C'est plus rapide ainsi ?
...

- Peut-être que je devrait faire un detachInterrupt() a l'entrée dans la fonction, et à nouveau attachInterrup() à sa sortie ? ainsi je risque de rater un ou deux pulse, mais au moins e calcul restera juste avec les suivants ?

- Dans mon cas : je sais +/- quel est le temps d'amortissement (nombre de secteurs parcourus) pour tendre à Vitesse=0
c'etait dans le but d'une collecte statistique
c'est la methode d'acquisition la plus efficace que j'avais trouvé (tout ce qui est traité dans l'interrupt consomme du temps)

- comme je l'ai expliqué , je ne suis pas assez pointu sur ce domaine ,  mais ça semble une bonne voie pour "calibrer une fenetre de tir"  8)

B@tto


ARGHHH en fait quand j'ai les relais qui s'activent, l'alim baisse avec la conso des bobines, et les créneaux en sortie du pont diviseur R37/R32 sont trop bas (3,08V crète) et l'atmega ne les détecte plus !! en remontant l'alim, ça fonctionne... Pourtant d'après la donc de l'atmega, il me semblait qu'un niveau haut était pris en compte à partir d'une tension bien plus faible que ça ??


Apparemment la question est simple mais la réponse complexe : http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=109947&start=20


Je vais modifier mon entrée, le pont diviseur foire, manifestement. Si d'ailleurs vous avez une idée à me suggérer ? par exemple ne pas faire un pont diviseur mais limiter la tension d'entrée avec une zéner ?


Résitance + zener c'est le top : coût et mise en place identique à un pont diviseur mais sans les inconvénients. D'ailleurs on l'oublie parfois mais la zener n'est pas forcement obligatoire seule la résistance limitant le courant est nécessaire : http://www.atmel.com/images/doc2508.pdf
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

bricofoy

merci b@tto pour ces liens. j'avais déja trouvé ce matin l'AN atmel, mais l'autre est très instructif aussi...

en gros, c'est la merde :P

Je crois que je vais tenter la version sale à la sauce atmel : juste une R en série avec l'entrée, et laisser les diodes internes faire leur boulot.
En fait, j'avais voulu faire un pont diviseur pour m'assurer d'avoir un courant minimum dans mon entrée pour éviter un certain nombre de parasites, dans la mesure ou l'environnement du montage (groupe électrogène : bobines, relais, alternateur, fort courants, etc) est quand même EMF-gène au possible...
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

bricofoy

bon là le soucis de voltage en entrée est flagrant :

Code: [Select]
tps : 0:2 0:2 ubat=12.00 rpm=1333
tps : 0:2 0:2 ubat=12.00 rpm=1666
tps : 0:2 0:2 ubat=12.00 rpm=1333
tps : 0:2 0:2 ubat=12.00 rpm=1333
tps : 0:2 0:2 ubat=11.81 rpm=1333
tps : 0:2 0:2 ubat=11.69 rpm=1333
tps : 0:2 0:2 ubat=11.60 rpm=1666
tps : 0:2 0:2 ubat=11.52 rpm=0
tps : 0:2 0:2 ubat=11.42 rpm=0
tps : 0:2 0:2 ubat=11.42 rpm=0
tps : 0:2 0:2 ubat=11.42 rpm=0
tps : 0:2 0:2 ubat=11.42 rpm=0
tps : 0:2 0:2 ubat=11.42 rpm=0
tps : 0:2 0:2 ubat=11.71 rpm=1333
tps : 0:2 0:2 ubat=12.20 rpm=1666
tps : 0:2 0:2 ubat=12.47 rpm=1333
tps : 0:2 0:2 ubat=12.57 rpm=1666
tps : 0:2 0:2 ubat=12.63 rpm=1333
tps : 0:2 0:2 ubat=12.90 rpm=1333
tps : 0:2 0:2 ubat=12.06 rpm=1333
tps : 0:2 0:2 ubat=11.28 rpm=0
tps : 0:2 0:2 ubat=11.28 rpm=0
tps : 0:2 0:2 ubat=10.64 rpm=0
tps : 0:2 0:2 ubat=10.93 rpm=0
tps : 0:2 0:2 ubat=11.91 rpm=1333
tps : 0:2 0:2 ubat=12.45 rpm=1333
tps : 0:2 0:2 ubat=12.73 rpm=1333
tps : 0:2 0:2 ubat=12.84 rpm=1333
tps : 0:2 0:2 ubat=12.84 rpm=1333
tps : 0:2 0:2 ubat=12.84 rpm=1333
tps : 0:2 0:2 ubat=12.84 rpm=1333
tps : 0:2 0:2 ubat=12.84 rpm=1666


pour ce qui est des erreurs de mesure, je viens de me rendre compte d'un truc : à la fréquence de mes impulsions, la période n'est que de quelques ms. Il faut déjà que je fasse la mesure avec des µs, ça sera sans doute bien plus précis...
-tu savais que si tu passe le CD de windows à l'envers, tu entends une chanson satanique ?
-non, mais il y a pire : à l'endroit, ça l'installe !

Go Up