Asservissement en courant avec capteur ACS712 - 30A

Nico49

Member
Bonjour,

je souhaiterais réaliser un asservissement en courant (d'une Drycell pour ceux qui connaissent...) à l'aide d'un capteur de courant à effet Hall réf : ACS712 (30 Amp).
J'ai déjà tenté de faire des mesures de courant grâce à ce capteur mais les résultats me paraissent erronés et non proportionnels aux courants mesurés.

J'utilise un Picaxe 20M2.
Le capteur de courant (ACS712) peut mesurer des courants de -30A à +30A.
La plage de tensions correspondante est : +2,5V pour -30A à +4,5V pour +30A et linéaire sur toute la plage (3,5V à 0A)
Sa sensibilité est de 100mV/A.

Je bute un peu sur la conversion à faire entre la valeur de la tension image du courant transmise par le capteur et la valeur qui sera à afficher sur mon LCD.

Le but final étant de commander la charge (ici une Drycell) via un transistor MOSFET et une sortie PWM du Picaxe et avoir un courant constant fixé à 10A environ en jouant sur le rapport cyclique de la sortie PWM.

Je souhaite afficher la valeur du courant sur 3 caractères avec un chiffre après la virgule (00,0A)

J'ai déjà un programme fonctionnel m'indiquant plusieurs infos de capteurs sur l'état de mon système (température, niveau d'eau dans le réservoir, détection rotation moteur...)

Voilà, si vous avez besoin d'infos supplémentaires, je suis à votre écoute !

Merci par avance pour votre aide.

Nico
 

PieM

Senior Member
Bonjour,

Si c'est un ACS712 - 30A, sa sensibilité n'est pas 100mV/A mais 66mV/A.
Le 0 est obtenu pour Vcc/2 donc 2.5V si Vcc est de 5V. Et 30A vont correspondre à 2.5V +/- 1.98V soit une amplitude de 0.5V à 4.5V
donc avec un readadc10, 0 --> 512 points
5V correspondent à 1024 pts
1 pt du readadc10 va correspondre à 5000/1024 en mV ou 5000/1024/66 en A de courant

Donc si x est la valeur lue avec readadc10:
faire x = x-512 changement d'origine
puis A = x * 50000 / 1024 / 66 avec A en 0.1 A
soit A = x * 37/50

pensez à mettre un C de 0.1µF sur l'alim du ACS712, un C de 1nF sur son filtre , et éventuellement, un passe bas sur l'entrée ana. Un simple C de 1µF peut suffire.
 

Nico49

Member
Bonjour,

Si c'est un ACS712 - 30A, sa sensibilité n'est pas 100mV/A mais 66mV/A.
Le 0 est obtenu pour Vcc/2 donc 2.5V si Vcc est de 5V. Et 30A vont correspondre à 2.5V +/- 1.98V soit une amplitude de 0.5V à 4.5V
donc avec un readadc10, 0 --> 512 points
5V correspondent à 1024 pts
1 pt du readadc10 va correspondre à 5000/1024 en mV ou 5000/1024/66 en A de courant

Donc si x est la valeur lue avec readadc10:
faire x = x-512 changement d'origine
puis A = x * 50000 / 1024 / 66 avec A en 0.1 A
soit A = x * 37/50

pensez à mettre un C de 0.1µF sur l'alim du ACS712, un C de 1nF sur son filtre , et éventuellement, un passe bas sur l'entrée ana. Un simple C de 1µF peut suffire.
Bonjour PieM et merci d'avoir répondu.

La sensibilité donnée pour ce capteur était pourtant de 100mV/A...
(Mon capteur est déjà équipé des 2 capas car il est monté sur PCB)

Une variation de la tension d'alimentation peut donc modifier la valeur du courant affichée, c'est bien ça ?!
Il faut donc mesurer précisément la tension d'alim pour avoir une plus grande précision de la valeur du courant affichée ?

Je vais faire un essai avec votre conversion, merci pour l'explication claire !

Sinon, avez-vous un exemple de programme pouvant réaliser mon asservissement en utilisant une sortie PWM du Picaxe ?

Merci et bonne soirée.

Nico
 

BESQUEUT

Senior Member
Sinon, avez-vous un exemple de programme pouvant réaliser mon asservissement en utilisant une sortie PWM du Picaxe ?
Principe général :
Code:
[color=Blue]do
            readadc10 [/color][color=Black]Canal, X
            D[/color][color=DarkCyan]=[/color][color=Blue]([/color][color=Black]Fonction de X[/color][color=Blue])
            pwmduty [/color][color=Black]Broche, D[/color]
[color=Blue]loop[/color]
X comme dans le message #3 de PieM
 

PapyJP

Senior Member
Si c'est un ACS712 - 30A, sa sensibilité n'est pas 100mV/A mais 66mV
Je suppose que l' ADC a, comme référence, la tension d' alim ( 5V ) que j' appelle V1.
Si oui, La tension d' alim n' intervient pas dans la conversion.
Mais si elle chute à V2, la sensibilité du capteur tombe à ( 66mV/A )*( V2/V1 )
Me gourge ?
 
Last edited:

BESQUEUT

Senior Member
Je suppose que l' ADC a, comme référence, la tension d' alim ( 5V ) que j' appelle V1.
Si oui, La tension d' alim n' intervient pas dans la conversion.
Mais si elle chute à V2, la sensibilité du capteur tombe à ( 66mV/A )*( V2/V1 )
Me gourge ?
po vraiment. Mais je ne vois pas pourquoi la sensibilité changerait... La résolution est 37.5 / 512 A
 
Last edited:

PieM

