Fonction "COUNT"

Yex2

Well-known member
#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.
Ok merci, je vais lire ça avec intérêt. Et oui j'ai effectivement remarqué que ça n'a rien changé dans la taille du code :cry:

Quelle version de doc utilisez-vous ? Dans cette version française de la doc des PiCAXEs la commandes macro n'y est pas.

Ben oui, mais c'est déjà le cas dans le code proposé...
Heu... :unsure:. Vous aviez conservé ma ligne d'origine. Voir plus bas

"gosub AfficheCalib ; pour voir la valeur de l'étalon",

Évidement ça refusait de compiler parce que la sous routine AfficheCalib avait été retirée. Mais c'est pas grave, je ne suis pas si nul que ça. J'ai vite compris... ;-)

Code suggéré
Code:
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
 

Yex2

Well-known member
Un GOTO n'est jamais nécessaire.
Dans votre cas, un DO LOOP UNTIL calibration=0 devrait faire l'affaire.
Bien noté. J'avais d’ailleurs l'intention de vous demander pourquoi ne pas utiliser GOTO alors que la doc des PICAXE l'utilise souvent dans leurs différents exemples. J'imagine que les concepteurs ont prévu le coup et adapté leur compilateur en conséquence. Je me trompe ?

Question, si j'utilise le "DO LOOP UNTIL calibration=0 ", est-ce que le test "if calibration = 0" avant de sortir de la loop sera quand même effectué si je l'écris tel quel : ?

Code:
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
        NombreLCD(Ligne4,etalon)      ; pour voir la valeur de l'étalon une fois le calibrage terminé
        pause 8000
        time = 0 : mini = 10000 : maxi =0 : 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 until calibration=0

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.
D'accord pour cette observation.

Comme j'expliquais, c'est la même sous routine d'interrupt pour la calibration ou le comptage régulier. Si effectivement un % de pulse est perdu, alors il sera constant en tout temps...

Par curiosité je vais faire un code tout ce qui a de plus simple pour voir s'il est possible d'aller chercher plus d’impulsions en limitant la fonction interrupt au strict minimum. i.e. inc impulsion : setint %xxx %xxx

Mais à la base sachez que je suis un très fort adepte de la maxime Américaine suivante : "if it ain't broken, don't fix it!". La meilleur traduction serait "Si ça fonctionne, touches y pas !

Merci de votre aide,

Yex
 

Yex2

Well-known member
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)
La doc du PICAXE spécifie qu'entre 4 Mhz et 16 MHz, time sera incr.menté à toute les secondes.

2.25 enabletime
Effet de l'augmentation de vitesse de l'horloge du PICAXE
La fonction time fonctionnera correctement à 4MHz et à 16 Mhz.
A 2MHz ou à 8MHz, l'intervalle sera de 2s
A 32 MHz, l'intervalle sera de 0,5s

Question générale : Si modifier la vitesse de l'horloge n'a pas d'influence sur le traitement des lignes de code, à quoi sert de la modifier ? Quelle sont les avantages évident et moins évident ?
 

MGU

Senior Member
La doc du PICAXE spécifie qu'entre 4 Mhz et 16 MHz, time sera incr.menté à toute les secondes.

2.25 enabletime
Effet de l'augmentation de vitesse de l'horloge du PICAXE
La fonction time fonctionnera correctement à 4MHz et à 16 Mhz.
A 2MHz ou à 8MHz, l'intervalle sera de 2s
A 32 MHz, l'intervalle sera de 0,5s

Question générale : Si modifier la vitesse de l'horloge n'a pas d'influence sur le traitement des lignes de code, à quoi sert de la modifier ? Quelle sont les avantages évident et moins évident ?
Je me suis mal exprimé. Il y a une relation, le même code s'exécute deux fois plus vite, si la vitesse horloge du picaxe est multipliée par deux.
Mais une ligne de code utilisé beaucoup de cycles horloge
MM
 

PieM

Senior Member
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.
Hypothèse totalement gratuite et contraire aux lois de l'hydrodynamique. Seules les pompes volumétriques peuvent fournir des débits constants (à qq % près) sous pression variable. Ce qui n'est pas le cas des pompes à diaphragme . voir #91.
 

BESQUEUT

Senior Member
Ok merci, je vais lire ça avec intérêt. Et oui j'ai effectivement remarqué que ça n'a rien changé dans la taille du code :cry:
Tant que ça tient dans la mémoire du Picaxe, la taille du code n'a aucune importance.
Le GOSUB est assez long à exécuter. Ça permet de mieux structurer un programme, mais ça peut être pénalisant si on optimise la vitesse.
S'il faut optimiser à la fois vitesse et taille du code, ça devient pointu...
Quelle version de doc utilisez-vous ? Dans cette version française de la doc des PiCAXEs la commandes macro n'y est pas.
Ouaip : faudrait reprendre ce gros travail de traduction...
Le problème c'est que Rev Ed ne nous fait pas part des modifications de leur doc et privilégie l'aide en ligne.
Et je reconnais que c'est ce que j'utilise en priorité parce que c'est à peu près à jour.
Heu... :unsure:. Vous aviez conservé ma ligne d'origine. Voir plus bas

"gosub AfficheCalib ; pour voir la valeur de l'étalon",

Évidement ça refusait de compiler parce que la sous routine AfficheCalib avait été retirée. Mais c'est pas grave, je ne suis pas si nul que ça. J'ai vite compris... ;-)
Oups : j'avais point vu que ce gosub est utilisé deux fois :

