Fonction "COUNT"

BESQUEUT

Senior Member
Un simple essai en vraie grandeur. En plaçant le serout dans la boucle principale, il est exécuté inutilement à chaque boucle et on lit à 75 Hz une quantité de 5 ou 6 litres au lieu de 10.
Dans l'interrupt, il n'est exécuté que toutes les 45 interruptions, on monte à 30l/mn sans problème, à 32MHz. même si on perd quelques pulses. A 75Hz (10L/mn) T=13,3ms
Avec la liaison capacitive, il n'y a pas de blocage. L'interruption est sur le niveau bas, avec 100nF et 10k (RC= 1ms) en 1ms, le niveau bas du pulse est au dessus du niveau 0 TTL

Cela dit, vous avez raison, mais le but était de valider le déclenchement de l'interruption. la10k est en fait remplacée par un pont 10k/22k pour être moins sensible au niveau des créneaux du capteur hall.

MM
Rien n'impose de faire un serout à chaque tour de la boucle principale ; vous utilisez la variable time pour faire clignoter une led chaque seconde. C'est bien suffisant pour la mise à jour du compteur.
Et avec le bon code d'interruption vous ne perdrez plus d'impulsions...
 
Last edited:

Yex2

Well-known member
Question idiote: est-il bien nécessaire d'actualiser un affichage tous les 0.1l pour quelqu'un qui prend une douche ....
C'est pas idiot du tout.

Je pense que l’optimisation du circuit est plus important qu'une lecture précise...
 

PieM

Senior Member
Je pense que l’optimisation du circuit est plus important qu'une lecture précise...
ça veut dire quoi, quand on a pu lire:
Dans un deuxième temps je voulais ajouter une fonction de calibration afin d'ajuster le compteur en fonction des conditions précises retrouvées dans chacune des situations. J'ose espéré me rapprocher d'une précision de ± 1%.
En outre, faut expliquer comment vous améliorez la précision d'un instrument en l'étalonnant avec un appareil plus précis.
Chronométrer un âne n'en fait pas un cheval de course.
 

Yex2

Well-known member
Mais le mieux serait d'utiliser une interruption hard, laquelle fonctionne sur une transition et non sur un état.
Dans ce cas, l'interruption serait :
Rich (BB code):
interrupt:
      inc w0
return
Bonjour,

Qu'est-ce qu'une interruption "hard" ? Est-ce la commande "hintsetup " ? N'est-ce pas pour la série X ? Et si non, comment l'utiliser, la doc n'est pas vraiment clair la-dessus.

Merci,

Yex
 
Last edited:

Yex2

Well-known member
Mais en #63 vous affirmez que le débit est toujours le même : donc il n'est pas nécessaire de tenir compte du débit,
et donc il suffit de compter le nombre d'impulsions pour avoir un compteur et non un débitmètre.
En #63 j'explique que le débit est toujours le même au chalet, sauf si quelqu'un décide de faire la vaisselle durant la douche.

Sur le voilier le débit est légèrement différent dans chaque douche. Il n'y a qu'une pompe pour le bateau mais la distance entre chaque douche et la pompe varie. La résistance des tuyaux devrait affecter le débit de chaque sortie. C'est pour ça que je désire calibrer chaque douche afin que la lecture de volume soit relativement précise.

Par contre, pour connaitre le coefficient de conversion optimal, il est nécessaire de faire au moins un test avec le circuit réel.
Exactement ce que je dis depuis le début.
 

Yex2

Well-known member
Le preload permettrait également éventuellement de corriger la variation liée au débit. Car contrairement à ce qui est affirmé, par construction une pompe centrifuge obéît à une loi de variation qui est une courbe débit/pression; le débit ne peut être constant quand la charge réseau varie...
Ce ne sont pas des pompes à centrifuge. Sur les bateaux, on retrouve surtout des pompes à diaphragmes pour les circuits d'eau douce.
 
Last edited:

BESQUEUT

Senior Member
En #63 j'explique que le débit est toujours le même au chalet, sauf si quelqu'un décide de faire la vaisselle durant la douche.

Sur le voilier le débit est légèrement différent dans chaque douche. Il n'y a qu'une pompe pour le bateau mais la distance entre chaque douche et la pompe varie. La résistance des tuyaux devrait affecter le débit de chaque sortie. C'est pour ça que je désire calibrer chaque douche afin que la lecture de volume soit relativement précise.


BESQUEUT said:
Par contre, pour connaitre le coefficient de conversion optimal, il est nécessaire de faire au moins un test avec le circuit réel.

Exactement ce que je dis depuis le début.
Ben non : vous mélangez différents posts.
J'ai dit en #55 que le mieux est d'établir une courbe de conversion valable à différents débits.
Mais comme j'avais cru comprendre que le débit était constant, un seul test avec le circuit réel pouvait être suffisant pour établir un unique coefficient de conversion.
Comme en fait le débit est toujours le même sauf...
il faut considérer que le débit est variable et établir la courbe, ce qui nécessite un programme un peu différent.

Les interruptions hard et surtout le compteur externe ne sont disponibles que sur les Picaxes X2.
C'est le PIC qui gère directement les changements d'état. C'est bien plus simple et surtout plus fiable.
Mais est-il possible d'utiliser un X2 ?
Si oui, le code est sensiblement différent...
 
Last edited:

BESQUEUT

Senior Member
Ce ne sont pas des pompes à centrifuge. Sur les bateaux, on retrouve surtout des pompes à diaphragmes pour les circuits d'eau douce.
Et qu'en concluez vous ?
Soit on est certain que le débit est constant et un seul coefficient est nécessaire.
Soit le débit est variable et il faut établir la courbe.
Dans le doute, faites le test proposé en #55 et le programme sera universel.
Pour que les choses soient bien claires, il ne s'agit pas du circuit réel mais du debitmetre directement branché sur un robinet de la maison.
 
Last edited:

Yex2

Well-known member
Et qu'en concluez vous ?
Ce sont des pompes à pression constante, du moins elles essayent... ;) Le débit devrait rester constant. On verra à l'usage.
Mais c'est pas très grave parce que l'objectif du circuit est de conscientiser les gens à l'économie de l'eau et non pas de connaître la consommation exacte. Pour ça j'ai des sondes capacitives dans chaque réservoir et c'est pas mal précis...

Soit on est certain que le débit est constant et un seul coefficient est nécessaire.
Soit le débit est variable et il faut établir la courbe.
Je suis d'accord mais j'espère que ça ne sera pas nécessaire. Si le débit varie un peu, on devrait rester dans une plage constante, du moins relativement constante...


Dans le doute, faites le test proposé en #55 et le programme sera universel.
Pour que les choses soient bien claires, il ne s'agit pas du circuit réel mais du debitmetre directement branché sur un robinet de la maison.
Je reviens à la maison demain pour quelques jours. Je pourrai alors faire de nouveaux tests avec toutes les suggestions reçues. Je vous tiendrai au courant des résultats...

Merci pour tout !

yex
 

PieM

Senior Member
Ce sont des pompes à pression constante, du moins elles essayent... ;) Le débit devrait rester constant. On verra à l'usage.
Voici un exemple de pression et débit constant sur une pompe à diaphragme selon l'auteur.

C'est pour ça que je désire calibrer chaque douche afin que la lecture de volume soit relativement précise.
Ce qui ne sert à rien puisque la pression donc le débit de chaque douche change en fonction du nombre de points de prélèvement simultanés!

23090
 

BESQUEUT

Senior Member
Voici un exemple de pression et débit constant sur une pompe à diaphragme selon l'auteur.



Ce qui ne sert à rien puisque la pression donc le débit de chaque douche change en fonction du nombre de points de prélèvement simultanés!

View attachment 23090
Sans compter que le robinet peut-être plus ou moins ouvert...
C'est le concept habituel de la constante variable.
 

Yex2

Well-known member
Sans compter que le robinet peut-être plus ou moins ouvert...
C'est le concept habituel de la constante variable.
Bien qu'il est possible d'ajuster le robinet, en générale les gens ne le font pas. Ils mettent toute la gomme...
Le débit n'est pas assez grand pour justifier de le réduire. Les pommeaux de douche sont restrictif pour économiser justement.


PieM said:
Ce qui ne sert à rien puisque la pression donc le débit de chaque douche change en fonction du nombre de points de prélèvement simultanés!
Évidement. Sauf que la pression et débit diminuera également partout. J'ose espéré que les circuits continueront d'enregistrer fidèlement les consommations individuelles.

Je rappelle le but n'est pas de connaître la consommation exact de chacun mais de conscientiser les invités à l'économie de l'eau.
 

ddaweb

New Member
Bonjour,

Qu'est-ce qu'une interruption "hard" ? Est-ce la commande "hintsetup " ? N'est-ce pas pour la série X ? Et si non, comment l'utiliser, la doc n'est pas vraiment clair la-dessus.

Merci,

Yex
Oui cela en fait partie, je ne l'ai pas compris à 100%, mais un bout de code qui l'initialisait bien, avec un 28x2, passage de 1 à 0 :
Rich (BB code):
hintsetup %00000001     'Initialisation interrupt sur entree B.0 -> barriere1
setint %00000001,%00000001            'trigger entree
setintflags %00000001,%00000001     'Activation flag interrupt
Pour le 28x2, il ne peut se faire que sur 3 entrées physiques : B.0 à B.2