Senior Member
po vraiment. Mais je ne vois pas pourquoi la sensibilité changerait... La résolution est 30 / 512 A
Non! l'amplitude 30 A ne correspond pas à Vcc/2 mais à 30* 0.066 soit 1.98V donc 405 pts si 5V en alim.
D'autre part, si Vcc change c'est le 0 qui va changer. Mais également la mesure puisque la valeur de l'echelon de mesure sera dans le rapport indiqué par Papy.
Mais la pente (sensibilité) elle ne varie pas ou pas beaucoup. De base elle est de 66mV/A mais peut être entre 64 et 68 mv/A selon la DS.
Donc selon la précision cherchée, il faudra peut être étalonner pour connaître sa valeur vraie.

C'est pour cela que dans la formule il faut entrer si possible la tension vraie d'alimentation du picaxe.
mon A= X-512 * 37/50 simplifié est donc à recalculer en fonction de la tension d'alim vraie.
Mais il ne faut pas oublier que la précision de la bête est donnée pour du ± 1.5% ! alors ...

Nico, la sensibilité de 100mV/A est pour le modèle 20A
il ne serait pas possible de mesurer +/-30A avec 100mV/A avec une alimentation de 5V du capteur!
 

PapyJP

Senior Member
po vraiment
' po vraiment ' = ' pas vraiment ' ou vous faites allusion à une célèbre BD ?

Je me suis mal exprimé: en effet la sensibilité du capteur ( supposé alimenté correctement ) ne change pas, elle est ce quelle est.
Mais vues après conversion AD, les mv / pas d' ADC changent.
En effet à 5V d' alim ( V1 ), [ 1024 pas = 5V ] soit 1 pas = V1 / 1024.
A V2<V1 [1024 pas = V2] soit 1 pas = V2 / 1024
Me gourge encore ?
 

BESQUEUT

Senior Member
À ma connaissance
512=0 À
1024=37,5 À
Quelle que soit la tension d'alim de l'acs & du picaxe, supposée commune.
 
Last edited:

PieM

Senior Member
À ma connaissance
512=0 À
1024=30 À
Quelle que soit la tension d'alim de l'acs & du picaxe, supposée commune.
Ben non !

0 correspond à 512 si les tensions ACS et Picaxe sont strictement identiques

pour 30A le ACS712-30 délivre 30* 66 mV soit 1.98 V quelles que soient les tensions d'alim.
Et 1.98V ça ne fait pas 512 points mesurés par l'adc mais 405 qui changent si l'alim varie comme le souligne Papy!
 

Nico49

Member
Exact PieM, pas possible de mesurer +/-30A avec 100mV/A avec une alim de 5V... le descriptif du capteur dans l'annonce est faux !

Oui PapyJP, c'est ce dont j'avais peur, que les pas ne soient plus les mêmes lorsque la tension d'alim change...
Je n'ai pas besoin d'une grande précision, une erreur de +/- 0,2A n'est pas trop grave.

En fait, il faut ajuster le "512" dans l'équation : A= X-512 * 37/50 pour recentrer le zéro ?


Merci Besqueut pour cet exemple.
Par contre, je ne pense pas pouvoir utiliser la boucle loop dans mon programme principale qui doit scanner l'état de plusieurs capteurs en permanence mais je peux peut-être intercaler le reste du programme ? :

readadc10 Canal, X
pwmduty Broche, D

Comment dois-je m'y prendre pour adapter mon rapport cyclique en fonction du courant mesuré et le réguler à 10A ?
 

Nico49

Member
C'est vrai, après réflexion, ce n'est pas possible d'avoir une sensibilité de 100mV/A pour +/-30A, le descriptif de l'annonce du capteur est faux...
 

Nico49

Member
Merci Besqueut pour l'exemple.

je ne crois pas pouvoir intercaler une boucle loop dans mon programme principal qui doit vérifier l'état de plusieurs capteurs en permanence.
Mais peut-être puis-je placer le reste du programme dans mon programme principale :

readadc10 Canal, X
pwmduty Broche, D

Comment dois-je m'y prendre pour ajuster le rapport cyclique en fonction du courant mesuré pour avoir un courant constant de 10A ?
 

PapyJP

Senior Member
En fait, il faut ajuster le "512" dans l'équation : A= X-512 * 37/50 pour recentrer le zéro ?
Ce serait une solution !
... encore faudrait-il connaitre les variations de la tension d' alim dans le temps et avec précision ... et là ... difficile ... voire impossible !
La vraie solution est d' avoir une alim 5V en béton ( insensible à tout: température, phases de la lune , j' en passe et des meilleures ... ).
 
Last edited:

BESQUEUT

Senior Member
Lire la notice !
Quand le courant est 0 A, l'acs sort vcc/2
Donc si le picaxe et le vcs ont la même alim, 0A correspond toujours à 512.

Par ailleurs, lire le paragraphe Ratiometry, page 9 de la notice.
La tension de sortie est proportionnelle à la tension d'alim.
Tous les tableaux sont néanmoins donnés pour une tension d'alim de 5V.

Donc je maintiens que si les alim sont communes entre l'acs et le Picaxe (et il faudrait avoir l'esprit spécialement tordu pour faire autrement)
512 correspond toujours à 0 A
1024 correspond toujours à 37,5 A
0 correspond toujours à 37,5 A dans l'autre sens

QUELLE QUE SOIT LA TENSION
d'alim dans les tolérances (entre 4,5 et 5,5 V en pratique)
 
Last edited:

BESQUEUT

Senior Member
Merci Besqueut pour l'exemple.

je ne crois pas pouvoir intercaler une boucle loop dans mon programme principal qui doit vérifier l'état de plusieurs capteurs en permanence.
Mais peut-être puis-je placer le reste du programme dans mon programme principale :

readadc10 Canal, X
pwmduty Broche, D

Comment dois-je m'y prendre pour ajuster le rapport cyclique en fonction du courant mesuré pour avoir un courant constant de 10A ?
2 solutions :
1) multitâche
2) une seule boucle qui lit tous les capteurs et en déduit les actions.