Je propose un truc du genre (non testé) :
Rich (BB code):
calib:
   EnvoiLCD(Ligne1,"Calibration requise ")
   EnvoiLCD(Ligne2,"Ajoutez 1 litre d'O ")
   EnvoiLCD(Ligne3,"Impulsions=         ")
   EnvoiLCD(Ligne4,"Etalon calcule=     ")
   pause 8000
      
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0

   etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
   Write 8, etalon
   NombreLCD(Ligne3,total)
   NombreLCD(Ligne4,etalon)
   pause 8000
   time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0
return
 
Last edited:

BESQUEUT

Senior Member
Bien noté. J'avais d’ailleurs l'intention de vous demander pourquoi ne pas utiliser GOTO alors que la doc des PICAXE l'utilise souvent dans leurs différents exemples. J'imagine que les concepteurs ont prévu le coup et adapté leur compilateur en conséquence. Je me trompe ?
Le GOTO contribue à rendre le code illisible.
Et oui les exemple de Rev Ed sont souvent contestables, et pas que à cause des GOTO...
Vous pouvez lancer ça en simulation :
Rich (BB code):
' ! démonstration de ce qu'il ne faut pas faire !

Main:
      sertxd("b0=",#b0,13,10)
      gosub SousProg
      goto Main
      
      
      
SousProg:
      inc b0
      if b0>0 then goto Main
      return
Notez que si vous lancez ça sur un Picaxe Réel, ça va tourner !
Il faut faire un code un peu plus complexe pour mettre en évidence le problème sur un Picaxe réel...

Notez qu'il est très difficile (impossible ?) de créer ce problème sans utiliser la commande GOTO.
Une bonne habitude au moins pour les débutants est donc de ne pas utiliser la commande GOTO.

Il existe toutefois de rares cas où un utilisateur expérimenté trouvera avantage à cette commande pour optimiser la taille et la vitesse d'exécution d'un programme. Ça reste rarissime.
 
Last edited:

BESQUEUT

Senior Member
"if it ain't broken, don't fix it!". La meilleur traduction serait "Si ça fonctionne, touches y pas !
Ouaip : je dirais "Pourquoi faire simple quand on sait faire compliqué ?"
C'est typique des programme "tombés en marche"...
Ça fonctionne, mais on se demande bien comment...
Disons que si c'est un test "jetable" c'est acceptable.
Si par contre le programme est susceptible d'être repris six mois plus tard pour amélioration et/ou déverminage,
alors on constate qu'un programme mal foutu est une galère sans nom. Pensez également aux contributeurs du forum qui tentent de vous venir en aide et doivent décrypter le code...

Un code trivial est souvent exempt de bug, et est en tout cas bien plus facile à déverminer.

J'en profite pour ma diatribe sur les commentaires débiles genre :

For b0=1 to 10 ' Boucle qui va de un à dix

Sans commentaire...

Préférer utiliser des symbol bien parlants, par exemple au lieu de :
if calibration=0 then
je suggère quelque chose comme :
if PoussoirCalib=Relaché then

Accessoirement, le fait de définir un symbol pour les états d'un contact permet de changer de type de logique en changeant une seule ligne de code...

Question générale : Si modifier la vitesse de l'horloge n'a pas d'influence sur le traitement des lignes de code, à quoi sert de la modifier ? Quelle sont les avantages évident et moins évident ?
Les Picaxes étant interprétés, la vitesse d'exécution est environ mille fois plus lente qu'un PIC compilé...
Pour beaucoup d'applications, ça n'a pas pas beaucoup d'importance, mais pour traquer des impulsions, ça devient un facteur limitant.
En particulier, les interruptions sont désactivées dans le sub Interrupt, et c'est pourquoi il est souvent préférable qu'il soit le plus rapide possible.
Même avec des interruptions hard, elles ne sont prises en compte qu'entre deux commandes. Donc il faut éviter les commandes les plus longues si on veut limiter la casse (la perte des événements que l'on souhaite traquer...)
Et bien sur, mettre le Picaxe à fond les bananes améliore grandement la réactivité du code. Il faut juste en tenir compte pour les commandes liées au temps et le port série...
 
Last edited:

BESQUEUT

Senior Member
"if it ain't broken, don't fix it!". La meilleur traduction serait "Si ça fonctionne, touches y pas !
Autre considération :
Si ça peut foirer, alors ça foirera un jour ou l'autre, et de préférence au moment où les conséquences seront les plus catastrophiques...
Illustration pratique :
Soit une fusée Ariane 4 ; elle est tenue verticale par un programme d'asservissement basé sur la variable b0 qui contient l'inclinaison de la fusée. En fonction, on ajuste la poussée du moteur opposé.
Ce programme donnant pleinement satisfaction, il est reconduit tel quel sur Ariane 5.
Sauf que, alors que sur Ariane 4, l'inclinaison ne dépasse jamais 150, elle peut atteindre 255 sur Ariane 5...
La valeur suivante étant bien évidemment zéro, on observe brutalement une réduction de puissance du moteur, suivi par une inclinaison de la fusée de plus en plus catastrophique...
Fort heureusement ( !!!) le système d'auto-destruction de la fusée a parfaitement fonctionné avant le retour au sol, volatilisant en quelques secondes quelques M€ ainsi que des satellites de grande valeur...
Grosse bêtise chef...
 

Yex2

Well-known member
Hypothèse totalement gratuite et contraire aux lois de l'hydrodynamique. Seules les pompes volumétriques peuvent fournir des débits constants (à qq % près) sous pression variable. Ce qui n'est pas le cas des pompes à diaphragme . voir #91.
C'est peut-être moi qui s'exprime pas bien mais en bout de ligne, ce qui compte c'est le résultat. Lorsque je prends une douche et que ma femme en prends une en même temps dans l'autre toilette, je ne constate aucune baisse de débit ni pression...

