demande d'aide sur les priorités des opérations sur l'arduino

Bonjour
Alors en premiers je plante le décors:
70 ans, le Certificat d'études primaire en poche.
A cette époque je n'ai appris que le "calcul"
pour autant je me débrouille convenablement dans la vie.

Mais la je ne comprend pas, soyez indulgent et pédagogue . Merci

Je reprend mon vieux prog en visual basic que j'ai écrit il y a une quinzaine d'années. En visual basic mes opérations s'effectuaient mais pas sur l'arduino!certainement un soucis de priorité.

J'ai lu (sans comprendre) la page sur les priorités en C++!

j'ai lu cela mais sans trouver d'exemple pour mon cas:

ce que j'ai écrit avec debug:

maintenant = RTC.get();
if ( (maintenant - depart) > 60 ) {   
    #ifdef DebugL1
    Serial.println( "1 minutes vient de passer" );
    #endif

Lecture_Compteur = hchc + hchp ;
Secondes_entre_deux_mesures = maintenant - depart;
Compteur_New = Lecture_Compteur;
     #ifdef DebugL1
      Serial.print( "compteur NEw = " );
      Serial.println( Compteur_New );
      Serial.print( "compteur old avant inversion = " );
     Serial.println( Compteur_Old );
    #endif 
 
 if ((Compteur_Old )== 0){
    Compteur_Old = Compteur_New;
  }
    Kwh_Consommes = ((Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures) * 3600;
    
    Compteur_Old = Compteur_New;
  #ifdef DebugL1
   Serial.print( "compteur old apres inversion = " );
   Serial.println( Compteur_Old );
  #endif 
    
    depart = RTC.get(); // Re-capturer l'heure
   
  #ifdef DebugL1
    Serial.print( " secondes entre deux  mesures = " );
    Serial.println(Secondes_entre_deux_mesures);
    Serial.print( " Kwh_Consommes = " );
    Serial.println(Kwh_Consommes);
    #endif

La "formule" qui me cause soucis (en fait me retourne toujours 0):

 Kwh_Consommes = ((Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures) * 3600

j'essaie de faire:
-Compteur_New - Compteur_Old)

puis ce résultat divisé par: Secondes_entre_deux_mesures

puis multiplié par 3600

exemple
20-10 / 60 * 3600 =600
or ma ligne me retourne toujours Zéro!

j'ai essayé long et unsigned long
Je suis perdu merci.

C’est surtout un problème de calcul avec des entiers. J’ai eu le même genre de problème sur un post récent, J-M-L l’a résolu (voir réponses 9 et suivantes).

Pour ton code, c’est difficile à corriger car on ne connait pas les types de variables utilisées, mais si c’est des int, il doit y avoir le même problème de dépassement de la limite (32767) ou d’arrondi à 0 d’un résultat inférieur à 1.

Si ta division

(Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures)

donne un résultat inférieur à 1 (genre 0.23), il est arrondi à 0 (si tu as des int, quels qu’ils soient, long, unsigned, etc) et tu peux multiplier ça par 3600 autant de fois que tu veux, ça reste égal à 0.

Donc :

  • Si tes résultats sont toujours positifs, passe en unsigned.
  • Si ta différence (Compteur_New - Compteur_Old) reste inférieure (toujours !) à 32767/3600 soit 9, tu peux rester en int, sinon passe en long et multiplie avant de diviser :
unsigned long Kwh_Consommes = (Compteur_New - Compteur_Old) * 3600ul / Secondes_entre_deux_mesures;

Au besoin, tu castes tout en unsigned long, c’est plus lourd mais ça assure :

unsigned long Kwh_Consommes = ((unsigned long)Compteur_New - (unsigned long)Compteur_Old) * 3600ul / (unsigned long)Secondes_entre_deux_mesures;

Bonjour Alain-Alph

Alain-alph:
certainement un soucis de priorité.

La "formule" qui me cause soucis (en fait me retourne toujours 0):

 Kwh_Consommes = ((Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures) * 3600

j'essaie de faire:
-Compteur_New - Compteur_Old)

puis ce résultat divisé par: Secondes_entre_deux_mesures

puis multiplié par 3600

exemple
20-10 / 60 * 3600 =600
or ma ligne me retourne toujours Zéro!

j'ai essayé long et unsigned long

1/ En ce qui concerne les priorités peut être résolu par l'emploi de parenthèses.

2/ Comme signalé par lesept (entre autres conseils utiles), multiplier avant de diviser est important ( pour éviter et/ou minimiser les problèmes de troncature ( calculs en entier ) et/ou de précision.

3/ IL EST NECESSAIRE DE POSTER LE CODE EN ENTIER.

Cordialement,
bidouilleelec

Bonjour Alain-alph d’un aussi vieux du Visual Basic

Alain-alph:
Je reprend mon vieux prog en visual basic que j’ai écrit il y a une quinzaine d’années. En visual basic mes opérations s’effectuaient mais pas sur l’arduino!certainement un soucis de priorité.

Que de plaisirs j’ai eu avec le Visual Basic et j’en ai encore dans Excel avec VBA.

Tu as très bien respecté les priorités, le problème est alleurs, tu a certainement déclaré des variables

Compteur_New et Compteur_Old

en integer (int)

20-10 / 60 * 3600 =600
Alors 20-10 = 10 10/60 = 0 0 * 3600 = 0

en flottantes (float)
Alors 20-10 = 10.0 10.0/60 = 0.17 0.17 * 3600 = 600

int Kwh_Consommes, Secondes_entre_deux_mesures; float Compteur_New, Compteur_Old;
//int Compteur_New, Compteur_Old, Kwh_Consommes, Secondes_entre_deux_mesures;

void setup()
{
	Serial.begin(115200);
	// 20-10 / 60 * 3600 =600
	Compteur_Old = 10;
	Compteur_New = 20;
	Secondes_entre_deux_mesures = 60;
	
	Kwh_Consommes = ((Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures) * 3600;
	

	Serial.println(Kwh_Consommes);
while(1){};	
}

Essayes avec la première ligne de définition des variables et ensuite avec la 2ème en déplacement la remarque //

Bonne programmation
Coirdialement
jpbbricole

Bonjour jpbbricole

jpbbricole:
Tu as très bien respecté les priorités, le problème est alleurs, tu a certainement déclaré des variables

Compteur_New et Compteur_Old

en integer (int)

20-10 / 60 * 3600 =600
Alors 20-10 = 10 10/60 = 0 0 * 3600 = 0

en flottantes (float)
Alors 20-10 = 10.0 10.0/60 = 0.17 0.17 * 3600 = 600

Je n'aurais pas dit que les priorités ont bien été respectées car :
( (20 - 10 ) * 3600 ) / 60
est préférable , même si il n' exclut pas la possibilité de débordement

Très cordialement,
bidouilleellec

Bonjour a tous et vraiment merci pour toute cette aide.
C'est difficile de se débrouiller seul dans son coin, même si le net regorge de tutos.
-Bon ça marche avec la ligne de lesept (a qui je vais devoir envoyer des chocolats vue le nombres de fois que ce dernier me sort de l'impasse)

Alors j'avais essayé long et unsigned long. Malgré tout le résultat restait a zéro!

en essayant cette ligne ça c'est mis a calculer correctement mais les valeurs (il me semble ) n'étaient pas accessible en dehors de la fonction.

unsigned long Kwh_Consommes = ((unsigned long)Compteur_New - (unsigned long)Compteur_Old) * 3600ul ;

j'ai adapté a mon code et miracle ça marche, mais je ne sais pas pourquoi

unsigned int papp = 0;// Puissance apparente, VA
char ptec[4] = ""; // Période Tarifaire en cours, 4 alphanumériques (HC.. ou HP..)
unsigned int iinst = 0; // Monophasé - Intensité Instantanée, A  (intensité efficace instantanée)
unsigned long hchc = 0; // contient l'index compteur Heure creuse
unsigned long hchp = 0; // contient l'index compteur Heure pleine

unsigned long Lecture_Compteur = 0; // pour le calcul des KW/h
unsigned long Kwh_Consommes = 0; // pour le calcul des KW/h
unsigned long Compteur_New = 0; // pour le calcul des KW/h
unsigned long Compteur_Old = 0; // pour le calcul des KW/h
unsigned long Secondes_entre_deux_mesures = 0 ; // pour le calcul des KW/h

  Kwh_Consommes = (Compteur_New - Compteur_Old) * 3600ul / Secondes_entre_deux_mesures;

Les différences entre ma façon de faire et celle de Lesept c'est qu'il a changé l'ordre des opérations et je pense que cela vient de la, si vous pouvez m'expliquer simplement.

  • Ma façon:en première ligne
  • Lesept en deuxième ligne.
    Pourtant
    Ca marchait en basic et sur ma calculette également. Un peu perdu la!
  • ce que fait ce calcul: il compte l'énergie en faisant la soustraction des index du compteur EDF (en WAtts) divise par le temps en secondes et multiplie par le nombres de secondes en 1 Heure.

Dans mes variables compteurs j'ai entre 0 et au grand maxi 100. 100 donnant 6KW/h

Kwh_Consommes = ((Compteur_New - Compteur_Old) / Secondes_entre_deux_mesures) * 3600;

Kwh_Consommes = (Compteur_New - Compteur_Old) * 3600ul / Secondes_entre_deux_mesures;

J'essaie déja de comprendre ça avant de'essayer de comprendre les autres réponses.

  • En basic (depuis les années 80 je me débrouille)
  • en PHP/SQL aussi, mais avec l'arduino j'ai vraiment du mal. Quoi que le langage arduino soit plaisant.
    Voila a quoi sert mon prog en basic qui j'espère sera remplacé par un arduino moins énergivore que le portable qui tourne 24/24H.
    https://mateleinfo.shost.ca/EDF/teleinfograph.php

PS que veut dire UL après un nombres j'ai vue cela plusieurs fois. Merci

Lis le message de jpbbricole pour comprendre l’ordre des opérations. Si tu as des variables entières (int), les divisions sont faites sur des entiers :

  • Par exemple, 30 divisé par 7 vaudra 4, alors que ta calculette te donnera un résultat avec des chiffres après la virgule.
  • Mais 12 divisé par 48 te donnera 0 au lieu de 0.25
  • Si ensuite tu dois multiplier par 3600, ça restera à 0.

Par contre si tu multiplies avant de diviser, tu feras 12 * 3600 = 43200 et ensuite 43200 / 48 = 900 ce qui est le bon résultat.
Le passage en long permet juste d’éviter de saturer lors de la multiplication, et le unsigned ajoute un peu de place en plus si tu es sûr que tu utiliseras toujours des entiers positifs.

Pour les chocolats, on verra hors antenne … :grin:

Bonsoir Alain-alph,

Alain-alph:
PS que veut dire UL après un nombres j’ai vue cela plusieurs fois. Merci

UL == Unsigned Long

Cordialement,
bidouilleelec

Bonsoir a tous et merci.
Désolé de ne pas avoir fait signe plus tôt: petit soucis.
En tout cas merci pour votre aide j’ai bien compris… enfin je pense.
Mais si de nouveau j’ai des soucis je reviendrais vers vous
et si je ne reviens pas avant noël, alors bonne fêtes de fin d’année a tous.
Alain

PS:

Bonjour Alain-alph d’un aussi vieux du Visual Basic

je me sert encore de VB Version 6 et ça me dépanne c’est très facile d’emploie, mais revers de la médaille parfois il y a des resultats inattendus!
Par contre au niveau Débug c’est géant avec l’exécution pas pas ou les points d’arrêt ou il n’y a qu’a poser le curseur de sa souris pour voir le contenue d’une variable.
Dommage que l’éditeur Arduino ne possède pas les même outils de deboggage.