Votre problème est d'écrire
D=fonction de X...
Soit delta la différence courant mesuré - courant voulu
À chaque boucle ajouter à D une part signée de delta
Si courant trop fort,diminuer D
Et vace-verci
 
Last edited:

Nico49

Member
2 solutions :
1) multitâche
2) une seule boucle qui lit tous les capteurs et en déduit les actions.

Votre problème est d'écrire
D=fonction de X...
Soit delta la différence courant mesuré - courant voulu
À chaque boucle ajouter à D une part signée de delta
Si courant trop fort,diminuer D
Et vace-verci
Bonjour,

je croyais que le multitâche n'était pas possible avec les Picaxes (20M2) ?!
Je pense qu'une seule boucle peut faire l'affaire dans mon cas, je n'ai pas besoin de corriger le rapport cyclique avec une fréquence élevée.
 

BESQUEUT

Senior Member
Bonjour,
je croyais que le multitâche n'était pas possible avec les Picaxes (20M2) ?!
ben si justement : c'est la spécificité de la série M par rapport à la série X
Picaxes applicables et exemple de code
Je pense qu'une seule boucle peut faire l'affaire dans mon cas, je n'ai pas besoin de corriger le rapport cyclique avec une fréquence élevée.
Ok pour ça.
Si vous bannissez l'instruction PAUSE, vous pouvez espérer une réactivité entre la centi et la milli seconde, ce qui n'est déjà pas si mal.
Attention, en cas de court circuit, le Picaxe sera dans tous les cas trop lent pour éviter la fumée blanche...
Prévoir une protection indépendante pour ce cas de figure.
 
Last edited:

jojojo

Senior Member
Bonjour à tous.

J'ai déjà été confronté à un problème d'asservissement, géré par un picaxe (08m2).

Piem a rapidement abordé le filtrage PB, en entrée de lecture ADC.

Si le courant doit être constant (asservissement parfait), un filtrage par soft sera INDISPENSABLE. (Kalman ou assimilé).

Et, les picaxes ne sont absolument pas adaptés...

Georges.
 

Nico49

Member
ben si justement : c'est la spécificité de la série M par rapport à la série X
Multi-Tasking/

Ok pour ça.
Attention, en cas de court circuit, le Picaxe sera dans tous les cas trop lent pour éviter la fumée blanche...
Prévoir une protection indépendante pour ce cas de figure.
Ah ok, je ne savais pas ! On doit être limité dans le nombre de tâches effectuées en simultané je suppose ?

J'avais prévu une protection pour ce cas de figure mais merci quand même.

Autre chose, j'ai écrit le programme permettant de faire mes mesures de courant et cela à l'air de fonctionner, merci pour les calculs de conversion !
Par contre, la valeur affichée sur mon LCD n'est pas vraiment stable alors que le tension transmise par le capteur ACS l'est. Comment puis-je corriger cela ?

Aussi, lorsque qu'aucun courant n'est mesuré, le 0 n'est pas stable, j'aimerais au moins que la valeur mini soit 0.
J'ai mis un "MIN 0" après le calcul de conversion mais ça ne change rien...
 

jojojo

Senior Member
Par contre, la valeur affichée sur mon LCD n'est pas vraiment stable alors que le tension transmise par le capteur ACS l'est
C'est là que je mettrai l'oscillo. Je parie pour un beau yoyo ...
Voir #21.
 

BESQUEUT

Senior Member
Ah ok, je ne savais pas ! On doit être limité dans le nombre de tâches effectuées en simultané je suppose ?

J'avais prévu une protection pour ce cas de figure mais merci quand même.

Autre chose, j'ai écrit le programme permettant de faire mes mesures de courant et cela à l'air de fonctionner, merci pour les calculs de conversion !
Par contre, la valeur affichée sur mon LCD n'est pas vraiment stable alors que le tension transmise par le capteur ACS l'est. Comment puis-je corriger cela ?

Aussi, lorsque qu'aucun courant n'est mesuré, le 0 n'est pas stable, j'aimerais au moins que la valeur mini soit 0.
J'ai mis un "MIN 0" après le calcul de conversion mais ça ne change rien...
Merci de fournir :
- votre programme
- le schéma du montage
- des photos de la réalisation.
- valeurs retournées par READADC10 pour 0 A

Sur un 20M2 : 8 taches en parallèle (c'est déjà pas mal il me semble !)
picaxem2.pdf
 
Last edited:

PieM

Senior Member
Donc je maintiens que si les alim sont communes entre l'acs et le Picaxe (et il faudrait avoir l'esprit spécialement tordu pour faire autrement)
512 correspond toujours à 0 A
1024 correspond toujours à 33,5 A
Ben oui sauf qu'en #9 c'était 512=0 À et 1024=30 À et que 1024 correspondrait en fait à 2.5/ 0.066 soit 37.8A et non 33.5A
D'autre part, sur ce genre de mesure, le capteur est généralement placé près de l'organe de puissance mesuré, alors que l'électronique peut être dans un boitier indépendant. Donc des tensions d'alim peuvent être différentes, sans pour autant être tordu!

Nico said:
Par contre, la valeur affichée sur mon LCD n'est pas vraiment stable alors que le tension transmise par le capteur ACS l'est. Comment puis-je corriger cela ?
La seule solution est de filtrer l'entrée ana surtout si le capteur est positionné loin du Picaxe.
comment est la liaison entre les deux ?
Il faut savoir quel niveau de régulation vous souhaitez en terme de bande passante.
Si le process est à évolution lente, un filtrage passe bas très simple par soft peut être suffisant.

Concernant la précision elle ne pourra être meilleure que les 1,5% de 30A soit 0.45A

