Desbordamiento absurdo :(

Hola buenas tardes, este es uno de esos topics los cuales no tiene sentido pero si una explicacion:

la verdad estan simple y tan absurdo que suceda este error que me frustra demasiado:

tengo este bloque en mi codigo:

// variable declarada
unsigned long  doseX=0;

el siguiente error se me presenta en una de mis operaciones el cual no quiero explicar porque seria demasiado largo, lo que les voy a presentar es el mismo error

BLOQUE CON DERBORDAMIENTO:

doseX = ((13)*(10000));
Serial.println(doseX);

en mi impresion tengo esto "4294966224" la variable se me desborda y es absurdo el resultado deberia ser 130 000 y no tiene porque desbordarse

AHORA, si yo añado un cero mas, es decir de "10 000" a "100 000" el resultado ya no se derborda

doseX = ((13)*(100000));
Serial.println(doseX);

tengo en mi impresion "1300000"

Si haces asi, tampoco se desborda

// variable declarada
unsigned long  doseX=0;

void setup() {
    Serial.begin(9600);
    doseX = (unsigned long) 13*10000;
    Serial.println(doseX);
}

void loop() {

}

El tema es que tanto 13 como 10000 se pueden representar como enteros. El compilador hace las cuentas de ese modo y claramente se desborda. Pero si agregas el typecast (unsigned long) le dices al compilador que considere la cuenta del tipo unsigned long y entonces corriges el problema.

ok muchas gracias, lo revisare si me funciona dare por resuelto el tema y dejare como consejo de buenas practicas

En realidad hacer el cast de una operación puede también generar un problema, por ejemplo:

doseX = (unsigned long)((13*10000)+1);

da como resultado 4294966225

Lo correcto es utilizar constantes long

doseX = 13L*10000L;
doseX = ((13L*10000L)+1L);

Me corrijo. En este caso al ser unsigned long:

doseX = 13UL*10000UL;
doseX = ((13UL*10000UL)+1UL);

No estoy para nada en desacuerdo con lo expresado por PeterKanTropus sin embargo miren esta curiosidad

doseX = (unsigned long) 13*10000+1;

qué resultado les parece que da?

Pues

130001

Sin embargo

doseX = (unsigned long)((13*10000)+1);

da 4294966225

De modo que los paréntesis parecen ser los responsables, pero no puedo afirmarlo aún.
Haré mas pruebas.

este es el bloque donde tengo los problemas!

        for(int i=41; i <= 76; i++){
           /******************************SAVE THE FEED ON*****************************/
           EEPROM.update(((i-41)+33),frameReceived[i]);
           if(countF == 0){
               doseX += (unsigned long)(frameReceived[i] * (10000));
               countF++;
               Serial.println(doseX);
           }
           else if(countF == 1){
               doseX += (unsigned long)(frameReceived[i] * (100));
               countF++;
               Serial.println(doseX);
           }
           else if(countF == 2){
               doseX += (unsigned long)(frameReceived[i]);
               Serial.println(doseX);
               dose[p] = doseX;
               doseX = 0;
               p++;
               countF = 0;
           }
       
       }
   }

estoy resiviendo datos en api mode in xbee, lo que voy capturando en ciertas posiciones lo cancateno haciendo uno suma y multiplicaciones para recorrer los digos, y es ahi donde se me desborda cuando le llega un 0x0D o 13 que es lo miso (13*10000), pero que curioso que solo al multiplicar por 10k sucede eso si añado o quito un 0 ya no se desborda, como ven ya añado (unsigned long) (framereceived *10000; y se sigue desvordando

Muchas gracias por su ayuda, esto fue lo que me ayudo!

    if(frameReceived[16] == 'A'){
        Serial.println("\n Tabla AM");

        for(int i=17; i <= 28; i++){
            arrayHour[p] = frameReceived[i]; 
            EEPROM.update((p+9),frameReceived[i]);
            /*Save Values beign block 9*/
            p++;
        }
        p = 0;
        for(int i=29; i <= 40; i++){
            frequency[p] = frameReceived[i];
            EEPROM.update((p+21),frameReceived[i]);
            /*Save Values begin block 21*/
            p++;
        }
        p = 0;
        for(int i=41; i <= 76; i++){
            /******************************SAVE THE FEED ON*****************************/
            EEPROM.update(((i-41)+33),frameReceived[i]);
            if(countF == 0){
                doseX += (frameReceived[i] * 10000UL);
                countF++;
                Serial.println(doseX);
            }
            else if(countF == 1){
                doseX += (frameReceived[i] * 100UL);
                countF++;
                Serial.println(doseX);
            }
            else if(countF == 2){
                doseX += frameReceived[i];
                Serial.println(doseX);
                dose[p] = doseX;
                doseX = 0;
                p++;
                countF = 0;
            }
        
        }
    }

    // If the first byte is a 'P' save the information to the PM cycle.
    if(frameReceived[16] == 'P'){
        p = 12;

        Serial.println("\n Tabla PM");

        for(int i=17; i <= 28; i++){
            arrayHour[p] = frameReceived[i];
            /**********save the hour PM from position 69 (12 init + 57 is equal to the new case*/
            EEPROM.update((p+57),frameReceived[i]);
            p++;
        }
        p = 12;
        for(int i=29; i <= 40; i++){
            frequency[p] = frameReceived[i];
            EEPROM.update((p+69),frameReceived[i]);
            p++;
        }
        p = 12;
        for(int i=41; i <= 76; i++){
            EEPROM.update(((i-41)+93),frameReceived[i]);
            if(countF == 0){
                doseX += (frameReceived[i] * 10000UL);
                countF++;
                Serial.println(doseX);
            }
            else if(countF == 1){
                doseX += (frameReceived[i] * 100UL);
                countF++;
                Serial.println(doseX);
            }
            else if(countF == 2){
                doseX += frameReceived[i];
                Serial.println(doseX);
                dose[p] = doseX;
                doseX = 0;
                p++;
                countF = 0;
            }
        }
    }

Surbyte en ambos casos esto funciona porque

doseX = (unsigned long) 13*10000;
doseX = (unsigned long) 13*10000+1;

Es equivalente a hacer

doseX = ((unsigned long) 13)*10000;
doseX = ((unsigned long) 13)*10000+1;

Es decir, esta haciendo el cast al numero 13, convirtiéndolo en un unsigned long (UL) y el compilador al tener un UL en la cuenta trabaja todo como UL

en cambio

doseX =(unsigned long)(13*10000);

(13*10000)
es el producto de dos integer y en exa el resultado es: 1fbd0. El uno se desborda y queda fbd0, ahora (no se porque ) al intentar meterlo en un UL le agrega FFFF y queda FFFFfbd0 que en decimal es 4294966224.

Jorge, por el motivo que puse mas arriba

doseX += (frameReceived[i] * 10000UL);

esta funcionando porque uno de los términos de la operación es un Unsigned Long (10000UL) y el compilador realiza todos los cálculos con UL, pero es una buena practica tener todos los términos del mismo tipo. En tu caso frameReceived debe devolver un integer, por eso tuviste problemas en un principio. lo correcto seria tener todo como UL
* *doseX += ( (unsigned long) frameReceived[i] * 10000UL);* *
Prueba hacer
* *doseX += ( (unsigned long) frameReceived[i] * 10000);* *
y veras que también funciona
pero no funcionara
* *doseX += (unsigned long)(frameReceived[i] * (10000));* *

Y por cierto, queda claro que no es un desbordamiento absurdo, sino como suele ocurrir un error que se comete por mala interpretación o mal uso del tipo de variable involucrada en las operaciones.