Alors le constructeur de ce voilier devait sûrement savoir ce qu'il faisait. Au prix de vente de ce bateau, l'acheteur est parfaitement en droit de s'attendre à une performance adéquate des douches pour lui et tous ses invités...
 
Last edited:

Yex2

Well-known member
Je propose un truc du genre (non testé) :
Rich (BB code):
calib:
   EnvoiLCD(Ligne1,"Calibration requise ")
   EnvoiLCD(Ligne2,"Ajoutez 1 litre d'O ")
   EnvoiLCD(Ligne3,"Impulsions=         ")
   EnvoiLCD(Ligne4,"Etalon calcule=     ")
   pause 8000
      
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0

   etalon = total+5/10        ; le "+5" est pour compenser l'erreur d'arrondis des PICAXEs
   Write 8, etalon
   NombreLCD(Ligne3,total)
   NombreLCD(Ligne4,etalon)
   pause 8000
   time = 0 : mini = 10000 : total = 0 : today = 0 : impulsions = 0
return
J'aime ça ! :D Vraiment plus propre en effet.

J'enlèverai même la ligne : NombreLCD(Ligne3,total) sous le "Write 8, etalon" puisque la valeur n'aura pas changé depuis la dernière loop.
 

Yex2

Well-known member
Le GOTO contribue à rendre le code illisible.
Et oui les exemple de Rev Ed sont souvent contestables, et pas que à cause des GOTO...
Vous pouvez lancer ça en simulation :
Rich (BB code):
' ! démonstration de ce qu'il ne faut pas faire !

Main:
      sertxd("b0=",#b0,13,10)
      gosub SousProg
      goto Main
      
      
      
SousProg:
      inc b0
      if b0>0 then goto Main
      return
Notez que si vous lancez ça sur un Picaxe Réel, ça va tourner !
Il faut faire un code un peu plus complexe pour mettre en évidence le problème sur un Picaxe réel...

Notez qu'il est très difficile (impossible ?) de créer ce problème sans utiliser la commande GOTO.
Une bonne habitude au moins pour les débutants est donc de ne pas utiliser la commande GOTO.

Il existe toutefois de rares cas où un utilisateur expérimenté trouvera avantage à cette commande pour optimiser la taille et la vitesse d'exécution d'un programme. Ça reste rarissime.

OK bien reçu.

À ma défense je l'ai utilisé une seule fois et ne sert qu'une seule fois dans le programme de calibration.

Mais j'aime bien votre code à #126 alors je vais faire la mise à jour.
 

Yex2

Well-known member
Ouaip : je dirais "Pourquoi faire simple quand on sait faire compliqué ?"
Ça, ça fait plus Français en effet... ;)
Et c'est vrai que les Français aiment faire compliquer... :eek:

Préférer utiliser des symbol bien parlants, par exemple au lieu de :
if calibration=0 then
je suggère quelque chose comme :
if PoussoirCalib=Relaché then


Je vois où vous voulez en venir. Je préfère quand même utilisé 0 ou 1 parce que c'est Universelle. Le Canada a deux langues officielles et hélas pas tous sont bilingue comme moi...

Vous remarquerez que mes choix de variable sont presque toujours des mots que les deux langues identifies rapidement. Ce n 'est pas un hasard, c'est voulu.

Les Picaxes étant interprétés, la vitesse d'exécution est environ mille fois plus lente qu'un PIC compilé...
Pour beaucoup d'applications, ça n'a pas pas beaucoup d'importance, mais pour traquer des impulsions, ça devient un facteur limitant.
En particulier, les interruptions sont désactivées dans le sub Interrupt, et c'est pourquoi il est souvent préférable qu'il soit le plus rapide possible.
Même avec des interruptions hard, elles ne sont prises en compte qu'entre deux commandes. Donc il faut éviter les commandes les plus longues si on veut limiter la casse (la perte des événements que l'on souhaite traquer...)
Et bien sur, mettre le Picaxe à fond les bananes améliore grandement la réactivité du code. Il faut juste en tenir compte pour les commandes liées au temps et le port série...
Merci de l'explication et ça éclaircie ma compréhension. Voyez-vous, ma toute première expérience de programmation d'un micro-contrôleur remonte à proche 25 ans. C'était à L'Université dans une cours d'électronique quelconque. On programmait en Assembler et peaufinait en Binaire. Le PIC était tellement rapide qu'il fallait mettre des pauses partout pour voir les textes défiler...
 

Yex2

Well-known member
Autre considération :
Si ça peut foirer, alors ça foirera un jour ou l'autre, et de préférence au moment où les conséquences seront les plus catastrophiques...
Illustration pratique :
Soit une fusée Ariane 4 ; elle est tenue verticale par un programme d'asservissement basé sur la variable b0 qui contient l'inclinaison de la fusée. En fonction, on ajuste la poussée du moteur opposé.
Ce programme donnant pleinement satisfaction, il est reconduit tel quel sur Ariane 5.
Sauf que, alors que sur Ariane 4, l'inclinaison ne dépasse jamais 150, elle peut atteindre 255 sur Ariane 5...
La valeur suivante étant bien évidemment zéro, on observe brutalement une réduction de puissance du moteur, suivi par une inclinaison de la fusée de plus en plus catastrophique...
Fort heureusement ( !!!) le système d'auto-destruction de la fusée a parfaitement fonctionné avant le retour au sol, volatilisant en quelques secondes quelques M€ ainsi que des satellites de grande valeur...
Grosse bêtise chef...

