Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Problèmes de compatibilité de types avec les multiplications.
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#1 Message par Superphénix » dim. 14 mai 2023 16:08 lien vers la Data-Sheet : Cliquez ici

Bonjour

Ça fait un jour que j'essaye de résoudre et de comprendre un problème avec des histoires de compatibilité de types en faisant des essais et je vais devenir fou. :mur: Du coup je vais plutôt poser la question ici. :-D

Je suis toujours sur la programmation d'un PIC18LF2620 pour faire marcher un capteur de type MS5837-02BA21.
Là je suis sur la partie calculs pour compenser l'erreur en fonction de la température en suivant plus ou moins ce qui est donné dans le datasheet.

Pour la partie "Pressure and temperature calculations: first order" je pense avoir réussit, puisque j'obtiens des valeurs crédibles.
Pour la partie "Second order", j'ai que des valeurs du genre 4.294.846.294 au lieux de quelque chose comme 101435 mBARx100 par exemple.
Je pense que le problème est au niveau de la ligne "Ti = (dT*dT*11)>>35 ;". Ti est de type long long et dT long.
En décomposant (de façon un peu abusé) en :

Code : Tout sélectionner

            var_inter64 = (long long)dT*(long long)dT ;
            var_inter64 = var_inter64*11 ;
            var_inter64 = var_inter64>>35 ;
            Ti = var_inter64 ;

pour tester, j'obtiens des valeurs plus crédibles sur dT mais, je suis pas sur d'avoir compris ce qui se passe et si les valeurs "crédibles" sont aussi les bonnes. :?

Voilà ce que j'ai fais pour l'instant :

Code : Tout sélectionner

unsigned long long  C1=0, C2=0, C3=0, C4=0, C5=0, C6=0 ;                    // 64 Bits + , Normalement 16Bits mais ici 64 pour les calculs par la suite.
signed long long    OFF=0, OFF2=0, SENS=0, SENS2=0, Ti=0, var_inter64=0 ;   // 64 Bits ±
signed long         dT=0, TEMP=0, TEMP2=0, OFFi=0, SENSi=0, P=0 ;           // 32 Bits ±
__uint24            D1=0, D2=0, P2=0 ;                                      // 24 Bits +


Code : Tout sélectionner

write_MS5837(0x1E) ;   // RESET MS5837
    C1 = read_MS5837(0b10100010, 2) ;   // C1
    C2 = read_MS5837(0b10100100, 2) ;   // C2
    C3 = read_MS5837(0b10100110, 2) ;   // C3
    C4 = read_MS5837(0b10101000, 2) ;   // C4
    C5 = read_MS5837(0b10101010, 2) ;   // C5
    C6 = read_MS5837(0b10101100, 2) ;   // C6
    C5 = C5<<8 ;
    C2 = C2<<17 ;
    C1 = C1<<16 ;


Code : Tout sélectionner

    while(1)
    {
        D1 = read_MS5837(0x4A, 3) ;         // D1, OSR=8192
        D2 = read_MS5837(0x5A, 3) ;         // D2, OSR=8192
       
        // T° et P au 1er ordre :
        dT = D2 - C5 ;
        TEMP = ((C6*dT)>>23) + 2000 ;
        OFF = C2 + ((C4*dT)>>6) ;
        SENS = C1 + ((C3*dT)>>7) ;
       
        // T° et P au 2nd ordre :
        if(TEMP>=2000)
        {
            P = (((D1*SENS)>>21) - OFF)>>15 ;
        }
        else
        {
            Ti = (dT*dT*11)>>35 ;
            var_inter64 = TEMP-2000 ;
            var_inter64 = var_inter64 * var_inter64 ;
            OFFi = (31*var_inter64)>>3 ;
            SENSi = (63*var_inter64)>>5 ;
           
            OFF2 = OFF - OFFi ;
            SENS2 = SENS - SENSi ;
            TEMP = TEMP - Ti ;
            P = ((((D1*SENS2)>>21) - OFF2)>>15) ;
        }
    }

Problèmes de compatibilité de types avec les multiplications.
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#2 Message par satinas » dim. 14 mai 2023 17:13 lien vers la Data-Sheet : Cliquez ici

Hello,
J'ai pas tout lu, une première info.
Lorsqu'on fait R = A*B, le langage C commence par évaluer l'expression A*B sans tenir compte de R, puis il fait R = valeur obtenue.
Pour calculer A*B, il prend la taille maxi de A et B. Si A est un int et B un long, il calcule un long, avec éventuellement un débordement si le résultat ne rentre pas dans un long. Ensuite il met le résultat dans R, résultat faux s'il y a eu débordement.
Il faut toujours gérer soi même les éventuels débordements, avec un cast explicite :
long long R = (long long)A * B;
Ou avec une conversion implicite :
long long R = A; R = R * B;
Il y a peut être des petites différences selon les versions de C, mais en gros cela marche comme ça.

Problèmes de compatibilité de types avec les multiplications.
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#3 Message par satinas » dim. 14 mai 2023 21:26 lien vers la Data-Sheet : Cliquez ici


Problèmes de compatibilité de types avec les multiplications.
Superphénix
Débutant
Débutant
Messages : 54
Enregistré en : mars 2020

#4 Message par Superphénix » mar. 16 mai 2023 14:23 lien vers la Data-Sheet : Cliquez ici

Merci ! En modifiant mon programme juste de sorte à tenir compte de ça, j'obtiens que des valeurs cohérentes.
Et merci pour le lien Github ! :)


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 106 invités