Si elle doit être la meilleure possible, en supposant des tension d'alimentation très stables, il n'y a qu'une solution, l'étalonnage autour de la valeur 10A.
A cette fin lire la valeur réelle de l'ana pour 0 A -> définition du 0 qui peut être #512
lire la valeur réelle pour 10A pour en déduire la pente réelle. qui peut être # de 66mV/A
Cela compensera une partie des erreurs, sauf la non linéarité qui restera à 7mV soit 0.1A
 

Nico49

Member
Bonjour à tous.

J'ai déjà été confronté à un problème d'asservissement, géré par un picaxe (08m2).

Piem a rapidement abordé le filtrage PB, en entrée de lecture ADC.

Si le courant doit être constant (asservissement parfait), un filtrage par soft sera INDISPENSABLE. (Kalman ou assimilé).

Et, les picaxes ne sont absolument pas adaptés...

Georges.
Comment fait-on du filtrage par soft ?
 

Nico49

Member
La seule solution est de filtrer l'entrée ana surtout si le capteur est positionné loin du Picaxe. comment est la liaison entre les deux ? Il faut savoir quel niveau de régulation vous souhaitez en terme de bande passante. Si le process est à évolution lente said:
Pour mes essais, le capteur est placé à environ 30 cm du Picaxe et est relié avec un câble blindé.
Pour la précision, si l'erreur est inférieur à 500mA, ça me va.

Pour la commande de ma Drycell, puis-je attaquer un MOSFET directement avec une sortie PWM du Picaxe ?

Sinon, pour éviter d'avoir des valeurs "inférieures" à zéro lorsque je ne mesure aucun courant, quelle commande je dois utiliser, un 'MIN 0' reste sans effet !
 

BESQUEUT

Senior Member
Têtu l'ami Piem...
Même avec 10m de câble d'alim, et vu la consommation de l'acs, ça m'étonnerait que les tensions diffèrent de plus d'une fraction de mV...
La résolution est 37.5/512 À
Soit 0.075 À
On peut faire mieux en ajoutant un ampli op
 

BESQUEUT

Senior Member
Pour mes essais, le capteur est placé à environ 30 cm du Picaxe et est relié avec un câble blindé.
Pour la précision, si l'erreur est inférieur à 500mA, ça me va.

Pour la commande de ma Drycell, puis-je attaquer un MOSFET directement avec une sortie PWM du Picaxe ?

Sinon, pour éviter d'avoir des valeurs "inférieures" à zéro lorsque je ne mesure aucun courant, quelle commande je dois utiliser, un 'MIN 0' reste sans effet !
Merci de publier votre code...
Par ailleurs, si l'objectif est un asservissement à 0 À de courant, je vous conseille plutôt une bonne pince coupante...
 

PieM

Senior Member
Têtu l'ami Piem...
Même avec 10m de câble d'alim, et vu la consommation de l'acs, ça m'étonnerait que les tensions diffèrent de plus d'une fraction de mV...
La résolution est 37.5/512 À
Soit 0.075 À
On peut faire mieux en ajoutant un ampli op
Je parlais bien sûr d'alimentation séparées ne sachant où est disposé le générateur de gaz, si c'est pour alimenter par exemple un moteur.
 

PieM

Senior Member
Pour la commande de ma Drycell, puis-je attaquer un MOSFET directement avec une sortie PWM du Picaxe ?

Sinon, pour éviter d'avoir des valeurs "inférieures" à zéro lorsque je ne mesure aucun courant, quelle commande je dois utiliser, un 'MIN 0' reste sans effet !
Oui on peut attaquer directement un MosFet à condition que ses caractéristiques Vgs soient de niveau logique 5V.
Mais attention que l'ACS va capter les variations PWM ! donc utiliser une fréquence élevée (> 100 kHz) et un sérieux filtrage.

Ce n'est pas MIN 0 qu'il faut faire, mais après la lecture ana écrire qu'elle n'est pas inférieure à 512 , donc MIN 512.

concernant le filtrage en soft:

initialiser avec

symbol coef = 5 ; par exemple
puis faire un readadc10 xx, w2

ensuite dans le corps du programme:

readadc10 xxx, w3
w2 = coef - 1 * w2 +w3 / coef ; w2 sera une valeur lissée de la lecture ana
si insuffisant augmenter la valeur de coef
 

Nico49

Member
Merci de publier votre code...
Par ailleurs, si l'objectif est un asservissement à 0 À de courant, je vous conseille plutôt une bonne pince coupante...

Voici mon code :
(il y a mes commentaires persos pour m'y retrouver, je débute...)

'***** PILOTAGE DRY CELL avec PICAXE 20M2 *****

'C.0 = OUT : Afficheur LCD 4x20 caractères
'C.1 = OUT : Arrêt / marche DRY CELL
'C.2 = IN : Mesure du courant consommé
'C.3 = IN : Interruption : Arrêt d'urgence
'C.4 = IN : Mesure de température d'eau sur DS18B20
'C.5 = IN : Détection rotation moteur
'C.6 = IN : Détection niveau bas dans le réservoir
'C.7 = OUT : Buzzer


#picaxe 20M2

symbol temp = b0
symbol moteur = pinC.5
symbol niveau = pinC.6
symbol courant = C.2
symbol buzzer = C.7
symbol drycell = C.1


init_LCD:
symbol LCD = C.0
symbol BD = N4800
pause 500
serout LCD,BD, (254,1)

dirsC = %00000011 'pinC.0 et pinC.1 en sorties, les autres en entrées


init_demo:
' b15 = 148
' serout LCD,BD, (254,192," INITIALISATION ") '(petite démo sur LCD le temps que le moteur prenne ses tours...)
' pause 1500

' for b2 = 1 to 20 'ligne de 20 caractères

' serout LCD,BD, (254,b15,4)
' pause 50
' serout LCD,BD, (254,b15,5)
' pause 50
' serout LCD,BD, (254,b15,6)
' pause 50
' serout LCD,BD, (254,b15,7)
' pause 50
' serout LCD,BD, (254,b15,8)
' pause 50
' b15 = b15 + 1

' next b2

' pause 1500
serout LCD,BD, (254,1)
' pause 1000


boucle_OFF:
call lecture_capteurs
pause 10

do
call niveau_eau
pause 10
call mesure_temp
pause 10
call rotation_moteur
pause 10
call mesure_courant
pause 10
loop while moteur=0 or temp<2 or temp>60 or b1>=128 'DRY CELL reste OFF tant que :
'moteur OFF ou
goto drycell_ON 'temp <2°C ou >=70°C ou <=0°C


boucle_ON:
setint %00001000,%00001000 'interruption quand pinC.3 = 1 (appui sur BP arrêt d'urgence)
call lecture_capteurs
pause 10