Je comprends mais ne perdons pas de vu l'objectif du projet ici, ce n'est pas une fusée. Les conséquences si le programme plante sont absolument null... :sneaky:

Ceci dit je respect et apprécie beaucoup votre soucis du détail et de la précision recherchée.
 
Last edited:

Yex2

Well-known member
Bonjour,

Question pratico pratique : Est-il nécessaire d'effacer un programme avant de l'exécuter ou est-ce que l'exécution inclus automatiquement l'effacage du programme actuel ?

Merci,

Yex

23092
 

ddaweb

New Member
Vous parlez le pgm dans le picaxe ?
Si oui, le fait d'en envoyer un nouveau, il remplace celui dans le picaxe ;)

Sinon exécuter dans le programme lui-même, c'est celui qui est dans la page sélectionnée ... je ne pense même pas qu'il faille sauver avant.
Mais cela ne remplace en rien le picaxe ... souvent j'ai eu un pgm qui fonctionnait très bien dans l'émulateur, mais pas dans le picaxe.
 

BESQUEUT

Senior Member
Je comprends mais ne perdons pas de vu l'objectif du projet ici, ce n'est pas une fusée. Les conséquences si le programme plante sont absolument null... :sneaky:

Ceci dit je respect et apprécie beaucoup votre soucis du détail et de la précision recherchée.
Les considérations générales ne sont pas applicables aux cas particuliers...
Pour aller dans votre sens, ma grand mère disait :
le mieux est l'ennemi du bien...
 

Yex2

Well-known member
Les considérations générales ne sont pas applicables aux cas particuliers...
Pour aller dans votre sens, ma grand mère disait :
le mieux est l'ennemi du bien...
Ma femme dit ça aussi et me le répète presque chaque jour depuis que je tripote ce circuit, dans la cuisine, depuis plus d'une semaine. :ROFLMAO:

Bon voici votre code #126 testé avec quelques changements pour corriger le dernier bug trouvé lors d'une deuxième calibration :

Pour fonctionner, la calibration nécessite que la variable etalon, total et today soit à 0.

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 4000

etalon =0 : total =0 : today =0      ; valeur remise à zéro
  
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0    ; 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
   NombreLCD(Ligne4,etalon)    ; pour voir la valeur de l'étalon une fois le calibrage terminé
   pause 8000
   time =0 : mini =10000 : maxi =0 : total =0 : today =0 : impulsions =0
return
 

Yex2

Well-known member
Bon ce message est pour confirmer qu'il n'y a pas de perte d'impulsion dans mon code.

J'obtiens systématiquement entre 860 et 869 impulsions / litre à chacun de mes tests. Que ce soit avec ce code épuré ou celui de mon programme :

Code:
interrupt:                                 ;comptage des impulsions du débitmètre

 inc total                            ; compte les impulsions à chaque interrupt

    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
Code du programme :

Code:
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

Ceci confirme donc ma théorie que la vitesse du PIC est beaucoup plus rapide que celui du débitmètre. L’interruption s'exécute plus rapidement que le prochain pulse du débitmètre. En tout cas pour le débit actuel du test.

Question : est-il possible de mesurer la rapidité de l'exécution de l'interruption en micro seconde en insérant une variable de temps autre que "time" ?
 

ddaweb

New Member
Peut-être utiliser SETINT OFF au bon endroit pour annuler l'interruption ?
Une pause en plus sera peut-être utile ?

Si je comprend bien c'est +/- le double ?
 

BESQUEUT

Senior Member
Question : est-il possible de mesurer la rapidité de l'exécution de l'interruption en micro seconde en insérant une variable de temps autre que "time" ?
Pas sur un M2. Les X2 ont un timer mais ça n'est pas idéal non plus.
Quand j'ai le problème, je fait un toggle sur une pin et je mesure avec un fréquencemètre, un analyseur logique, un oscillo...
ou un T...y

Avec un de ces instruments il serait d'ailleurs possible de vérifier directement les impulsions envoyées par le débitmètre.
 

Yex2

Well-known member
Pas sur un M2. Les X2 ont un timer mais ça n'est pas idéal non plus.
Quand j'ai le problème, je fait un toggle sur une pin et je mesure avec un fréquencemètre, un analyseur logique, un oscillo...
ou un T...y

Avec un de ces instruments il serait d'ailleurs possible de vérifier directement les impulsions envoyées par le débitmètre.
Ça serait chouette mais mon oscilloscope est dans une boite empilée dans le fond d'un entrepôt... 😢 Dommage j'aurais pu clore ce sujet. spécifique.

Est-ce qu'il y a des formules précises qui donnent le temps exact d'exécusion pour chaque fonction ? Il me semble que c'est assez élémentaire comme besoin en programmation...

Savez-vous combien de temps (approximativement) prends le pic pour exécuter une ligne de code de l'interrupt de mon programme ?

On sait que le débitmètre tourne entre 32 et 90 Hz pour les débits utiles. Puisque la bascule lit essentiellement le demi-cycle, on peut dire que c'est 64 à 180 Hz.

64 Hz = 1 pulse à tous les 15.6 msec
180 Hz = 1 pulse à tous les 5.6 msec

Conclusion, si l'interruption s'exécute en moins de 5.6 ms, il n'y aura jamais de perte de pulse.
 
Last edited:

Yex2

Well-known member
Peut-être utiliser SETINT OFF au bon endroit pour annuler l'interruption ?
Une pause en plus sera peut-être utile ?

Si je comprend bien c'est +/- le double ?
Mais pourquoi voudrait-on ralentir ou annuler l'interruption ? Le but est justement de ne manquer aucun pulse.

