Search code examples
sensorsavri2ccalculationatmega32

Result of adding numbers in AVR MCU is not corrext


I program the BMP280 sensor (pressure and temperature sensor) with the AtMega32. One of the elements of measuring with a sensor is the conversion of the "raw" value into a "human readable" value, I have to read the calibration values from the registers. I manage to read all the values, except one, and actually I manage to read it correctly, but for unknown reasons, the MCU miscalculates the value - first you have to read the LSB, then the MSB, and then sum them up to one number. Here is the code:

uint8_t cmd[2] = {0xD0, 0};
uint8_t msb1 = 0;
uint8_t lsb1 = 0;
char str[32];
 
//lsb1 = 6
cmd[0] = 0x8E;
tw_master_transmit(0x76, cmd, 1, 0);
tw_master_receive(0x76, cmd, sizeof(cmd));
lsb1 = cmd[0];
 
//msb1 = 150
cmd[0] = 0x8F;
tw_master_transmit(0x76, cmd, 1, 0);
tw_master_receive(0x76, cmd, sizeof(cmd));
msb1 = cmd[0];
 
//uart print
sprintf(str, "%d.%05u\r\n", (int)lsb1, (int)((lsb1 - (int)lsb1) * 100000));
print_string(str);
sprintf(str, "%d.%05u\r\n", (int)msb1, (int)((msb1 - (int)msb1) * 100000));
print_string(str);
 
//should be msb1*256+lsb1=38406, but actually is -27130
uint16_t dig_p1 = (msb1<<8) | lsb1;
 
//uart print
sprintf(str, "%d.%05u\r\n", (int)dig_p1, (int)((dig_p1 - (int)dig_p1) * 100000));
print_string(str);

The values in the variables lsb1 and msb1 are surely well read (checked with the Nucleo), and the value of dig_p1 should be 38406 (also checked with the Nucleo), but MCU shouws -27130. The rest of the values are calculated correctly. What is wrong?


Solution

  • Note int in AVR is 16-bit wide, and can store values from -32768 to 32767.

    in their binary representation (10010110 00000110) -27130 (signed) equals to 38406 (unsigned)

    If you want to get unsigned result use %u instead of %d in sprintf:

    sprintf(str, "%u.%05u\r\n", dig_p1, (int)((dig_p1 - (int)dig_p1) * 100000));