EDIT :
Ne pas oublier de mettre cette ligne avant le return de interrupt:
Rich (BB code):
SetIntFlags %0000001,%00000001             'reinitialisation flag interrupt : OBLIGATOIRE POUR INTERRUPT
 
Last edited:

BESQUEUT

Senior Member
Oui cela en fait partie, je ne l'ai pas compris à 100%, mais un bout de code qui l'initialisait bien, avec un 28x2, passage de 1 à 0 :
Rich (BB code):
hintsetup %00000001     'Initialisation interrupt sur entree B.0 -> barriere1
setint %00000001,%00000001            'trigger entree
setintflags %00000001,%00000001     'Activation flag interrupt
Pour le 28x2, il ne peut se faire que sur 3 entrées physiques : B.0 à B.2

EDIT :
Ne pas oublier de mettre cette ligne avant le return de interrupt:
Rich (BB code):
SetIntFlags %0000001,%00000001             'reinitialisation flag interrupt : OBLIGATOIRE POUR INTERRUPT
Certes mais il semble qu'un X2 ne soit pas envisagé.
Ce serait néanmoins plus adapté pour ce besoin dans la mesure où on détecte directement des transitions et de façon plus efficace...
En outre Piem a dit que les X2 disposent d'un compteur externe qui traite directement les impulsions.
 
Last edited:

PieM

Senior Member
Eléments du CDCF après 96 posts:
Comme ma pompe à un débit fixe, une fois calibré j'espère que le compteur sera précis.
On voit que le nombre d'impulsion n'est pas linéaire. Il augmente avec le débit. Sauf qu'on voit l'inverse sur la doc.
De plus la marge d'erreur annoncé est de 10%.
J'ose espéré me rapprocher d'une précision de ± 1%.
Sauf que la pression et débit diminuera également partout. Quand la pression pompe diminue, le débit augmente.
Je rappelle le but n'est pas de connaître la consommation exact de chacun.
Sur d'autres forums il y aurait déjà l'étiquette TROLL !
 

ddaweb

New Member
Certes mais il semble qu'un X2 ne soit pas envisagé.
Ce serait néanmoins plus adapté pour ce besoin dans la mesure où on détecte directement des transitions et de façon plus efficace...
En outre Piem a dit que les X2 disposent d'un compteur externe qui traite directement les impulsions.
Tout à fait j'ai déjà lu sur compteur externe.
Mais je ne faisais que répondre à sa question, il est grand assez pour prendre la décision final, voir changer d'idée en fin de compte :sneaky:
 

Yex2

Well-known member
Oui cela en fait partie, je ne l'ai pas compris à 100%, mais un bout de code qui l'initialisait bien, avec un 28x2, passage de 1 à 0 :
Rich (BB code):
hintsetup %00000001     'Initialisation interrupt sur entree B.0 -> barriere1
setint %00000001,%00000001            'trigger entree
setintflags %00000001,%00000001     'Activation flag interrupt
Pour le 28x2, il ne peut se faire que sur 3 entrées physiques : B.0 à B.2

EDIT :
Ne pas oublier de mettre cette ligne avant le return de interrupt:
Rich (BB code):
SetIntFlags %0000001,%00000001             'reinitialisation flag interrupt : OBLIGATOIRE POUR INTERRUPT
Merci ddaweb. C'est ce que je pensais.
 

MGU

Senior Member
Bonjour,

Je viens essayer de recentrer le débat...
Une réponse à une question : la bat85 du schéma sert à raboter le pulse positif donné par la liaison capacitive (5V +5V=10V , on dépasse les 5V max sur l'entrée). Mais de toute façon, ce schéma, on le jette.
Le but du jeu : sensibiliser des insouciants au problème de l'eau sur un bateau qui ne dispose que de 1000l en tout
4 cabines, 4 débitmètres low cost pour mesurer les consos de chaque cabine.
Les débitmètres sont considérés comme linéaires en fonction de débit entre 1 et 10l/mn (comme tous les capteurs de ce type, ils sont mauvais aux très bas débits genre goute à goute).
capteurs effet Hall à 450 pulses/L (à vérifier 450, 480,...suivant les docs).
Donc, dans un premier temps, je propose de faire un truc simple, avec un 08M2, le capteur, avec l'interrupt à bascule qui fonctionne très bien, sans blocage, et sans perte de pulses détectable.
Affichage LCD I2C, hors interruption ( on ne le dira jamais assez), résolution 1 dL, j'aime bien voir défiler les chiffres et c'est mieux pour "conscientiser les invités" ).

C'est oui ?. C'est non?

MM
 
Last edited:

Yex2

Well-known member
Bonjour,

Je viens essayer de recentrer le débat...
Une réponse à une question : la bat85 du schéma sert à raboter le pulse positif donné par la liaison capacitive (5V +5V=10V , on dépasse les 5V max sur l'entrée). Mais de toute façon, ce schéma, on le jette.
Le but du jeu : sensibiliser des insouciants au problème de l'eau sur un bateau qui ne dispose que de 1000l en tout
4 cabines, 4 débitmètres low cost pour mesurer les consos de chaque cabine.
Les débitmètres sont considérés comme linéaires en fonction de débit entre 1 et 10l/mn (comme tous les capteurs de ce type, ils sont mauvais aux très bas débits genre goute à goute).
capteurs effet Hall à 450 pulses/L (à vérifier 450, 480,...suivant les docs).
Donc, dans un premier temps, je propose de faire un truc simple, avec un 08M2, le capteur, avec l'interrupt à bascule qui fonctionne très bien, sans blocage, et sans perte de pulses détectable.
Affichage LCD I2C, hors interruption ( on ne le dira jamais assez), résolution 1 dL, j'aime bien voir défiler les chiffres et c'est mieux pour "conscientiser les invités" ).

C'est oui ?. C'est non?

MM
Bonsoir Michel,

Bon pour le projet du chalet, c'est terminé. Il reste une petite amélioration à apporter sur le texte de calibration mais sinon ça fonctionne comme je voulais.

J'ai fait le premier programme en me servant de la fonction COUNT. Ça été assez facile mais COUNT cause du dérapage à l'horloge, rendant la fonction de fin de cycle un peu erratique.

Donc tel que je l'avais écrit la semaine dernière, j'ai refait la version en me servant de SETINT.

J'ai utilisé la bascule suivante pour régler le problème de la loop infinie :

Code:
if pinC.3 = 0 then        ; armer l’interruption sur le bon niveau
    setint %1000,%1000        ; interruption niveau 1 sur C.3
    else setint %0,%1000    ; interruption niveau 0 sur C.3
endif
J'ai une fonction de calibrage qui fonctionne correctement. Je me sert de la même fonction interruption pour calibrer ou en mode régulier. Il n'y a donc plus d'erreur d'impulsions. J'obtiens toujours ± 430 impulsions par litre à un débit de 4L/M. Donc une fréquence e 28.6 Hz, ce qui est 12% de moins que ce que la doc précise (32 Hz). J'ai commandé 4 autres débitmètres et je suis très curieux de savoir s'ils seront aussi imprécis...

L'affichage principale ressemble à ceci :

************************
Conso Total 00.0 L
Dern. Douche 00.0 L
Maximum Enr. 00.0 L
Minimum Enr. 00.0 L
*************************

Les données sont enregistrés dans l'EEPROM. Le circuit peut donc être fermé lorsque nous sommes absent. J'ai d'ailleurs décidé de le brancher sur le circuit de la pompe. Le circuit sera toujours "off" lorsqu'il n'est pas utilisé.

180 Secondes d'inactivités du débitmètre déclenche la vérification des Minimum & Maximum et enregistre ces données au besoin.

J'ai une fonctionne de remise à zéro des données enregistrées. J'utilise le même poussoir que le calibrage.

Je pensais ajouter deux DEL pour signifier un record minimum (DEL verte) ou maximum (DEL rouge), et peut-être une troisième pour signifier aucun record (DEL jaune). Mais pour faire ça, il faudrait que je change de PICAXE comme un 14M2. C'est à voir, je vais y penser...

Sur le 08M2, j'utilise les broches C1 et 2 pour le LCD. Le débit mètre est sur C.3. C4 c'est le poussoir. C.0 pourrait servir pour les DEL rouge et verte. Il manquerait une sortie pour la DEL Jaune. J'ai lu quelques part qu'il est possible de bloquer le picaxe pour pourvoir se servir de C.5. Mais je ne suis pas tellement certain de savoir comment faire.

******************

Maintenant que le prototype du chalet est fonctionnel, je peux penser à faire ceux du bateau.

Les différences sont :

a) 4 circuits pour chacune des toilettes qui se rapporterons à une console à la table à carte.
Au lieu de "Dern. Douche 00.0 L ", on lira "Conso Quotidienne L", qui sera remis à zéro une fois par jour durant la nuit (vers 3h)

b) L'afficheur à la table à carte affichera seulement la "Consommations totales" de chaque cabine.

Ex.:

Cabi. AvBab 000.0 L >> (Avant Bâbord)
Cabi. AvTri 000.0 L >> (Avant Tribord)
Cabi. ArBab 000.0 L >> (Arrière Bâbord)
Cabi. ArTri 000.0 L >> (Arrière Tribord)

De cette manière je peux connaître la consommation des toilettes sans devoir y aller physiquement dans les cabines. Le respect de l'intimité des invités est important...

c) Peut-être les DEL rouge, jaune et verte sur chaque afficheur des toilettes comme pour le chalet. Un repère visuel est toujours pratique.

d) Possibilité de remettre les données à distance (de la console de la table à carte). Sur ce point, à l'origine j'avais pensé de simplement mettre les circuit hors tension en prenant soin de ne pas enregistrer les données dans l'EEPROM comme je fais au chalet. Puisque sur le bateau, le circuit restera toujours allumer, Ça me semble logique sauf si quelqu'un ferme le mauvais circuit et efface tout en cours de route. Je dois y penser...

Sur le circuit de la console, il faudrait utiliser une entrée pour les PV afin de détecter la tombé de la nuit et déclencher le compte à rebours de la mise à zéro de la conso quotidienne.

Voilà pour le moment.

Au plaisir de te lire,

Yex
 
Last edited:

MGU

Senior Member
Bonjour,

Oui, ça serait sympa de publier le fruit de ton travail, ça peut servir à d'autres.
Des questions posées sont restées sans réponse comme par ex la vérification de la linéarité en ft du débit.
Voici un code regroupant les différentes observations ci dessus.
Code:
;    SCL sur C.1
;    SDA sur C.2
#picaxe 08M2    ;directive picaxe utilisé (pour erreur de commandes)
dirsC =%000111
setfreq M16        ;fréquence 16MHz   
;****** Nominations constantes ********

;******* noms variables bit sur b0 ***********
symbol rsbit=bit0      ;bit commande/data afficheur
symbol flag=bit1        ;bascule interruption   

;***** noms variables bytes ****************
 ; b1,b2,b3,b4,b5 utilisés dans bintoascii
symbol partiel= b6
symbol car =b7       ;caractère à afficher
symbol dat =b8            ;data LCD
symbol cpt =b9       ;compteur

;****** noms variables word *********
symbol total =w13        ;consomation total depuis dernier reset

;******* Nominations ports ***********

; Initialisation I2C 4 bits , etc ********
    hi2csetup i2cmaster,%01001110, i2cfast_16, i2cbyte
    for cpt=0 to 5
      lookup cpt,($33,$32,$28,$c,$6,$01),car
      gosub EnvoiByteCommInit
    next
    setint %0,%1000    ;niveau 0 sur C.3
    pullup %1000    ;pullup sur C.3
    pause 100    ;temps init du LCD
    gosub AfficheInitial
; boucle principale
    do     
    outpinC.0=time         ;led clignote 1s
    if partiel>=45 then     ;n litres/min = fréq/7,5
        inc total            ;-> 1 litre/min = 7,5 impulsions/s
        partiel=0            ;-> 1 L = 7,5 x60 = 450 impulsions -> 0,1L =45 impulsions           
        bintoascii total,b5,b4,b3,b2,b1 
        car= 136    'position curseur
        gosub EnvoiByteComm     
         for cpt=0 to 7
         lookup cpt,(b5,b4,b3,b2,",",b1," L"),car
            GOSUB EnvoiByteData   ;
       next   
    endif         
    loop

; les sousroutines **********************

interrupt:     ;bit0=0 =>interupt sur niveau bas: bit0=1 =>interupt sur niveau haut
    if flag=0 then           
        inc partiel         
        flag=1
        setint %1000,%1000        ;interruption sur niveau haut avec bit0=1
    else                        ;l'interruption est sur niveau haut avec bit0=1   
        setint %0,%1000    ;niveau 0 sur C.3
         flag=0 
    endif
    return   

;  Affichage texte initial ***********************
AfficheInitial:
    car= 128    'curseur début ligne 1
    gosub EnvoiByteComm   
    for cpt=0 to 7
        lookup cpt,("Conso = "),car
        GOSUB EnvoiByteData   
    next     
    return

; Sub envoi vers LCD via I2C *************
EnvoiByteCommInit:
    pause 15
EnvoiByteComm:
    rsbit=0
EnvoiByteData:
;1ére moitié
    dat=car & $F0 | %1000 | rsbit ;%1000 pour l'éclairage
    hi2cout (dat)
    pause 1       
    dat=dat | %1100
    hi2cout (dat)    ;pulse sur E cad P2
    pause 1
    dat=dat | %1000 & %1011   ;fin pulse
    hi2cout (dat)
    pause 1   
;2éme moitié
    dat=car & $0F * 16 | %1000 | rsbit
    hi2cout (dat)
    pause 1   
    dat=dat | %1100
    hi2cout (dat)
    pause 1
    dat=dat | %1000 & %1011
    hi2cout (dat)   
    rsbit=1
    return
A+

MM
 

Yex2

Well-known member
Bonjour à tous,

Tel que spécifié plus haut, il me reste à modifier le texte de calibrage.
Pour ce qui est des DEL, je pense bien les ajouter alors je devrai également de changer de pic.

Je publierai le code une fois le tout terminé.

Merci à tous,

Yves
 

Yex2

Well-known member
Bonsoir à tous,

Voici donc mon premier code :cool:

Quelques observations :

a) Ça fait pas mal longtemps que je n'avais pas programmé. J'imagine qu'il existe des façons plus simple et plus élégante de faire ce programme. Les suggestions constructives sont les bienvenues.

b) je crois bien avoir correctement débuger la totalité des fonctionnalités, du moins je l'espère.

c) pour tester le circuit, je suggère de modifier la valeur de "cycle" entre 5 et 10 secondes afin de faire des tests plus rapidement.

d) tout le code qui sert à l'affichage du LCD provient des programmes de MGU. C'est du copier/collé. Je n'ai pas de mérite. Toutefois, je n'ai pas non plus compris tout ce qui se passait. Il est peut-être possible d'épurer ce code. Je compte utiliser les fonctions de matrice avec les 14M2.

e) la bascule d’interruption génère deux fois plus de pulse que sans bascule. C'est une bonne chose car ça diminue l'erreur d'arrondissement des PICAXE de moitié. De plus à la ligne 303 j'aoute 5 avant de diviser, ce qui diminue encore de moitié cette erreur. Au final elle passe de 2% dans le pire cas à 0.23%

f) il est possible de rendre le tout encore plus précis en utilisant une plus grande quantité d'eau pour la calibration. Toujours à la ligne 303, multiplier le diviseur "10" par le nombre de litre utilisé. Par exemple, si vous utiliser 4 litres, il faudra diviser (etalon+5)/ (10 *4).

Le code dans le prochain message (trop de caractère apparemment...)

Bonne lecture,

Yex
 
Last edited:

Yex2

Well-known member
Première parti du code :

Code:
; Ce programme et circuit vise à sensibiliser les gens à leur consommation d'eau dans des conditions où l'eau potable est une denrée rare.
; Le débitmètre Chinois est le modèle "YF-S201". La doc est disponible sur ce site : http://www.hobbytronics.co.uk/datasheets/sensors/YF-S201.pdf
; Ce débitmètre, lorsqu'il ne tourne pas, est dans un état ou un autre, soit "0" ou "1".
; Une interruption à bascule (inspiré du code de PieM) est utilisé pour contrer le problème précédant. Cette bascule génère deux fois plus d'impulsion que le débitmètre. Ce n'est pas un problème, même que c'est plutôt un avantage car il réduit l'imprécision de l'arrondi des PICAXE.
; La fréquence du débitmètre varie avec le débit et le niveau d'erreur est déclaré être de ±10%. Dans les faits, celui utilisé avec 12% d'erreur.
; La calibration est donc nécessaire et tiendra compte automatiquement du débit, de l'erreur de précision du débitmètre ainsi que du nombre accru d'impulsions de l'interruption à bascule.
; La sous routine de calibration se déclanche au démmarrage si la valeur de l'etalon = 0 ou si le possoir est enfoncé au mment de la mise sous tension.
; tous les codes utilisés pour l'affichage des données au LCD proviennent de différent programme publié par MGU ou inspirer de...
;    SCL sur C.1
;    SDA sur C.2

#picaxe 08M2                ;directive picaxe utilisé
dirsC =%000111

setfreq M16                    ;fréquence 16MHz 
;****** Nominations constantes ********
symbol baud= N2400_16              ;vitesse liaison RS232

;******* noms variables bit sur b0 ***********
symbol rsbit=bit0                ;bit commande/data afficheur
symbol calibr=bit1            ;memo phase calibration

;***** noms variables bytes ****************
; b1,b2,b3,b4,b5 utilisés dans bintoascii
symbol posi        =b6        ; position curseur
symbol car            =b7        ; caractère à afficher
symbol dat            =b8        ; utilisé dans la sous routine "EnvoiByteData"     