C'est exactement le double parce que la "bascule" fait en sorte de lire les "0" et les "1" alternativement. Donc on lit le demi-cycle.
 
Last edited:

Yex2

Well-known member
Vous parlez le pgm dans le picaxe ?
Si oui, le fait d'en envoyer un nouveau, il remplace celui dans le picaxe ;)

Sinon exécuter dans le programme lui-même, c'est celui qui est dans la page sélectionnée ... je ne pense même pas qu'il faille sauver avant.
Mais cela ne remplace en rien le picaxe ... souvent j'ai eu un pgm qui fonctionnait très bien dans l'émulateur, mais pas dans le picaxe.

Merci ddaweb,

Je me posais la question parce que imaginez la situation suivantes où vous effacer un programme de 2000 bytes avec un qui est plus petit, disons 1980 bytes. Qu'arrive t'il avec les espaces de mémoire (20 bytes) du vieux programme qui ne seront pas remplacé par le plus récent ? Sont-ils effacé ou demeure t'il en mémoire causant des interférences ?

Yex
 

BESQUEUT

Senior Member
Ça serait chouette mais mon oscilloscope est dans une boite empilée dans le fond d'un entrepôt... 😢 Dommage j'aurais pu clore ce sujet. spécifique.

Est-ce qu'il y a des formules précises qui donnent le temps exact d'exécusion pour chaque fonction ? Il me semble que c'est assez élémentaire comme besoin en programmation...

Savez-vous combien de temps (approximativement) prends le pic pour exécuter une ligne de code de l'interrupt de mon programme ?

On sait que le débitmètre tourne entre 32 et 90 Hz pour les débits utiles. Puisque la bascule lit essentiellement le demi-cycle, on peut dire que c'est 64 à 180 Hz.

64 Hz = 1 pulse à tous les 15.6 msec
180 Hz = 1 pulse à tous les 5.6 msec

Conclusion, si l'interruption s'exécute en moins de 5.6 ms, il n'y aura jamais de perte de pulse.
Le seul document que je connaisse à été fourni en #119.
La vitesse d'exécution dépends de pas mal de choses...
Par exemple 2+3 est calculé plus vite que 222+223...
 
Last edited:

ddaweb

New Member
Merci ddaweb,

Je me posais la question parce que imaginez la situation suivantes où vous effacer un programme de 2000 bytes avec un qui est plus petit, disons 1980 bytes. Qu'arrive t'il avec les espaces de mémoire (20 bytes) du vieux programme qui ne seront pas remplacé par le plus récent ? Sont-ils effacé ou demeure t'il en mémoire causant des interférences ?

Yex
Je ne l'ai jamais utilisée la fonction "Effacer", mais je suppose que c'est pour effacer la programmation dans le picaxe.
Le fait d'envoyer un nouveau programme remplace celui déjà présent dans le picaxe.
Il reboot, donc la ram et les variables en mémoire sont remises à 0.