do
call niveau_eau
pause 10
call mesure_temp
pause 10
call rotation_moteur
pause 10
call mesure_courant
pause 10
loop while moteur=1 and temp>1 and temp<=60 'DRY CELL reste ON tant que :
'moteur ON et
goto drycell_OFF 'temp >1°C et <=60°C


'********** SOUS-PROGRAMMES **********
'--------------------------------------------------------------------------------------
lecture_capteurs:
serout LCD,BD, (254,1)

pause 10
serout LCD,BD, (254,128,1) 'Symbole niveau d'eau (1)
pause 10
serout LCD,BD, (254,140,3) 'Symbole température (3)
pause 10
serout LCD,BD, (254,148,"Moteur: Conso:")
pause 10
return

'--------------------------------------------------------------------------------------
niveau_eau: '(capteur à base d'ILS)
if niveau=0 then
serout LCD,BD, (254,130,"OK ")
endif

if niveau=1 then
serout LCD,BD, (254,130,"BAS")
pause 300
serout LCD,BD, (254,130," ")
endif
return

'--------------------------------------------------------------------------------------
mesure_temp: '(capteur de température DS18B20)
readtemp C.4,temp
b1=temp

if temp>=60 and temp<127 then 'temp >=60°C
serout LCD,BD, (254,142,">60",2,"!") 'afficher >60°C!
pause 300
serout LCD,BD, (254,142," ")
pause 10
endif

if temp>=0 and temp<60 then 'temp >=0°C et <10°C afficher sur 1 car
serout LCD,BD, (254,142,#temp,2," ")
endif

if temp>127 then 'temp <-1°C et >-9°C afficher sur 1 car
temp=temp-128
serout LCD,BD, (254,142,"-",#temp,2," ")
endif
return

'--------------------------------------------------------------------------------------
rotation_moteur: '(détection réalisée avec un relais 1 contact à fermeture branché aux bornes de l'alternateur)
if moteur=0 then
serout LCD,BD, (254,212,"STOP")
endif
pause 10

if moteur=1 then
serout LCD,BD, (254,212,"RUN ")
endif
pause 10
return

'--------------------------------------------------------------------------------------
mesure_courant: '(capteur de courant ADS712 - 30A)
readadc10 courant,w10

w10=w10-514
w11=w10*37/50 MIN 1

bintoascii w11,b11,b10,b9,b8,b7
serout LCD,BD, (254,227,b9,b8,",",b7,"A")

return

'--------------------------------------------------------------------------------------
drycell_ON:
pause 1000
serout LCD,BD, (254,1)
high buzzer 'Buzzer ON
pause 10
serout LCD,BD, (254,128,"********************")
pause 10
serout LCD,BD, (254,192," DRY CELL ")
pause 10
serout LCD,BD, (254,148," ON ")
pause 10
serout LCD,BD, (254,212,"********************")
pause 1000
low buzzer 'Buzzer OFF
high drycell 'DRY CELL ON '(allume une led pour le moment !)
goto boucle_ON

'--------------------------------------------------------------------------------------
drycell_OFF:
pause 1000
serout LCD,BD, (254,1)
high buzzer 'Buzzer ON
pause 10
serout LCD,BD, (254,128,"********************")
pause 10
serout LCD,BD, (254,192," DRY CELL ")
pause 10
serout LCD,BD, (254,148," OFF ")
pause 10
serout LCD,BD, (254,212,"********************")
pause 1000
low buzzer 'Buzzer OFF
low drycell 'DRY CELL OFF
goto boucle_OFF

'--------------------------------------------------------------------------------------
interrupt:
low drycell 'DRY CELL OFF
serout LCD,BD, (254,1)
high buzzer 'Buzzer ON
pause 10
serout LCD,BD, (254,128,"********************")
pause 10
serout LCD,BD, (254,192,"* ARRET D'URGENCE *")
pause 10
serout LCD,BD, (254,148,"* DRY CELL OFF *")
pause 10
serout LCD,BD, (254,212,"********************")
pause 1000
low buzzer 'Buzzer OFF
stop
 

PieM

Senior Member
Mettez le programme entre balises # (voir mode avancé en bas de page forum)
ça donne ça:

Code:
'***** PILOTAGE DRY CELL avec PICAXE 20M2 *****

'C.0 = OUT : Afficheur LCD 4x20 caractères
'C.1 = OUT : Arrêt / marche DRY CELL
'C.2 = IN : Mesure du courant consommé
'C.3 = IN : Interruption : Arrêt d'urgence
'C.4 = IN : Mesure de température d'eau sur DS18B20
'C.5 = IN : Détection rotation moteur
'C.6 = IN : Détection niveau bas dans le réservoir
'C.7 = OUT : Buzzer


#picaxe 20M2

    symbol temp    = b0
    symbol moteur    = pinC.5
    symbol niveau    = pinC.6
    symbol courant    = C.2
    symbol buzzer    = C.7
    symbol drycell    = C.1


init_LCD:
    symbol LCD = C.0
    symbol BD = N4800
    pause 500
    serout LCD,BD, (254,1)

dirsC = %00000011        'pinC.0 et pinC.1 en sorties, les autres en entrées


init_demo:
'    b15 = 148
'    serout LCD,BD, (254,192,"   INITIALISATION   ")      '(petite démo sur LCD le temps que le moteur prenne ses tours...)
'    pause 1500
    
'    for b2 = 1 to 20        'ligne de 20 caractères
    
'    serout LCD,BD, (254,b15,4)
'    pause 50
'    serout LCD,BD, (254,b15,5)
'    pause 50
'    serout LCD,BD, (254,b15,6)
'    pause 50
'    serout LCD,BD, (254,b15,7)
'    pause 50
'    serout LCD,BD, (254,b15,8)
'    pause 50
'    b15 = b15 + 1    
                
'    next b2

'    pause 1500
    serout LCD,BD, (254,1)
'    pause 1000
    

boucle_OFF:
    call lecture_capteurs
    pause 10
    
    do
    call niveau_eau
    pause 10
    call mesure_temp
    pause 10
    call rotation_moteur
    pause 10
    call mesure_courant
    pause 10
    loop while moteur=0 or temp<2 or temp>60 or b1>=128    'DRY CELL reste OFF tant que :
                                                        'moteur OFF ou
goto drycell_ON                                                'temp <2°C ou >=70°C ou <=0°C


boucle_ON:
    setint %00001000,%00001000                                             'interruption quand pinC.3 = 1 (appui sur BP arrêt d'urgence)
    call lecture_capteurs
    pause 10
    
    do
    call niveau_eau
    pause 10
    call mesure_temp
    pause 10
    call rotation_moteur
    pause 10
    call mesure_courant
    pause 10
    loop while moteur=1 and temp>1 and temp<=60      'DRY CELL reste ON tant que :
                                                  'moteur ON et