;****** noms variables word *********
symbol etalon        =w13        ; diviseur d'impulsion pour avoir 0.1 litre
symbol cpt            =w12        ; compteur
symbol total        =w11        ; consommation total depuis le dernier reset
symbol today        =w10        ; consommation journalière ou douche
symbol mini            =w9        ; consommation miminum depuis dernier reset
symbol maxi            =w8        ; consommation miminum depuis dernier reset
symbol impulsions        =w7        ; impulsion du bébitmètre
symbol cycle        =180        ; temps du cycle de douche en seconde

;******* Nominations ports ***********
symbol calibration      = pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées

; Initialisation I2C 4 bits , etc ********
    hi2csetup i2cmaster,%01001110, i2cslow_32, i2cbyte
  
; Initialisation LCD *********
    for cpt=0 to 5
        lookup cpt,($33,$32,$28,$c,$6,$01),car
        gosub EnvoiByteCommInit
    next
    pause 100                    ;temps init du LCD

if pinC.3 = 0 then                ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %1000,%1000            ; interruption niveau 1 sur C.3
    else setint %0,%1000        ; interruption niveau 0 sur C.3
endif

; lecteur des données en mémoire   
        read 0, word mini, word maxi, word total, word today, word etalon      ; lecture de données enregistrées           
    if etalon =0 then : gosub calib                       ; Afficher texte de calibration        
    else if calibration = 0 then : gosub calib      ; pour forcer une calibration à la mise sous tension. 
    endif

main: 
    disabletime 
    if mini =0 then
        mini =10000         ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord 

                ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records

;boucle de comptage
do
    if time >= cycle then        ; Enregistre le temps de la douche après "cycle" secondes d'inactivitées
        gosub record        ; cette routine enregistre les minimums et maximums
    endif

    if calibration=0 then        ; pour remettre toutes les valeurs à zéro sauf pour mini qui doit être à 10000
        time =0 : mini =10000 : maxi =0 : total =0 : today =0
        disabletime            ; Pour empêcher la sous routine "record" d'être appeler avant une nouvelle consommation d'eau
        write 0, word mini, word maxi, word total, word today
        gosub AfficheCourant
        gosub AfficheRecord
    endif
        gosub AfficheCourant        ; sous-routine de la consommation d'eau.
loop

; les sousroutines **********************

interrupt:                             ;comptage des impulsions du débitmètre
if time > cycle then : today = 0 : endif        ; remise à zéro de la consommation quotidienne après que la douche soit enregistrée (voir ligne 75)

inc impulsions                        ; compte les impulsions à chaque interrupt

    if impulsions    >=etalon then         ; etalon = noombre d'impulsions pour 0.1 L
           inc today                        ; incrémente de 0.1 L consommation quotidienne
        inc total                    ; incrémente de 0.1 L volume total consommé
      impulsions =impulsions - etalon         ; remet impulsions à 0 et conserve le reste s'il y a lieu
    endif

    if pinC.3 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %1000,%1000                ; interruption niveau 1 sur C.3
            else setint %0,%1000            ; interruption niveau 0 sur C.3
    endif
    enabletime                        ; pour démarrer l'horloge afin d'enregistrer les records
    time = 0                        ; reset l'horloge pour l'enregistrement des données (voir ligne 75)
    return

;calcule les minimums et maxiums

record:
    if mini > today then                 ; Si consommation de la douche est inférieur au record mini enregistré, enregistrez nouveau record.
        mini= today
        write 0, word mini
    endif
    if maxi < today then                ; Si consommation de la douche est supérieur au record maxi enregistré, enregistrez nouveau record.
        maxi=today
        write 2, word maxi
    endif
    gosub AfficheRecord                ; afficher les nouveaux résultats

    return

;  Affichage texte initial ***********************       

AfficheInitial: 

    car= 128    'curseur début ligne 1
    gosub EnvoiByteComm 
    for cpt=0 to 19
    lookup cpt,("Conso Total en LITRE"),car
    GOSUB EnvoiByteData 
    next 

    car= 192    'curseur  début ligne 2
    gosub EnvoiByteComm 
    for cpt=0 to 19
    lookup cpt,("Dern. Douche       L"),car
    GOSUB EnvoiByteData 
    next

    car= 148    'curseur  début ligne 3
    gosub EnvoiByteComm 
    for cpt=0 to 19
    lookup cpt,("Maximum Enregistre L"),car
    GOSUB EnvoiByteData 
    next

    car=212        'curseur début ligne 4
    gosub EnvoiByteComm
    for cpt=0 to 19
    lookup cpt,("Minimum Enregistre L"),car
    GOSUB EnvoiByteData
    next
    pause 6000
    gosub AfficheCourant
    gosub AfficheRecord
    pause 6000
return

; Affichage les valeurs Total et douche courante lors du comptage en ajustant le nombre de chiffre selon le nombre

AfficheCourant: 
     car= 139    'curseur  ligne 1, position 12
      gosub EnvoiByteComm 
    if total> 999 then
        bintoascii total,b5,b4,b3,b2,b1 
        for cpt=0 to 8
            lookup cpt,("  ",b4,b3,b2,",",b1," L"),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
      next
      else if total> 99 then
         bintoascii total,b5,b4,b3,b2,b1 
        for cpt=0 to 8
            lookup cpt,("   ",b3,b2,",",b1," L"),car    ;on a besoin que de 3 chiffres
            GOSUB EnvoiByteData
      next
    else
        bintoascii total,b5,b4,b3,b2,b1 
        for cpt=0 to 8
            lookup cpt,("    ",b2,",",b1," L"),car    ;on a besoin que de 2 chiffres
            GOSUB EnvoiByteData
      next
    endif
  
        car= 204    'curseur  ligne 2, position 12
        gosub EnvoiByteComm     
      if today> 99 then
         bintoascii today,b5,b4,b3,b2,b1 
        for cpt=0 to 7
            lookup cpt,("  ",b3,b2,",",b1," L"),car    ;on a besoin que de 3 chiffres
            GOSUB EnvoiByteData
      next
    else
        bintoascii today,b5,b4,b3,b2,b1 
        for cpt=0 to 7
            lookup cpt,("   ",b2,",",b1," L"),car    ;on a besoin que de 2 chiffres
            GOSUB EnvoiByteData
      next
    endif
     write 4, word total, word today      ; écriture des volumes consommés
return
 
Last edited:

Yex2

Well-known member
Deuxième partie :

Code:
; Affiche minimum et maximum***********************

; Lusage de la flèche ".>" permet d'indiquer à l'invité s'il s'agit d'un nouveau record.

AfficheRecord:
    car= 159    'curseur  ligne 3, position 12
      gosub EnvoiByteComm
    if maxi =0 or maxi > today then
         bintoascii maxi,b5,b4,b3,b2,b1        
       for cpt=0 to 8
            lookup cpt,(".   ",b2,",",b1," L"),car         ;on enlève les symboles ">>"
            GOSUB EnvoiByteData
      next
    else if maxi > 999 then
         bintoascii maxi,b5,b4,b3,b2,b1        
       for cpt=0 to 8
            lookup cpt,(".>",b4,b3,b2,",",b1," L"),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
      next
    else if maxi> 99 then
         bintoascii maxi,b5,b4,b3,b2,b1  
        for cpt=0 to 8
            lookup cpt,(".> ",b3,b2,",",b1," L"),car        ;on a besoin que de 3 chiffres
        GOSUB EnvoiByteData
      next
    else
        bintoascii maxi,b5,b4,b3,b2,b1  
        for cpt=0 to 8
            lookup cpt,(".>  ",b2,",",b1," L"),car        ;on a besoin que de 2 chiffres
        GOSUB EnvoiByteData
      next  
      endif


    car= 223    'curseur  ligne 4, position 12
      gosub EnvoiByteComm
    if mini > 9999 or mini <> today then            ;Condition de départ OU aucun record enregistré
        bintoascii mini,b5,b4,b3,b2,b1        
      for cpt=0 to 8
            lookup cpt,(".   ",b2,",",b1," L"),car        
            GOSUB EnvoiByteData
      next      
    else if mini > 999 then
        bintoascii mini,b5,b4,b3,b2,b1        
       for cpt=0 to 8
            lookup cpt,(".>",b4,b3,b2,",",b1," L"),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
      next
    else if mini> 99 then
        bintoascii mini,b5,b4,b3,b2,b1  
        for cpt=0 to 8
        lookup cpt,(".> ",b3,b2,",",b1," L"),car        ;on a besoin que de 3 chiffres
            GOSUB EnvoiByteData
       next
    else
       bintoascii mini,b5,b4,b3,b2,b1  
        for cpt=0 to 8
            lookup cpt,(".>  ",b2,",",b1," L"),car        ;on a besoin que de 2 chiffres
        GOSUB EnvoiByteData
       next
endif

return