il existe 2 paramètres en plus dans la programmation, je ne sais pas trop à quoi ils servent (je suppose que cela n'efface pas ces paramètres), les spécialistes pourront mieux y répondre :

Code:
#no_data
#no_table
Autre supposition, si ces paramètres ont été configurés dans l'interface de programmation, ils seront envoyés si ces lignes ne sont pas présentes.
 

BESQUEUT

Senior Member
Merci ddaweb,

Je me posais la question parce que imaginez la situation suivantes où vous effacer un programme de 2000 bytes avec un qui est plus petit, disons 1980 bytes. Qu'arrive t'il avec les espaces de mémoire (20 bytes) du vieux programme qui ne seront pas remplacé par le plus récent ? Sont-ils effacé ou demeure t'il en mémoire causant des interférences ?

Yex
Jamais constaté la moindre interférence: c'est très bien géré.
Quand on voit la complexité du pseudo code qui est interprété par le PIC, on comprend que c'est un travail d'orfèvre...
 

Yex2

Well-known member
Je me suis mal exprimé. Il y a une relation, le même code s'exécute deux fois plus vite, si la vitesse horloge du picaxe est multipliée par deux.
Mais une ligne de code utilisé beaucoup de cycles horloge
MM
Bonjour Michel,

Selon hippy (Technical support) il semblerait qu'en augmentant la vitesse d'horloge ont augmente effectivement la vitesse d’exécution des lignes de code. Voir son post #8 de ce thread : https://picaxeforum.co.uk/threads/function-setint.31574/#post-327532
 

Yex2

Well-known member
Bonjour à tous,

Toujours selon hippy, la vitesse d’exécution de ma routine d'Interrupt est de 5 ms à la fréquence de 4Mz et de 1.3 ms à 16 MHz.

Voir son message #11 @ https://picaxeforum.co.uk/threads/function-setint.31574/#post-327532

La plage d'opération du débitmètre varie de 32 à 90 Hz (on double avec la bascule) donc 64 à 180 Hz. Ce qui donne des pulses entre 15.6 ms et 5.6 ms.

Même avec une vitesse de 4 MHz on serait correct mais à 16 MHz nous avons beaucoup de marge. Pas possible de manquer des pulses.

Bon ce problème est maintenant clos. Je passe à la prochaine étape. Je converti présentement le code pour aller sur un 14M2 et ajouterai les 3 DELs ainsi qu'un autre poussoir pour différencier la calibration et la remise à zéro.
 

Yex2

Well-known member
Voici la version "presque" finale du compteur chalet sur un 14M2 avec 3 DELs. Il subsiste un bug avec les DEL. (voir routine record: )

Lorsque les conditions sont ON pour la rouge ou la verte, celle-ci clignote un coup et s'éteigne.

PS: j'ai trouvé le bug. Voir message #152


Code:
;pour 14M2:sda sur B.4 ; scl sur B.3

#picaxe 14M2                
dirsB =%000111

setfreq M16          
;****** Nominations constantes ********
symbol baud= N2400_16        ;vitesse liaison RS232
symbol cycle    =5        ; temps du cycle de douche en seconde
symbol Ligne1    =128     
symbol Ligne2    =192    
symbol Ligne3    =148     
symbol Ligne4    =212    

;******* 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"
symbol cpt        =b9           ; compteur


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


;******* Nominations ports ***********
symbol calibration =pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées
symbol remise_0     =pinC.3    ; poussoir de remise à zéro des données
symbol ledROUGE     = B.0 
symbol ledJAUNE     = B.1
symbol ledVERTE     = B.2 


#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

 
; Initialisation I2C . pour 14M2:sda sur B.4 ; scl sur B.3
    hi2csetup i2cmaster,%01001110, i2cfast_16, 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.0 = 0 then            ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %01,%01       
    else setint %00,%01
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 or calibration =0 then : gosub calib                           ; Afficher texte de calibration    
    endif                                                 ; pour forcer une calibration à la mise sous tension


main:
    low ledVERTE
    low ledJAUNE
    low ledROUGE

    disabletime            ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records
    if mini =0 then
        mini =10000             ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord

;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 remise_0=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.0 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %01,%01                ; interruption niveau 1 sur C.0
        else setint %0,%01              ; interruption niveau 0 sur C.0
    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:
    low ledVERTE
    low ledJAUNE
    low ledROUGE
 
    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
      high ledVERTE            
    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
      high ledROUGE
    endif

    if mini < today AND maxi > today then
        high ledJAUNE            ; del JAUNE = consommation moyenne
    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                    ;Condition de départ OU aucun record enregistré
       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 4000

etalon =0 : total =0 : today =0      ; valeur remise à zéro
 
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0    ; 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
   NombreLCD(Ligne4,etalon)    ; pour voir la valeur de l'étalon une fois le calibrage terminé
   pause 8000
   time =0 : mini =10000 : maxi =0 : total =0 : today =0 : impulsions =0
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:

Yex2

Well-known member
J'ai trouvé le bug.

Voici la version finale (chalet) sur 14M2 avec 3 DEL:
Fin de cycle de la douche = 180 sec.

Code:
;pour 14M2:sda sur B.4 ; scl sur B.3

#picaxe 14M2                    ;directive picaxe utilisé
dirsB =%000111

setfreq M16             ;fréquence 16MHz
;****** Nominations constantes ********
symbol baud= N2400_16      
symbol cycle    =180      
symbol Ligne1    =128      
symbol Ligne2    =192     
symbol Ligne3    =148       
symbol Ligne4    =212      

;******* 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"  
symbol cpt        =b9           ; compteur


;****** noms variables word *********
symbol etalon    =w13           ; diviseur d'impulsion pour avoir 0.1 litre
symbol total    =w12           ; consommation total
symbol today    =w11           ; dernière douche
symbol mini        =w10        ; consommation miminum
symbol maxi        =w9            ; consommation miminum
symbol impulsions    =w8        ; impulsion du bébitmètre


;******* Nominations ports ***********
symbol calibration =pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées
symbol remise_0     =pinC.3    ; poussoir de remise à zéro des données
symbol ledROUGE     = B.0   
symbol ledJAUNE     = B.1   
symbol ledVERTE     = B.2   


#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

   
; Initialisation I2C . pour 14M2:sda sur B.4 ; scl sur B.3
    hi2csetup i2cmaster,%01001110, i2cfast_16, 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.0 = 0 then            ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %01,%01            ; interruption niveau 1 sur C.0
    else setint %0,%01          ; interruption niveau 0 sur C.0
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:
    low ledVERTE
    low ledJAUNE
    low ledROUGE  

    disabletime            ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records
    if mini =0 then
        mini =10000             ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord

;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
      inc time            ; pour éviter d'entrer à nouveau dans la routine record
    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.0 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %01,%01                ; interruption niveau 1 sur C.0
        else setint %0,%01              ; interruption niveau 0 sur C.0
    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:
   
    low ledVERTE
    low ledJAUNE
    low ledROUGE  
   
    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
      high ledVERTE                ; led VERTE indique un record minimum
    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
      high ledROUGE                 ; led ROUGE indique un record maximum
    endif

    if mini < today AND maxi > today then
        high ledJAUNE            ; del JAUNE = consommation moyenne
    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                    ;Condition de départ OU aucun record enregistré
       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 4000

etalon =0 : total =0 : today =0      ; valeur remise à zéro
   
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0    ; 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
   NombreLCD(Ligne4,etalon)    ; pour voir la valeur de l'étalon une fois le calibrage terminé
   pause 8000
   time =0 : mini =10000 : maxi =0 : total =0 : today =0 : impulsions =0
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
Voici la version finale (voilier) sur 14M2
Fin de cycle autour de 2h30 du matin

Code:
;pour 14M2:sda sur B.4 ; scl sur B.3

#picaxe 14M2                    ;directive picaxe utilisé
dirsB =%000111

setfreq M16             ;fréquence 16MHz
;****** Nominations constantes ********
symbol baud= N2400_16        ;vitesse liaison RS232
symbol cycle    =5      ; temps du cycle à partir du coucher du soleil (8hrs)
symbol Ligne1    =128        ; ligne 1, colonne 1
symbol Ligne2    =192        ; ligne 2, colonne 1
symbol Ligne3    =148        ; ligne 3, colonne 1
symbol Ligne4    =212        ; ligne 4, colonne 1

;******* 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"   
symbol cpt        =b9           ; compteur


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


;******* Nominations ports ***********
symbol calibration =pinC.4    ; poussoir de calibration et de reset des valeurs enregistrées
symbol remise_0     =pinC.3    ; poussoir de remise à zéro des données
symbol PV          =pinC.2    ; Entrée des panneaux solaires pour déclanchement du compteur de cycle
symbol ledROUGE     = B.0    ; Sortie DEL rouge
symbol ledJAUNE     = B.1    ; Sortie DEL jaune
symbol ledVERTE     = B.2    ; Sortie DEL verte


#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

    
; Initialisation I2C . pour 14M2:sda sur B.4 ; scl sur B.3
    hi2csetup i2cmaster,%01001110, i2cfast_16, 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.0 = 0 then            ; armer l'interruption sur le bon niveau selon l'état du débitmètre
    setint %01,%01            ; interruption niveau 1 sur C.0
    else setint %00,%01          ; interruption niveau 0 sur C.0
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 or calibration =0 then : gosub calib                           ; Afficher texte de calibration       
    endif                                                 ; pour forcer une calibration à la mise sous tension


main:
    low ledVERTE
    low ledJAUNE
    low ledROUGE   

    disabletime            ; Pour empêcher l'horloge de tourner et démarrer la fonction d'enregistrement des records
    if mini =0 then
        mini =10000             ; Nécessaire au démarrage sinon la valeur MIN sera toujours = à 0
    endif
    gosub AfficheInitial
    gosub AfficheRecord

;boucle de comptage
do
    if PV =0 then        ; déclanche le timer au couché du soleil.
        enabletime
    else disabletime    : time =0   
    endif
        
    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
      inc time
      today =0            ; consommation quotidienne remise à 0.
    endif

    if remise_0=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

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.0 = 0 then                    ; armer l'interruption sur le bon niveau selon l'état du débitmètre
        setint %01,%01                ; interruption niveau 1 sur C.0
        else setint %0,%01              ; interruption niveau 0 sur C.0
    endif
    return

;calcule les minimums et maxiums

record:
    low ledVERTE
    low ledJAUNE
    low ledROUGE
    
    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
      high ledVERTE               
    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
      high ledROUGE
    endif

    if mini < today AND maxi > today then
        high ledJAUNE            ; del JAUNE = consommation moyenne
    endif
                
    gosub AfficheRecord                    ; afficher les nouveaux résultats

    return

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

AfficheInitial:
    EnvoiLCD(Ligne1,"Conso Total en LITRE")
    EnvoiLCD(Ligne2,"Conso Quotidienne  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= 203    '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                    ;Condition de départ OU aucun record enregistré
       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 4000

 etalon =0 : total =0 : today =0      ; valeur remise à zéro
    
   do
      NombreLCD(Ligne3,total)
   loop until calibration=0    ; 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
   NombreLCD(Ligne4,etalon)    ; pour voir la valeur de l'étalon une fois le calibrage terminé
   pause 8000
   time =0 : mini =10000 : maxi =0 : total =0 : today =0 : impulsions =0
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
Il me reste seulement à faire la console qui recevra l'info des 4 cabines.

Finalement je vais afficher l'information suivante :

AvBab 000 00.0 00.0
AvTri 000 00.0 00.0
ArBab 000 00.0 00.0
ArTri 000 00.0 00.0

Soit la conso total, le maxi et le mini
 

BESQUEUT

Senior Member
Il me reste seulement à faire la console qui recevra l'info des 4 cabines.

Finalement je vais afficher l'information suivante :

AvBab 000 00.0 00.0
AvTri 000 00.0 00.0
ArBab 000 00.0 00.0
ArTri 000 00.0 00.0

Soit la conso total, le maxi et le mini
Il faut ouvrir un nouveau thread pour ça...
J'aime bien le "seulement..."
IMHO faire communiquer 5 picaxes entre eux dans les 2 sens n'est pas trivial.
Mais vous avez l'air confiant.
 

PieM

Senior Member
J'aime bien le "seulement..."
IMHO faire communiquer 5 picaxes entre eux dans les 2 sens n'est pas trivial.
Mais vous avez l'air confiant.
C'est certain qu'assurer la com entre picaxes et la tour de contrôle (!) sans perturber les comptages par interruptions, ça va être coton!
C'est à la fin qu'est dévoilé un élément essentiel du CDC qui risque de tout fiche en l'air...
Car une solution plus futée aurait été d'utiliser count en tant que débitmètre, en intégrant en f(temps) et ce qui permettait en plus de compenser la non linéarité du capteur.
 

Yex2

Well-known member
C'est certain qu'assurer la com entre picaxes et la tour de contrôle (!) sans perturber les comptages par interruptions, ça va être coton!
Relisez mes messages d'hier. J'ai la confirmation qu'il n'est pas possible de perdre des pulses dans mon code. L'Interruption s’exécute en ±1.5 ms alors que la vitesse maximum du débitmètre est de 5.6 ms/pulse dans le cas de 600 L/H, ce qui est largement au dessus du débit de mes douches qui sera plus proche du 15 ms pas pulse...

Et même si on perdait quelques pulse sur 865, qu'est-ce que ça pourrait bien faire ? Une fois calibrer, si des pulses se perd ils se perdront également dans toutes les douches.

C'est à la fin qu'est dévoilé un élément essentiel du CDC qui risque de tout fiche en l'air...
Bien non j'en avais parlé plus haut. Mais vous êtes tellement obsédé par la chasse des bobos que vous ne lisez que ce qui vous permet de rétorquer.

Et de toute façon, si vous lisez mon premier message, je posais une question sur la fonction COUNT. Je n'ai jamais ouvert le sujet avec une demande d'aide pour réaliser projet...

En passant, j'ai déjà réussi à faire communiquer 4 picaxes dans un autre projet (avec l'aide de MGU). Un de plus un de moins, je ne vois pas vraiment le "chalenge"... ;)
 