goto drycell_OFF                                   'temp >1°C et <=60°C


'********** SOUS-PROGRAMMES **********
'--------------------------------------------------------------------------------------
lecture_capteurs:
    serout LCD,BD, (254,1)
    
    pause 10
    serout LCD,BD, (254,128,1)                       'Symbole niveau d'eau (1)
    pause 10
    serout LCD,BD, (254,140,3)                       'Symbole température (3)
    pause 10
    serout LCD,BD, (254,148,"Moteur:       Conso:")
    pause 10
    return

'--------------------------------------------------------------------------------------
niveau_eau:                                               '(capteur à base d'ILS)
    if niveau=0 then
        serout LCD,BD, (254,130,"OK ")
        endif    
    
    if niveau=1 then
        serout LCD,BD, (254,130,"BAS")
        pause 300
        serout LCD,BD, (254,130,"   ")
        endif
    return

'--------------------------------------------------------------------------------------
mesure_temp:                                             '(capteur de température DS18B20)
    readtemp C.4,temp
    b1=temp

    if temp>=60 and temp<127 then                'temp >=60°C
        serout LCD,BD, (254,142,">60",2,"!")                  'afficher >60°C!
        pause 300
        serout LCD,BD, (254,142,"     ")
        pause 10
        endif
    
    if temp>=0 and temp<60 then                            'temp >=0°C et <10°C afficher sur 1 car
        serout LCD,BD, (254,142,#temp,2,"   ")
        endif

    if temp>127 then                                    'temp <-1°C et >-9°C afficher sur 1 car
    temp=temp-128
        serout LCD,BD, (254,142,"-",#temp,2,"  ")
        endif
    return

'--------------------------------------------------------------------------------------
rotation_moteur:                                            '(détection  réalisée avec un relais 1 contact à fermeture branché aux bornes de  l'alternateur)
    if moteur=0 then
        serout LCD,BD, (254,212,"STOP")
        endif    
    pause 10
    
    if moteur=1 then
        serout LCD,BD, (254,212,"RUN ")
        endif
    pause 10
    return

'--------------------------------------------------------------------------------------
mesure_courant:                                           '(capteur de courant ADS712 - 30A)
    readadc10 courant,w10

    w10=w10-514
    w11=w10*37/50 MIN 1
    
    bintoascii w11,b11,b10,b9,b8,b7
    serout LCD,BD, (254,227,b9,b8,",",b7,"A")

    return    

'--------------------------------------------------------------------------------------    
drycell_ON:
    pause 1000
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"      DRY CELL      ")
    pause 10
        serout LCD,BD, (254,148,"         ON         ")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    high drycell        'DRY CELL ON                                  '(allume une led pour le moment !)
    goto boucle_ON

'--------------------------------------------------------------------------------------
drycell_OFF:
    pause 1000
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"      DRY CELL      ")
    pause 10
        serout LCD,BD, (254,148,"         OFF        ")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    low drycell            'DRY CELL OFF
    goto boucle_OFF

'--------------------------------------------------------------------------------------
interrupt:
    low drycell            'DRY CELL OFF
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"* ARRET D'URGENCE  *")
    pause 10
        serout LCD,BD, (254,148,"*   DRY CELL OFF   *")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    stop
Rapidement :une remarque : l'interruption s'initialise en début de programme et le interrup: se termine par la même initialisation et un return.
Avant que l'ami Besqueut vous arrache un oeil :rolleyes: oubliez les goto ! (et il a raison... pas d'arracher les yeux)
donc une structure avec des gosub et des return.
 

Nico49

Member
Mettez le programme entre balises # (voir mode avancé en bas de page forum)
ça donne ça:

Code:
'***** PILOTAGE DRY CELL avec PICAXE 20M2 *****