calib:         ; routine de calibration obligatoire. Le débitmètre utilisé est -12% plus bas quespécifié dans la doc du manufacturier.
    car= 128    'curseur début ligne 1, colonne 1
    gosub EnvoiByteComm  
    for cpt=0 to 19
    lookup cpt,        ("Calibration requise "),car
    GOSUB EnvoiByteData  
    next

     car= 192    'curseur  ligne 2, colonne 1
    gosub EnvoiByteComm  
    for cpt=0 to 19
    lookup cpt,        ("Ajoutez 1 litre d'O "),car
    GOSUB EnvoiByteData  
    next
         
     car= 148    'curseur  ligne 3, colonne 1
      gosub EnvoiByteComm
       for cpt=0 to 19
            lookup cpt,("Impulsions=         "),car  
            GOSUB EnvoiByteData
    next

    car= 212    'curseur  ligne 4, colonne 1
      gosub EnvoiByteComm  
        for cpt=0 to 19
            lookup cpt,("Etalon calcule=     "),car  
            GOSUB EnvoiByteData
        next
      pause 8000

do  
    if calibration=0 then            ; le poussoir enregistre la fin du cycle de comptage et calcule l'etalon.  Il est sur C.4
        etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
        Write 8, etalon
        gosub AfficheCalib        ; pour voir la valeur de l'étalon
        pause 8000
        time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0 ; remet toute les valeurs à zéro pour débuter le comptage réel.
        goto main  
    endif
        gosub AfficheCalib            ; sous-routine de la consommation d'eau.
loop

return
;
AfficheCalib:        ; affiche les données de l'étalonnage

      car= 164    'curseur  ligne 3, colonne 16
      gosub EnvoiByteComm
        bintoascii total,b5,b4,b3,b2,b1  
        for cpt=0 to 3
            lookup cpt,(b4,b3,b2,b1),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
    next

      car= 228    'curseur  ligne 4, colonne 16
      gosub EnvoiByteComm
        bintoascii etalon,b5,b4,b3,b2,b1  
        for cpt=0 to 3
            lookup cpt,(b4,b3,b2,b1),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
    next  
   
return

; Sub envoi vers LCD via I2C ************* ; copié du programme des sondes capacitives de MGU.
EnvoiByteCommInit:
    pause 15
EnvoiByteComm:
    rsbit=0
EnvoiByteData:
;1ére moitié
    dat=car & $F0 | %1000 | rsbit     ;%1000 pour l'éclairage
    hi2cout (dat)
    pause 1      
    dat=dat | %1100
    hi2cout (dat)                ;pulse sur E cad P2
    pause 1
    dat=dat | %1000 & %1011       ;fin pulse
    hi2cout (dat)
    pause 1  
;2éme moitié
    dat=car & $0F * 16 | %1000 | rsbit
    hi2cout (dat)
    pause 1  
    dat=dat | %1100
    hi2cout (dat)
    pause 1
    dat=dat | %1000 & %1011
    hi2cout (dat)  
    rsbit=1
    return
 
Last edited:

MGU

Senior Member
Bonjour,

Va y avoir des questions, c'est sûr...
Pourquoi ces test >999, >99,....
C'est pour éviter d'écrire les 0 non significatifs ? comme : 0042,6 ?

MM
 

Yex2

Well-known member
Bonjour,

Va y avoir des questions, c'est sûr...
Pourquoi ces test >999, >99,....
C'est pour éviter d'écrire les 0 non significatifs ? comme : 0042,6 ?

MM
Oui c'est ça. Je n'ai pas trouver d'autre façon de le faire.

Et la petite ">" c'est pour indiqué qu'il y a eu un record d'enregistré.
 

BESQUEUT

Senior Member
a) Ça fait pas mal longtemps que je n'avais pas programmer. J'imagine qu'il existe des façons plus simple et plus élégante de faire ce programme. Les suggestions constructives sont les bienvenues.
Dans l'ensemble c'est plutôt lisible et bien structuré.
Un seul GOTO, mais pas dramatique : on comprends quand même comment ça fonctionne.
Grosse lourdeur pour l'affichage LCD : quelques macros permettent de faciliter la lecture.

Comme déjà dit et répété, l'interruption ne doit contenir que :
inc impulsions
et la bascule du setint.
Le reste devrait pouvoir être placé sans encombre dans la boucle principale.

La conséquence est que si des impulsions arrivent entre le début de l'interruption et le nouveau setint, elles sont perdues !
Ça explique peut être le problème d'étalonnage.
Vous affirmez qu'aucune impulsion n'est perdue : comment vous en êtes vous assuré ?
 

BESQUEUT

Senior Member
Code suggéré
Code:
#picaxe 08M2                ;directive picaxe utilisé
dirsC =%000111

setfreq M16                    ;fréquence 16MHz 
;****** Nominations constantes ********
symbol baud= N2400_16              ;vitesse liaison RS232

;******* noms variables bit sur b0 ***********
symbol rsbit=bit0                ;bit commande/data afficheur
symbol calibr=bit1            ;memo phase calibration

;***** noms variables bytes ****************
; b1,b2,b3,b4,b5 utilisés dans bintoascii
symbol posi        =b6        ; position curseur
symbol car            =b7        ; caractère à afficher
symbol dat            =b8        ; utilisé dans la sous routine "EnvoiByteData"     

;****** noms variables word *********
symbol etalon        =w13        ; diviseur d'impulsion pour avoir 0.1 litre
symbol cpt            =w12        ; compteur
symbol total        =w11        ; consommation total depuis le dernier reset
symbol today        =w10        ; consommation journalière ou douche
symbol mini            =w9        ; consommation miminum depuis dernier reset
symbol maxi            =w8        ; consommation miminum depuis dernier reset
symbol impulsions        =w7        ; impulsion du bébitmètre
symbol cycle        =180        ; temps du cycle de douche en seconde

symbol Ligne1= 128
symbol Ligne2= 192
symbol Ligne3= 148
symbol Ligne4= 212

#macro EnvoiLCD(Ligne,Texte)
    car= Ligne
    gosub EnvoiByteComm 
    for cpt=0 to 19
    lookup cpt,(Texte),car
    GOSUB EnvoiByteData 
    next 
#endmacro

#macro VolumeLCD(Nbre,t5,t4,t3)
       bintoascii Nbre,b5,b4,b3,b2,b1 
       for cpt=0 to 8
            lookup cpt,(t5,t4,t3,b2,",",b1," L"),car
            GOSUB EnvoiByteData
       next
#endmacro

#macro NombreLCD(Ligne,Nbre)
      car= Ligne+16    ' colonne 16
      gosub EnvoiByteComm
        bintoascii Nbre,b5,b4,b3,b2,b1  
        for cpt=0 to 3
            lookup cpt,(b4,b3,b2,b1),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
          next
#endmacro


;******* Nominations ports ***********
symbol calibration      = pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées

; Initialisation I2C 4 bits , etc ********
    hi2csetup i2cmaster,%01001110, i2cslow_32, i2cbyte
  
; Initialisation LCD *********
    for cpt=0 to 5
        lookup cpt,($33,$32,$28,$c,$6,$01),car
        gosub EnvoiByteCommInit
    next
    pause 100                    ;temps init du LCD

if pinC.3 = 0 then                ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %1000,%1000            ; interruption niveau 1 sur C.3
    else setint %0,%1000        ; interruption niveau 0 sur C.3
endif

; lecteur des données en mémoire   
        read 0, word mini, word maxi, word total, word today, word etalon      ; lecture de données enregistrées           
    if etalon =0 then : gosub calib                       ; Afficher texte de calibration        
    else if calibration = 0 then : gosub calib      ; pour forcer une calibration à la mise sous tension. 
    endif

main: 
    disabletime 
    if mini =0 then
        mini =10000         ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord 

                ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records

;boucle de comptage
do
    if time >= cycle then        ; Enregistre le temps de la douche après "cycle" secondes d'inactivitées
        gosub record        ; cette routine enregistre les minimums et maximums
    endif

    if calibration=0 then        ; pour remettre toutes les valeurs à zéro sauf pour mini qui doit être à 10000
        time =0 : mini =10000 : maxi =0 : total =0 : today =0
        disabletime            ; Pour empêcher la sous routine "record" d'être appeler avant une nouvelle consommation d'eau
        write 0, word mini, word maxi, word total, word today
        gosub AfficheCourant
        gosub AfficheRecord
    endif
        gosub AfficheCourant        ; sous-routine de la consommation d'eau.
loop

; les sousroutines **********************

interrupt:                             ;comptage des impulsions du débitmètre
if time > cycle then : today = 0 : endif        ; remise à zéro de la consommation quotidienne après que la douche soit enregistrée (voir ligne 75)

inc impulsions                        ; compte les impulsions à chaque interrupt

    if impulsions    >=etalon then         ; etalon = noombre d'impulsions pour 0.1 L
           inc today                        ; incrémente de 0.1 L consommation quotidienne
        inc total                    ; incrémente de 0.1 L volume total consommé
      impulsions =impulsions - etalon         ; remet impulsions à 0 et conserve le reste s'il y a lieu
    endif

    if pinC.3 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %1000,%1000                ; interruption niveau 1 sur C.3
            else setint %0,%1000            ; interruption niveau 0 sur C.3
    endif
    enabletime                        ; pour démarrer l'horloge afin d'enregistrer les records
    time = 0                        ; reset l'horloge pour l'enregistrement des données (voir ligne 75)
    return

;calcule les minimums et maxiums