Last edited:

Yex2

Well-known member
Il faut ouvrir un nouveau thread pour ça...
J'aime bien le "seulement..."
IMHO faire communiquer 5 picaxes entre eux dans les 2 sens n'est pas trivial.
Mais vous avez l'air confiant.
Je suis d'un naturel optimiste. Nous avons survécu à + de 300 ans d'occupation Anglaise. Je n'ai pas de doute que je vais survivre à ce projet. :cool:

Mais plus sérieusement, je ne suis pas à mes débuts en programmation. Le premier code que j'ai appris c'est le Basic justement, il y a ouff "38 ans" :eek: !
J'ai aussi codé Assembler, Binaire (langue machine) Fortran (j'adorais), Perl et j'en oublis. Bref je mis remet et ça me revient...

Dans le projet des sondes capacitives, que je réalisé avec l'aide de MGU, j'ai trois sondes qui communique avec le picaxe central. J'ai étudié le code utilisé et c'est pas sorcier. Un picaxe de plus ou de moins, ça fera pas une grande différence.

J'ai une question concernant votre code suivant :

Code:
AfficheInitial:
    EnvoiLCD(Ligne1,"Conso Total en LITRE")
    EnvoiLCD(Ligne2,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3,"Maximum Enregistre L")
    EnvoiLCD(Ligne4,"Minimum Enregistre L")
    pause 6000