'C.0 = OUT : Afficheur LCD 4x20 caractères
'C.1 = OUT : Arrêt / marche DRY CELL
'C.2 = IN : Mesure du courant consommé
'C.3 = IN : Interruption : Arrêt d'urgence
'C.4 = IN : Mesure de température d'eau sur DS18B20
'C.5 = IN : Détection rotation moteur
'C.6 = IN : Détection niveau bas dans le réservoir
'C.7 = OUT : Buzzer


#picaxe 20M2

    symbol temp    = b0
    symbol moteur    = pinC.5
    symbol niveau    = pinC.6
    symbol courant    = C.2
    symbol buzzer    = C.7
    symbol drycell    = C.1


init_LCD:
    symbol LCD = C.0
    symbol BD = N4800
    pause 500
    serout LCD,BD, (254,1)

dirsC = %00000011        'pinC.0 et pinC.1 en sorties, les autres en entrées


init_demo:
'    b15 = 148
'    serout LCD,BD, (254,192,"   INITIALISATION   ")      '(petite démo sur LCD le temps que le moteur prenne ses tours...)
'    pause 1500
    
'    for b2 = 1 to 20        'ligne de 20 caractères
    
'    serout LCD,BD, (254,b15,4)
'    pause 50
'    serout LCD,BD, (254,b15,5)
'    pause 50
'    serout LCD,BD, (254,b15,6)
'    pause 50
'    serout LCD,BD, (254,b15,7)
'    pause 50
'    serout LCD,BD, (254,b15,8)
'    pause 50
'    b15 = b15 + 1    
                
'    next b2

'    pause 1500
    serout LCD,BD, (254,1)
'    pause 1000
    

boucle_OFF:
    call lecture_capteurs
    pause 10
    
    do
    call niveau_eau
    pause 10
    call mesure_temp
    pause 10
    call rotation_moteur
    pause 10
    call mesure_courant
    pause 10
    loop while moteur=0 or temp<2 or temp>60 or b1>=128    'DRY CELL reste OFF tant que :
                                                        'moteur OFF ou
goto drycell_ON                                                'temp <2°C ou >=70°C ou <=0°C


boucle_ON:
    setint %00001000,%00001000                                             'interruption quand pinC.3 = 1 (appui sur BP arrêt d'urgence)
    call lecture_capteurs
    pause 10
    
    do
    call niveau_eau
    pause 10
    call mesure_temp
    pause 10
    call rotation_moteur
    pause 10
    call mesure_courant
    pause 10
    loop while moteur=1 and temp>1 and temp<=60      'DRY CELL reste ON tant que :
                                                  'moteur ON et
goto drycell_OFF                                   'temp >1°C et <=60°C


'********** SOUS-PROGRAMMES **********
'--------------------------------------------------------------------------------------
lecture_capteurs:
    serout LCD,BD, (254,1)
    
    pause 10
    serout LCD,BD, (254,128,1)                       'Symbole niveau d'eau (1)
    pause 10
    serout LCD,BD, (254,140,3)                       'Symbole température (3)
    pause 10
    serout LCD,BD, (254,148,"Moteur:       Conso:")
    pause 10
    return

'--------------------------------------------------------------------------------------
niveau_eau:                                               '(capteur à base d'ILS)
    if niveau=0 then
        serout LCD,BD, (254,130,"OK ")
        endif    
    
    if niveau=1 then
        serout LCD,BD, (254,130,"BAS")
        pause 300
        serout LCD,BD, (254,130,"   ")
        endif
    return

'--------------------------------------------------------------------------------------
mesure_temp:                                             '(capteur de température DS18B20)
    readtemp C.4,temp
    b1=temp

    if temp>=60 and temp<127 then                'temp >=60°C
        serout LCD,BD, (254,142,">60",2,"!")                  'afficher >60°C!
        pause 300
        serout LCD,BD, (254,142,"     ")
        pause 10
        endif
    
    if temp>=0 and temp<60 then                            'temp >=0°C et <10°C afficher sur 1 car
        serout LCD,BD, (254,142,#temp,2,"   ")
        endif

    if temp>127 then                                    'temp <-1°C et >-9°C afficher sur 1 car
    temp=temp-128
        serout LCD,BD, (254,142,"-",#temp,2,"  ")
        endif
    return

'--------------------------------------------------------------------------------------
rotation_moteur:                                            '(détection  réalisée avec un relais 1 contact à fermeture branché aux bornes de  l'alternateur)
    if moteur=0 then
        serout LCD,BD, (254,212,"STOP")
        endif    
    pause 10
    
    if moteur=1 then
        serout LCD,BD, (254,212,"RUN ")
        endif
    pause 10
    return

'--------------------------------------------------------------------------------------
mesure_courant:                                           '(capteur de courant ADS712 - 30A)
    readadc10 courant,w10

    w10=w10-514
    w11=w10*37/50 MIN 1
    
    bintoascii w11,b11,b10,b9,b8,b7
    serout LCD,BD, (254,227,b9,b8,",",b7,"A")

    return    

'--------------------------------------------------------------------------------------    
drycell_ON:
    pause 1000
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"      DRY CELL      ")
    pause 10
        serout LCD,BD, (254,148,"         ON         ")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    high drycell        'DRY CELL ON                                  '(allume une led pour le moment !)
    goto boucle_ON

'--------------------------------------------------------------------------------------
drycell_OFF:
    pause 1000
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"      DRY CELL      ")
    pause 10
        serout LCD,BD, (254,148,"         OFF        ")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    low drycell            'DRY CELL OFF
    goto boucle_OFF

'--------------------------------------------------------------------------------------
interrupt:
    low drycell            'DRY CELL OFF
    serout LCD,BD, (254,1)
    high buzzer            'Buzzer ON
    pause 10
        serout LCD,BD, (254,128,"********************")
    pause 10
        serout LCD,BD, (254,192,"* ARRET D'URGENCE  *")
    pause 10
        serout LCD,BD, (254,148,"*   DRY CELL OFF   *")
    pause 10
        serout LCD,BD, (254,212,"********************")
    pause 1000
    low buzzer            'Buzzer OFF
    stop