record:
    if mini > today then                 ; Si consommation de la douche est inférieur au record mini enregistré, enregistrez nouveau record.
        mini= today
        write 0, word mini
    endif
    if maxi < today then                ; Si consommation de la douche est supérieur au record maxi enregistré, enregistrez nouveau record.
        maxi=today
        write 2, word maxi
    endif
    gosub AfficheRecord                ; afficher les nouveaux résultats

    return

;  Affichage texte initial ***********************       

AfficheInitial: 
    EnvoiLCD(Ligne1,"Conso Total en LITRE")
    EnvoiLCD(Ligne2,"Dern. Douche       L")
    EnvoiLCD(Ligne3,"Maximum Enregistre L")
    EnvoiLCD(Ligne4,"Minimum Enregistre L")


    pause 6000
    gosub AfficheCourant
    gosub AfficheRecord
    pause 6000
return

; Affichage les valeurs Total et douche courante lors du comptage en ajustant le nombre de chiffre selon le nombre

AfficheCourant: 
    car= 139    'curseur  ligne 1, position 12
    gosub EnvoiByteComm 
    if total> 999 then
            VolumeLCD(total,"  ",b4,b3)
    else if total> 99 then
        VolumeLCD(total,"  "," ",b3)
    else
        VolumeLCD(total,"  "," "," ")
    endif
  
    car= 204    'curseur  ligne 2, position 12
    gosub EnvoiByteComm     
    if today> 99 then
        VolumeLCD(today,"  "," ",b3)
    else
        VolumeLCD(today,"  "," "," ")
    endif
     write 4, word total, word today      ; écriture des volumes consommés
return


; Affiche minimum et maximum***********************
; L'usage de la flèche ".>" permet d'indiquer à l'invité s'il s'agit d'un nouveau record.

AfficheRecord:
    car= 159    'curseur  ligne 3, position 12
    gosub EnvoiByteComm
    if maxi =0 or maxi > today then
       VolumeLCD(maxi,". "," "," ")
    else if maxi > 999 then
       VolumeLCD(maxi,".>",b4,b3)
    else if maxi> 99 then
       VolumeLCD(maxi,".>"," ",b3)
    else
        VolumeLCD(maxi,".>"," "," ")
    endif


    car= 223    'curseur  ligne 4, position 12
    gosub EnvoiByteComm
    if mini > 9999 or mini <> today then            ;Condition de départ OU aucun record enregistré
       VolumeLCD(mini,". "," "," ")    
    else if mini > 999 then
        VolumeLCD(mini,". ",b4,b3)    
    else if mini> 99 then
         VolumeLCD(mini,". "," ",b3)    
    else
         VolumeLCD(mini,". "," "," ")    
    endif

return

calib:         ; routine de calibration obligatoire. Le débitmètre utilisé est -12% plus bas que spécifié dans la doc du manufacturier.
       EnvoiLCD(Ligne1,"Calibration requise ")
    EnvoiLCD(Ligne2,"Ajoutez 1 litre d'O ")
    EnvoiLCD(Ligne3,"Impulsions=         ")
    EnvoiLCD(Ligne4,"Etalon calcule=     ")
      pause 8000

do  
    if calibration=0 then            ; le poussoir enregistre la fin du cycle de comptage et calcule l'etalon.  Il est sur C.4
        etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
        Write 8, etalon
        gosub AfficheCalib        ; pour voir la valeur de l'étalon
        pause 8000
        time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0 ; remet toute les valeurs à zéro pour débuter le comptage réel.
        goto main  
    endif
    NombreLCD(Ligne3,total)
    NombreLCD(Ligne4,etalon)
loop

return
;


; Sub envoi vers LCD via I2C ************* ; copié du programme des sondes capacitives de MGU.
EnvoiByteCommInit:
    pause 15
EnvoiByteComm:
    rsbit=0
EnvoiByteData:
;1ére moitié
    dat=car & $F0 | %1000 | rsbit     ;%1000 pour l'éclairage
    hi2cout (dat)
    pause 1      
    dat=dat | %1100
    hi2cout (dat)                ;pulse sur E cad P2
    pause 1
    dat=dat | %1000 & %1011       ;fin pulse
    hi2cout (dat)
    pause 1  
;2éme moitié
    dat=car & $0F * 16 | %1000 | rsbit
    hi2cout (dat)
    pause 1  
    dat=dat | %1100
    hi2cout (dat)
    pause 1
    dat=dat | %1000 & %1011
    hi2cout (dat)  
    rsbit=1
    return
 

Yex2

Well-known member
Dans l'ensemble c'est plutôt lisible et bien structuré.
Un seul GOTO, mais pas dramatique : on comprends quand même comment ça fonctionne.
Grosse lourdeur pour l'affichage LCD : quelques macros permettent de faciliter la lecture.
Le GOTO était nécessaire pour sortir de la calibration et retourner au programme principale.

Pour l'affichage je sais, avez-vous des suggestions pour accélérer son écriture ? Vous parliez de macro, avez-vous un exemple à proposer ?


Comme déjà dit et répété, l'interruption ne doit contenir que :
inc impulsions
et la bascule du setint.
Le reste devrait pouvoir être placé sans encombre dans la boucle principale.
Oui sauf que "time" doit être mis à zéro lors des interruptions. Ça indique que la douche est en fonction. Lorsque c'est terminé, le temps redémarre et permet de déterminer la fin de la douche.

Pour ce qui est de inc today et total, pensez-vous qu'il est possible d'envoyer cette condition hors d'Interrupt ? Je pense que oui. Je vais essayer et vous revenir la-dessus. Sauf que je me sert justement de "total" pour la calibration...:unsure:

Code:
    if impulsions    >=etalon then         ; etalon = noombre d'impulsions pour 0.1 L
           inc today                        ; incrémente de 0.1 L consommation quotidienne
        inc total                    ; incrémente de 0.1 L volume total consommé
      impulsions =impulsions - etalon         ; remet impulsions à 0 et conserve le reste s'il y a lieu
    endif


Dans le programme pour le bateau, ça ne sera pas nécessaire d'avoir les conditions de "time" dans la loop d'interrupt. puisque je suis seulement intéressé de connaître la consommation journalière. J'utiliserai les panneaux solaires pour activer la fonction time au début de la nuit. La variable "cycle" sera ajustée à quelques heures. Le code pourrait ressembler à ceci :

Code:
symbol nuit      = pinC.5    ; entrée de PV

do
if nuit = 0 then : enabletime    ; active le l'horloge lorsque les PV retourne 0 volt
else time=0 : disable time    ; horloge à zéro et désactivée durant le jour.
endif

if time >= cycle then        ; enregistre la consommation journalière à chaque 24 heures
    gosub record                ; cette routine enregistre les minimums et maximums
endif
        gosub AfficheCourant        ; sous-routine de la consommation d'eau.
loop


interrupt:                             ;comptage des impulsions du débitmètre
inc impulsions                        ; compte les impulsions à chaque interrupt
    if impulsions    >=etalon then         ; etalon = noombre d'impulsions pour 0.1 L
           inc today                        ; incrémente de 0.1 L consommation quotidienne
        inc total                    ; incrémente de 0.1 L volume total consommé
      impulsions =impulsions - etalon         ; remet impulsions à 0 et conserve le reste s'il y a lieu
    endif

    if pinC.3 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %1000,%1000                ; interruption niveau 1 sur C.3
            else setint %0,%1000            ; interruption niveau 0 sur C.3
    endif
    return
La conséquence est que si des impulsions arrivent entre le début de l'interruption et le nouveau setint, elles sont perdues !
Ça explique peut être le problème d'étalonnage.
Vous affirmez qu'aucune impulsion n'est perdue : comment vous en êtes vous assuré ?
Il n'y a plus de problème avec l'étalonnage. Parce que je me suis assuré que la loop du calibrage et celle comptage normale appelle tous les deux une seule fonction d'affichage qui contient tous les deux seulement deux valeurs à afficher. La loop normale appelle "AfficheCourant" et la loop de calibrage appelle "AfficheCalib" J'estime que le temps d'affichage est très similaire dans les deux cas.

La preuve est dans le pudding :) : J'utilise un litre d'eau pour l'étalonnage. Je récupère ce même litre et le renvois à de nombreuse reprise après la calibrage et j'obtiens immanquablement toujours un litre. Ce qui démontre que le nombre d'impulsions au calibrage reste le même en mode de comptage. De plus, dans mes codes d'essais, j'affichais justement les impulsions dans le mode courant et constatait qu'il était le même qu'au calibrage pour une quantité d'eau similaire (1 litre).

Comme j'expliquais plus haut, pour avoir une plus grande précision, il serait préférable d'utiliser plus d'eau. Par exemple 4 litres permettrait d'avoir moins d'erreur.

"Perte de pulse" : Je vous lis sur ce sujet depuis le début du "post". Je suis un peu sceptique pour la raison suivante : Le micro-processeur tourne à 16 MHz alors que le débitmètre tourne de 32 à 90 Hz. Les chances de perdre une impulsion sont à mon avis pas mal nul puisque la vitesse d’exécution de la fonction interrupt est pas mal plus vite que la génération de pulse du débitmètre. C'est pratiquement la différence entre la vitesse de la lumière et celle du son. Est-ce que mon raisonnement est logique ?

Merci de vos suggestions,