return
Est-it possible de faire des opérations comme incrémenter Ligne1 afin de déplacer l curseur à l'aide d'une loop ?

Ex.:

Code:
    EnvoiLCD(Ligne1+8,"Conso Total en LITRE")
    EnvoiLCD(Ligne2+8,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3+8,"Maximum Enregistre L")
    EnvoiLCD(Ligne4+8,"Minimum Enregistre L")
Ou encore :

Code:
    EnvoiLCD(Ligne1+variable,"Conso Total en LITRE")
    EnvoiLCD(Ligne2+variable,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3+variable,"Maximum Enregistre L")
    EnvoiLCD(Ligne4+variable,"Minimum Enregistre L")
Merci de votre aide BESQUEUT.
 

MGU

Senior Member
Bonjour,

Petit recentrage de débat, afin d'essayer de dégager une ligne directrice, à défaut d'un CDC.
Il y a 4 cabines équipées d'un capteur de volume d'eau. Chaque cabine aurait son propre afficheur (?), avec un comptage journalier: conso du jour, jour max et jour min. La notion de jour reste à définir (je n'en vois pas dans les codes donnés). Je pensais à une simple LDR pour définir la tombée de la nuit, c'est simple et d'une précision suffisante, les PPV me semblent plus difficiles d'emploi.
Et donc maintenant une console centrale pour regrouper et comparer les résultats.
La liaison peut se faire à raison d'une par nuit (filaire RS232, radio...?). Gestion de l'émission et de la réception des infos à préciser.
Y a encore un peu de travail...

MM
 

BESQUEUT

Senior Member
Je suis d'un naturel optimiste. Nous avons survécu à + de 300 ans d'occupation Anglaise. Je n'ai pas de doute que je vais survivre à ce projet. :cool:

Mais plus sérieusement, je ne suis pas à mes débuts en programmation. Le premier code que j'ai appris c'est le Basic justement, il y a ouff "38 ans" :eek: !
J'ai aussi codé Assembler, Binaire (langue machine) Fortran (j'adorais), Perl et j'en oublis. Bref je mis remet et ça me revient...

Dans le projet des sondes capacitives, que je réalisé avec l'aide de MGU, j'ai trois sondes qui communique avec le picaxe central. J'ai étudié le code utilisé et c'est pas sorcier. Un picaxe de plus ou de moins, ça fera pas une grande différence.

J'ai une question concernant votre code suivant :

Code:
AfficheInitial:
    EnvoiLCD(Ligne1,"Conso Total en LITRE")
    EnvoiLCD(Ligne2,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3,"Maximum Enregistre L")
    EnvoiLCD(Ligne4,"Minimum Enregistre L")
    pause 6000
return
Est-it possible de faire des opérations comme incrémenter Ligne1 afin de déplacer l curseur à l'aide d'une loop ?

Ex.:

Code:
    EnvoiLCD(Ligne1+8,"Conso Total en LITRE")
    EnvoiLCD(Ligne2+8,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3+8,"Maximum Enregistre L")
    EnvoiLCD(Ligne4+8,"Minimum Enregistre L")
Ou encore :

Code:
    EnvoiLCD(Ligne1+variable,"Conso Total en LITRE")
    EnvoiLCD(Ligne2+variable,"Conso Quotidienne  L")
    EnvoiLCD(Ligne3+variable,"Maximum Enregistre L")
    EnvoiLCD(Ligne4+variable,"Minimum Enregistre L")
Merci de votre aide BESQUEUT.
Oui ça va marcher.
Ça fait :
Car=ligne4 + variable

Je ne doute nullement de vos compétences et J'ai un parcours très semblable quoique légèrement plus ancien.
La difficulté pour la console centrale est de recevoir simultanément 4 ports série ; je ne vois pas bien comment synchroniser tout ça mais vous semblez détenir une solution que j'ai hâte de connaître.
 
Top