Rapidement :une remarque : l'interruption s'initialise en début de programme et le interrup: se termine par la même initialisation et un return.
Avant que l'ami Besqueut vous arrache un oeil :rolleyes: oubliez les goto ! (et il a raison... pas d'arracher les yeux)
donc une structure avec des gosub et des return.
Ben en fait c'est volontaire pour l'interruption car elle ne doit être active que dans cette partie du programme (que lorsque la Drycell est sous tension), pas d'intérêt de faire un arrêt d'urgence si la Drycell n'est pas alimentée, et pas de return car je veux que le système soit "immobilisé" tant qu'il n'y a pas eu de mise hors tension... (Enfin, c'est une ébauche de programme alors il va encore changer ;)) mais merci pour vos conseils avisés, je suis toujours preneur !

Quelle différence entre les "gosub / return" et les "goto" ?
 

PieM

Senior Member
Ben en fait c'est volontaire pour l'interruption car elle ne doit être active que dans cette partie du programme (que lorsque la Drycell est sous tension), pas d'intérêt de faire un arrêt d'urgence si la Drycell n'est pas alimentée, et pas de return car je veux que le système soit "immobilisé" tant qu'il n'y a pas eu de mise hors tension... (Enfin, c'est une ébauche de programme alors il va encore changer ;)) mais merci pour vos conseils avisés, je suis toujours preneur !

Quelle différence entre les "gosub / return" et les "goto" ?
OK pour l'interruption. Mais alors ça revient à une mise hors tension du système, suivie d'une éventuelle remise sous tension ?
Concernant le gosub, il appelle un sous programme et revient à l'instruction suivante.
Avec un goto, on va à un sous programme, qui lui même va sur un autre etc.. d'où des difficultés parfois à suivre un cheminement (type plat de nouilles) , et un risque évident de truc qui boucle et plante.
 

BESQUEUT

Senior Member
et un risque évident de truc qui boucle et plante.
sans parler du risque de passer par un RETURN avant d'avoir fait un GOSUB... (ce qui ne semble pas être le cas ici)

En fait, à la première lecture d'un programme, on ne va pas voir ce que fait un sous-programme. On suppose ce qu'il fait d'après son nom, et on continue à lire la suite. Ceci permet de "comprendre" le corps principal du programme sans rentrer dans les détails.

Dans le cas du GOTO on est obligé d'aller voir dans le détail de ce qui semble être une sorte de sous-programme pour découvrir tout à la fin qu'on revient au point de départ (ou pas...)
Du coup, on a perdu le déroulé du programme principal.


Sauf erreur de ma part, il est possible de remettre tout le bloc
drycell_ON
à sa place (c'est à dire à la place de l'instruction goto drycell_ON )
du coup, on peut également supprimer le
goto boucle_ON
et la lecture devient nettement plus linéaire...
 
Last edited:

Nico49

Member
OK pour l'interruption. Mais alors ça revient à une mise hors tension du système, suivie d'une éventuelle remise sous tension ?
Concernant le gosub, il appelle un sous programme et revient à l'instruction suivante.
Avec un goto, on va à un sous programme, qui lui même va sur un autre etc.. d'où des difficultés parfois à suivre un cheminement (type plat de nouilles) , et un risque évident de truc qui boucle et plante.
Ah ok, j'ai eu quelques rebouclages bizarres lors des premiers tests du prog, probablement dûs à ces "goto" ! J'ai quand même réussi à avoir le fonctionnement souhaité après quelques modifs et en gardant les "goto"... coups de chance... ?!
 

BESQUEUT

Senior Member
Ah ok, j'ai eu quelques rebouclages bizarres lors des premiers tests du prog, probablement dûs à ces "goto" ! J'ai quand même réussi à avoir le fonctionnement souhaité après quelques modifs et en gardant les "goto"... coups de chance... ?!
C'est ce qu'on dénomme
"programme tombé en marche" .:p

A la prochaine modif, qu'adviendra-t-il :confused:

Mais je vous rassure : on a vu bien pire !
Même si des améliorations sont possibles, on est loin de certains "tas de nouilles" impossibles à déchiffrer.
 

Nico49

Member
C'est ce qu'on dénomme
"programme tombé en marche" .:p

A la prochaine modif, qu'adviendra-t-il :confused:

Mais je vous rassure : on a vu bien pire !
Même si des améliorations sont possibles, on est loin de certains "tas de nouilles" impossibles à déchiffrer.
C'est bon, j'ai remplacé les GOTO par des GOSUB ! ;)
Ca fonctionne toujours !
 

Nico49

Member
sans parler du risque de passer par un RETURN avant d'avoir fait un GOSUB... (ce qui ne semble pas être le cas ici)

En fait, à la première lecture d'un programme, on ne va pas voir ce que fait un sous-programme. On suppose ce qu'il fait d'après son nom, et on continue à lire la suite. Ceci permet de "comprendre" le corps principal du programme sans rentrer dans les détails.

Dans le cas du GOTO on est obligé d'aller voir dans le détail de ce qui semble être une sorte de sous-programme pour découvrir tout à la fin qu'on revient au point de départ (ou pas...)
Du coup, on a perdu le déroulé du programme principal.


Sauf erreur de ma part, il est possible de remettre tout le bloc
drycell_ON
à sa place (c'est à dire à la place de l'instruction goto drycell_ON )
du coup, on peut également supprimer le
goto boucle_ON
et la lecture devient nettement plus linéaire...
Du coup on peut aussi faire de même avec le bloc drycell_OFF ?

Je trouvais qu'en créant 2 sous-programmes (drycell_ON & drycell_OFF, ça éclaircissais le programme principal et sa compréhension, non ?
 
Top