Yex
 
Last edited:

Yex2

Well-known member
Code suggéré
Code:
#picaxe 08M2                ;directive picaxe utilisé
dirsC =%000111

setfreq M16                    ;fréquence 16MHz
;****** Nominations constantes ********
symbol baud= N2400_16              ;vitesse liaison RS232

;******* noms variables bit sur b0 ***********
symbol rsbit=bit0                ;bit commande/data afficheur
symbol calibr=bit1            ;memo phase calibration

;***** noms variables bytes ****************
; b1,b2,b3,b4,b5 utilisés dans bintoascii
symbol posi        =b6        ; position curseur
symbol car            =b7        ; caractère à afficher
symbol dat            =b8        ; utilisé dans la sous routine "EnvoiByteData"    

;****** noms variables word *********
symbol etalon        =w13        ; diviseur d'impulsion pour avoir 0.1 litre
symbol cpt            =w12        ; compteur
symbol total        =w11        ; consommation total depuis le dernier reset
symbol today        =w10        ; consommation journalière ou douche
symbol mini            =w9        ; consommation miminum depuis dernier reset
symbol maxi            =w8        ; consommation miminum depuis dernier reset
symbol impulsions        =w7        ; impulsion du bébitmètre
symbol cycle        =180        ; temps du cycle de douche en seconde

symbol Ligne1= 128
symbol Ligne2= 192
symbol Ligne3= 148
symbol Ligne4= 212

#macro EnvoiLCD(Ligne,Texte)
    car= Ligne
    gosub EnvoiByteComm
    for cpt=0 to 19
    lookup cpt,(Texte),car
    GOSUB EnvoiByteData
    next
#endmacro

#macro VolumeLCD(Nbre,t5,t4,t3)
       bintoascii Nbre,b5,b4,b3,b2,b1
       for cpt=0 to 8
            lookup cpt,(t5,t4,t3,b2,",",b1," L"),car
            GOSUB EnvoiByteData
       next
#endmacro

#macro NombreLCD(Ligne,Nbre)
      car= Ligne+16    ' colonne 16
      gosub EnvoiByteComm
        bintoascii Nbre,b5,b4,b3,b2,b1 
        for cpt=0 to 3
            lookup cpt,(b4,b3,b2,b1),car    ;on a besoin que de 4 chiffres
            GOSUB EnvoiByteData
          next
#endmacro


;******* Nominations ports ***********
symbol calibration      = pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées

; Initialisation I2C 4 bits , etc ********
    hi2csetup i2cmaster,%01001110, i2cslow_32, i2cbyte
 
; Initialisation LCD *********
    for cpt=0 to 5
        lookup cpt,($33,$32,$28,$c,$6,$01),car
        gosub EnvoiByteCommInit
    next
    pause 100                    ;temps init du LCD

if pinC.3 = 0 then                ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %1000,%1000            ; interruption niveau 1 sur C.3
    else setint %0,%1000        ; interruption niveau 0 sur C.3
endif

; lecteur des données en mémoire  
        read 0, word mini, word maxi, word total, word today, word etalon      ; lecture de données enregistrées          
    if etalon =0 then : gosub calib                       ; Afficher texte de calibration       
    else if calibration = 0 then : gosub calib      ; pour forcer une calibration à la mise sous tension.
    endif

main:
    disabletime
    if mini =0 then
        mini =10000         ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord

                ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records

;boucle de comptage
do
    if time >= cycle then        ; Enregistre le temps de la douche après "cycle" secondes d'inactivitées
        gosub record        ; cette routine enregistre les minimums et maximums
    endif

    if calibration=0 then        ; pour remettre toutes les valeurs à zéro sauf pour mini qui doit être à 10000
        time =0 : mini =10000 : maxi =0 : total =0 : today =0
        disabletime            ; Pour empêcher la sous routine "record" d'être appeler avant une nouvelle consommation d'eau
        write 0, word mini, word maxi, word total, word today
        gosub AfficheCourant
        gosub AfficheRecord
    endif
        gosub AfficheCourant        ; sous-routine de la consommation d'eau.
loop

; les sousroutines **********************

interrupt:                             ;comptage des impulsions du débitmètre
if time > cycle then : today = 0 : endif        ; remise à zéro de la consommation quotidienne après que la douche soit enregistrée (voir ligne 75)

inc impulsions                        ; compte les impulsions à chaque interrupt

    if impulsions    >=etalon then         ; etalon = noombre d'impulsions pour 0.1 L
           inc today                        ; incrémente de 0.1 L consommation quotidienne
        inc total                    ; incrémente de 0.1 L volume total consommé
      impulsions =impulsions - etalon         ; remet impulsions à 0 et conserve le reste s'il y a lieu
    endif

    if pinC.3 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %1000,%1000                ; interruption niveau 1 sur C.3
            else setint %0,%1000            ; interruption niveau 0 sur C.3
    endif
    enabletime                        ; pour démarrer l'horloge afin d'enregistrer les records
    time = 0                        ; reset l'horloge pour l'enregistrement des données (voir ligne 75)
    return

;calcule les minimums et maxiums

record:
    if mini > today then                 ; Si consommation de la douche est inférieur au record mini enregistré, enregistrez nouveau record.
        mini= today
        write 0, word mini
    endif
    if maxi < today then                ; Si consommation de la douche est supérieur au record maxi enregistré, enregistrez nouveau record.
        maxi=today
        write 2, word maxi
    endif
    gosub AfficheRecord                ; afficher les nouveaux résultats

    return

;  Affichage texte initial ***********************      

AfficheInitial:
    EnvoiLCD(Ligne1,"Conso Total en LITRE")
    EnvoiLCD(Ligne2,"Dern. Douche       L")
    EnvoiLCD(Ligne3,"Maximum Enregistre L")
    EnvoiLCD(Ligne4,"Minimum Enregistre L")


    pause 6000
    gosub AfficheCourant
    gosub AfficheRecord
    pause 6000
return

; Affichage les valeurs Total et douche courante lors du comptage en ajustant le nombre de chiffre selon le nombre

AfficheCourant:
    car= 139    'curseur  ligne 1, position 12
    gosub EnvoiByteComm
    if total> 999 then
            VolumeLCD(total,"  ",b4,b3)
    else if total> 99 then
        VolumeLCD(total,"  "," ",b3)
    else
        VolumeLCD(total,"  "," "," ")
    endif
 
    car= 204    'curseur  ligne 2, position 12
    gosub EnvoiByteComm    
    if today> 99 then
        VolumeLCD(today,"  "," ",b3)
    else
        VolumeLCD(today,"  "," "," ")
    endif
     write 4, word total, word today      ; écriture des volumes consommés
return


; Affiche minimum et maximum***********************
; L'usage de la flèche ".>" permet d'indiquer à l'invité s'il s'agit d'un nouveau record.

AfficheRecord:
    car= 159    'curseur  ligne 3, position 12
    gosub EnvoiByteComm
    if maxi =0 or maxi > today then
       VolumeLCD(maxi,". "," "," ")
    else if maxi > 999 then
       VolumeLCD(maxi,".>",b4,b3)
    else if maxi> 99 then
       VolumeLCD(maxi,".>"," ",b3)
    else
        VolumeLCD(maxi,".>"," "," ")
    endif


    car= 223    'curseur  ligne 4, position 12
    gosub EnvoiByteComm
    if mini > 9999 or mini <> today then            ;Condition de départ OU aucun record enregistré
       VolumeLCD(mini,". "," "," ")   
    else if mini > 999 then
        VolumeLCD(mini,". ",b4,b3)   
    else if mini> 99 then
         VolumeLCD(mini,". "," ",b3)   
    else
         VolumeLCD(mini,". "," "," ")   
    endif

return

calib:         ; routine de calibration obligatoire. Le débitmètre utilisé est -12% plus bas que spécifié dans la doc du manufacturier.
       EnvoiLCD(Ligne1,"Calibration requise ")
    EnvoiLCD(Ligne2,"Ajoutez 1 litre d'O ")
    EnvoiLCD(Ligne3,"Impulsions=         ")
    EnvoiLCD(Ligne4,"Etalon calcule=     ")
      pause 8000

do 
    if calibration=0 then            ; le poussoir enregistre la fin du cycle de comptage et calcule l'etalon.  Il est sur C.4
        etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
        Write 8, etalon
        gosub AfficheCalib        ; pour voir la valeur de l'étalon
        pause 8000
        time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0 ; remet toute les valeurs à zéro pour débuter le comptage réel.
        goto main 
    endif
    NombreLCD(Ligne3,total)
    NombreLCD(Ligne4,etalon)
loop

return
;


; Sub envoi vers LCD via I2C ************* ; copié du programme des sondes capacitives de MGU.
EnvoiByteCommInit:
    pause 15
EnvoiByteComm:
    rsbit=0
EnvoiByteData:
;1ére moitié
    dat=car & $F0 | %1000 | rsbit     ;%1000 pour l'éclairage
    hi2cout (dat)
    pause 1     
    dat=dat | %1100
    hi2cout (dat)                ;pulse sur E cad P2
    pause 1
    dat=dat | %1000 & %1011       ;fin pulse
    hi2cout (dat)
    pause 1 
;2éme moitié
    dat=car & $0F * 16 | %1000 | rsbit
    hi2cout (dat)
    pause 1 
    dat=dat | %1100
    hi2cout (dat)
    pause 1
    dat=dat | %1000 & %1011
    hi2cout (dat) 
    rsbit=1
    return

Oups je viens de voir le code après avoir envoyé mon dernier message. Je regarde ça et vous reviens.

Merci,

Yex
 

Yex2

Well-known member
Code suggéré
Code:
symbol Ligne1= 128
symbol Ligne2= 192
symbol Ligne3= 148
symbol Ligne4= 212

#macro EnvoiLCD(Ligne,Texte)
    car= Ligne
    gosub EnvoiByteComm
    for cpt=0 to 19
    lookup cpt,(Texte),car
    GOSUB EnvoiByteData
    next
#endmacro
Bonjour BESQUEUT,

Je ne trouve pas la fonction #macro... #endmacro dans la doc des PICAXE. Est-ce que ça fonctionne un peu comme une sous routine?

Code:
calib:         ; routine de calibration obligatoire. Le débitmètre utilisé est -12% plus bas que spécifié dans la doc du manufacturier.
       EnvoiLCD(Ligne1,"Calibration requise ")
    EnvoiLCD(Ligne2,"Ajoutez 1 litre d'O ")
    EnvoiLCD(Ligne3,"Impulsions=         ")
    EnvoiLCD(Ligne4,"Etalon calcule=     ")
      pause 8000

do
    if calibration=0 then            ; le poussoir enregistre la fin du cycle de comptage et calcule l'etalon.  Il est sur C.4
        etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
        Write 8, etalon
        gosub AfficheCalib        ; pour voir la valeur de l'étalon
        pause 8000
        time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0 ; remet toute les valeurs à zéro pour débuter le comptage réel.
        goto main
    endif
    NombreLCD(Ligne3,total)
    NombreLCD(Ligne4,etalon)
loop

return
Dans la sousroutine CALIB, j'avais la ligne de code "gosub AfficheCalib" qui servait à afficher la valeur de l'étalon à la fin du calibrage. Mais tu as supprimé la sousroutine AfficheCalib. Je crois qu'il faudrait ajouter "NombreLCD(Ligne4,etalon)", à la place. Est-ce exacte ?

Je vais essayer ce code aujourd'hui et t'en donner des nouvelles,

Merci,

Yex
 

MGU

Senior Member
Bonjour,

Les macros donnent un code moins indigeste, il est vrai que le code original datait du temps de PE5.5, il fallait un toilettage (merci BESQUEUT).

Ne pas confondre vitesse horloge et vitesse d'exécution, ça n'a rien à voir, surtout avec le basic du picaxe, simple, mais lent.
J'ai modifié le code de test en #103, on monte plus haut en fréquence en 16 MHz (time bat la seconde)

Donc, la même quantité d'eau, mesurée plusieurs fois dans les mêmes conditions donne la même valeur, c'est la "fidélité" de la mesure, pas la "précision".
Si 1L donne toujours 1L sans erreur, à différents débits, ce serait la fidélité plus la précision. Mais on ne sait toujours pas, c'est si cette quantité d'eau donne la même mesure si elle s'écoule en 30s, 1mn, 5 mn.
Il faudrait se rapprocher des conditions standards d'utilisation des douches, on en connait rien.

MM
 

Yex2

Well-known member
Bonjour,

Les macros donnent un code moins indigeste, il est vrai que le code original datait du temps de PE5.5, il fallait un toilettage (merci BESQUEUT).

Ne pas confondre vitesse horloge et vitesse d'exécution, ça n'a rien à voir, surtout avec le basic du picaxe, simple, mais lent.
J'ai modifié le code de test en #103, on monte plus haut en fréquence en 16 MHz (time bat la seconde)
Ok merci de l'info. C'est genre de détail qui font toute la différence.

Existe-il de l'information pertinente sur la vitesse d'exécution du code?


Donc, la même quantité d'eau, mesurée plusieurs fois dans les mêmes conditions donne la même valeur, c'est la "fidélité" de la mesure, pas la "précision".
Si 1L donne toujours 1L sans erreur, à différents débits, ce serait la fidélité plus la précision. Mais on ne sait toujours pas, c'est si cette quantité d'eau donne la même mesure si elle s'écoule en 30s, 1mn, 5 mn.
Il faudrait se rapprocher des conditions standards d'utilisation des douches, on en connait rien.
La précision vient du débitmètre lui-même. Une fois correctement calibré, il retourne toujours les mêmes valeurs aux mêmes conditions.
Je viens de faire un test avec la version du programme de BESQUEUT. Une fois calibré, j'ai versé 1 litre en 15 sec et ensuite refait le test en 30 sec. Je suis arrivé au même volume dans les deux cas. Reste à savoir si le comportement sera le même avec le débit et pression du voilier. On se croise les doigts...

Au risque de me répéter, pour le chalet le débit est constant. Le chalet c'est pour mes pots de chasse et pêche et ils ont compris mon obsession avec l'eau. Le problème c'est plus avec les invités occasionnels. S'il est facile de sortir l'homme de la ville il est plus difficile de sortir la ville de l'homme... ;)

Pour le bateau ça va varié mais très peu. Je n'ai pas répondu au affirmations gratuites précédentes concernant le débit vs pression parce que je ne voyais plus l'intérêt de ce débat stérile. En réalité, les constructeurs de voilier "haut de gamme" ont parfaitement prévu l'utilisation d'une pompe suffisamment puissante en pression et débit afin de permettre l'usage de toutes les douches en même temps sans perte de débit appréciable. C'est bien le cas de mon voilier.

Vous ne le saviez pas mais en 2016-2017, j'étais le chef d'une base de charter dans les Antilles pour la plus grosse compagnie de location de voiliers/catamarans au monde. J'étais entre autres tâches en charge de la maintenance de la flotte de la base. Il est facile de calculer la pompe requise afin que tous les clients puisse prendre leur douche en même temps. Il suffis d'additionner le débit de chaque douche et d'ajouter un facteur de sécurité raisonnable. Si par exemple le débit de la douche est de 4L/min, une pompe avec un débit de 20 L/min suffira à alimenter 4 douches, voir 5 en comptant la douche de pont.

Il faut savoir que les douches ont justement des débits relativement fixe grâce au mitigeur et aussi au pommeau lui-même conçu pour offrir une certaine résistance. Donc si la pompe maintien sa pression (disons 50 psi) et que son débit est largement suffisant, chaque douche devrait maintenir son propre débit et pression indépendamment des autres. Mais bon on verra l'automne prochain...
 

BESQUEUT

Senior Member
Je ne trouve pas la fonction #macro... #endmacro dans la doc des PICAXE. Est-ce que ça fonctionne un peu comme une sous routine?
#macro
Ben c'est dans la liste des commandes en ligne, à la lettre # à la fin...
C'est plutôt semblable à un symbol : ça remplace un paragraphe par une seule ligne.
Notez que la taille du programme reste la même, contrairement à l'utilisation d'un GOSUB.
Dans la sousroutine CALIB, j'avais la ligne de code "gosub AfficheCalib" qui servait à afficher la valeur de l'étalon à la fin du calibrage. Mais tu as supprimé la sousroutine AfficheCalib. Je crois qu'il faudrait ajouter "NombreLCD(Ligne4,etalon)", à la place. Est-ce exacte ?
Ben oui, mais c'est déjà le cas dans le code proposé...
 
Last edited:

BESQUEUT

Senior Member
Le GOTO était nécessaire pour sortir de la calibration et retourner au programme principale.
Un GOTO n'est jamais nécessaire.
Dans votre cas, un DO LOOP UNTIL calibration=0 devrait faire l'affaire.
Comme beaucoup, vous avez de la chance que le Picaxe gère plutôt bien le GOSUB sans RETURN.
Avec d'autres interpréteurs BASIC, ça conduit inévitablement à un dépassement de pile (stack overflow...)
Mais en insistant très fort, on y arrive aussi avec un Picaxe, qui pour le coup fait des choses totalement inattendues...

Existe-il de l'information pertinente sur la vitesse d'exécution du code?
Voir également PieM #80 qui explique pourquoi il ne faut pas mettre de serout dans une interruption...

Vos tests montrent que le code est fidèle, pas que toutes les impulsions sont prises en compte. Il est possible et probable que vous perdiez un pourcentage assez constant d'impulsions, ce qui n’entacherait pas trop la fidélité. Mais si le nombre d'impulsions par litre est le même avec votre code et celui qui ne contient que le inc impulsions, alors il n'y a pas d'amélioration possible, sauf un X2.
 

Attachments

Last edited:

ddaweb

New Member
Petite info, à partir du 28x2, il y a moyen de mettre un résonateur, multipliant par 4 la vitesse du µc et la stabilité du timer ...
Quelques adaptations à faire dans le code pour :
- l'activer
- les pauses vont 4x plus vite évidemment (base de 4 µsec)
- initialisation des impressions série
- etc ... je n'ai pas analysé votre code au complet, c'est les principales
 
Last edited:
Top