problema de calibración dspic MPU6050

2

Uso dspic33fj128gp802 y MPU6050 para mi proyecto. El microcontrolador toma con éxito los datos del canal de sensores 6 y envía la PC de datos a través de UART. Cuando quiero agregar "float 2.0" o "int 2" a los datos del acelerómetro para la calibración, se detiene el envío de datos a uart. He intentado todas las combinaciones de tipos de datos pero siempre falla. Solo agrego una línea de código a mi código fuente, pero cuando agrego, el código no envía datos a la PC. Yo uso MikroC pro para dspic. La línea recién agregada se puede ver en el código fuente como negrita en función de Extract_Readings. Esta línea recién agregada no genera ningún error de compilación o depuración.

accel_z = (float) accel_z + 2.0;

Como solución cuando cambio la última línea a accel_z = (float) accel_z / 2.0;

divide con éxito el resultado en 2. Como resumen, el operador de división funciona bien pero el operador de adición no funciona.

No puedo encontrar ninguna solución. Estoy esperando sus consideraciones.

Gracias.

El código fuente está abajo:

 #include "MPU_IMU_Register_Map.h"

unsigned int raw_data[7];

sbit INT at RB7_bit;
sbit INT_Direction at TRISB7_bit;

int gyro_x_temp, gyro_y_temp, gyro_z_temp, accel_x_temp, accel_y_temp, accel_z_temp, temp_raw;
char i, buff, gyro_x_out[15], gyro_y_out[15], gyro_z_out[15], accel_x_out[15], accel_y_out[15], accel_z_out[15], temp_out[15];
float temp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z;

void MCU_Init(){
  ADPCFG = 0xffff;

  TRISBbits.TRISB10 = 1;
  TRISBbits.TRISB11 = 0;
  Delay_ms(100);

  RPINR18bits.U1RXR = 10;
  RPOR5bits.RP11R   = 3;

  INT_Direction = 1;
  I2C1_Init(400000);
  Delay_ms(100);

  Delay_ms(100);
  UART1_Init_Advanced(19200, 1, 1, 1);
  Delay_ms(600);

  UART1_Write_Text("MCU Ready\n");
  Delay_ms(100);
}
void MPU_I2C_Write(unsigned char s_addr, unsigned char r_addr, unsigned char len, unsigned char *dat) {
 unsigned int i;
 I2C1_Start();                         // issue I2C start signal
 I2C1_Write(s_addr & 0xFE);            // send byte via I2C  (device address + W(&0xFE))
 I2C1_Write(r_addr);                   // send byte (address of EEPROM location)
 for (i = 0 ; i < len ; i++){
  I2C1_Write(*dat++);                 // send data (data to be written)
 }
 I2C1_Stop();                          // issue I2C stop signal

}

void MPU_I2C_Read(unsigned char s_addr, unsigned char r_addr, unsigned char len, unsigned char *dat) {
 unsigned int i;
 I2C1_Start();                         // issue I2C start signal
 I2C1_Write(s_addr & 0xFE);            // send byte via I2C  (device address + W(&0xFE))
 I2C1_Write(r_addr);                   // send byte (data address)
 I2C1_Restart();                       // issue I2C signal repeated start
 I2C1_Write(s_addr | 0x01);            // send byte (device address + R(|0x01))
 for (i = 0; i < (len-1); i++){
  *dat++ = I2C1_Read(_I2C_ACK);       // Read the data (acknowledge)
  }
  *dat = I2C1_Read(_I2C_NACK);          // Read the data (NO acknowledge)
 I2C1_Stop();                          // issue I2C stop signal
 }

void MPU_I2C_Read_Int(unsigned char s_addr, unsigned char r_addr, unsigned char len, unsigned char *dat) {
  unsigned int i;
  unsigned short *pt;
  I2C1_Start();                         // issue I2C start signal
  I2C1_Write(s_addr & 0xFE);            // send byte via I2C  (device address + W(&0xFE))
  I2C1_Write(r_addr);                   // send byte (data address)
  I2C1_Restart();                       // issue I2C signal repeated start
  I2C1_Write(s_addr | 0x01);            // send byte (device address + R(|0x01))
  for (i = 0 ; i < ((len << 1)-1) ; i++){
   if (i%2) {
     pt = pt - 1;
   }
   else {
     pt = dat + i + 1;
   }
    *pt = I2C1_Read(_I2C_ACK);          // Read the data (acknowledge)
  }
  *(pt - 1) = I2C1_Read(_I2C_NACK);     // Read the data (NO acknowledge)
  I2C1_Stop();                          // issue I2C stop signal
}


void MPU_Init(){
 MPU_I2C_Write(mpu_I2C_ADDR, mpu_rm_PWR_MGMT_1 , 1, 0x80);
 Delay_ms(100);
 MPU_I2C_Write(mpu_I2C_ADDR, mpu_rm_PWR_MGMT_1 , 1, 0x00);
 Delay_ms(100);

 MPU_I2C_Write(mpu_I2C_ADDR, mpu_rm_FIFO_EN , 1, 0x78);
 Delay_ms(100);

 MPU_I2C_Write(mpu_I2C_ADDR, mpu_rm_INT_ENABLE , 1, 0x10);
 Delay_ms(100);

 MPU_I2C_Read (mpu_I2C_ADDR, mpu_rm_ACCEL_CONFIG, 1, &raw_data);
 Delay_ms(100);


 MPU_I2C_Read (mpu_I2C_ADDR, mpu_rm_INT_ENABLE, 1, &raw_data);
 Delay_ms(100);

 raw_data[0] |= 0x11;
 MPU_I2C_Write(mpu_I2C_ADDR, mpu_rm_INT_ENABLE, 1, &raw_data[0]);
 Delay_ms(100);
 UART1_Write_Text("MPU6050 Hazir\n");

}
void Extract_Readings() {

 accel_x_temp = raw_data[0];
 accel_x = (float)accel_x_temp / 2048.0;
 accel_y_temp = raw_data[1];
 accel_y = (float)accel_y_temp / 2048.0;
 accel_z_temp = raw_data[2];
 accel_z = (float)accel_z_temp / 2048.0;
 **accel_z = (float) accel_z + 2.0;** //When this line deleted or changed to accel_z = (float) accel_z /2.0, code works well

 temp_raw = raw_data[3];

 temp = (float)temp_raw / 325.0;

 gyro_x_temp = raw_data[4];
 gyro_x = (float)gyro_x_temp / 131.0;
 gyro_y_temp = raw_data[5];
 gyro_y = (float)gyro_y_temp / 131.0;

 gyro_z_temp = raw_data[6];
 gyro_z = (float)gyro_z_temp / 131.0;

}
void Convert_Readings_To_String() {

FloatToStr(accel_x, accel_x_out);
FloatToStr(accel_y, accel_y_out);
FloatToStr(accel_z, accel_z_out);


FloatToStr(temp, temp_out);


FloatToStr(gyro_x, gyro_x_out);
FloatToStr(gyro_y, gyro_y_out);
FloatToStr(gyro_z, gyro_z_out);

}


void Print_Readings() {

 Delay_ms(500);
 UART1_Write_Text("\nGyro readings:\n");
 UART1_Write(0x0D);
 UART1_Write_Text("\nx = \n");
 UART1_Write_Text(gyro_x_out);
 UART1_Write(0x0D);
 UART1_Write_Text("\ny = \n");
 UART1_Write_Text(gyro_y_out);
 UART1_Write(0x0D);
 UART1_Write_Text("\nz = \n");
 UART1_Write_Text(gyro_z_out);
 UART1_Write(0x0D);
 UART1_Write(0x0D);
 UART1_Write(0x0D);


 UART1_Write_Text("\nAccel readings:\n");
 UART1_Write(0x0D);
 UART1_Write_Text("\nx = \n");
 UART1_Write_Text(accel_x_out);
 UART1_Write(0x0D);
 UART1_Write_Text("\ny = \n");
 UART1_Write_Text(accel_y_out);
 UART1_Write(0x0D);
 UART1_Write_Text("\nz = \n");
 UART1_Write_Text(accel_z_out);
 UART1_Write(0x0D);
 UART1_Write(0x0D);
 UART1_Write(0x0D);


 UART1_Write_Text("\nTemperature readings (Celsius) = ");
 UART1_Write_Text(temp_out);
 UART1_Write(0x0D);
 UART1_Write(0x0D);
 UART1_Write(0x0D);
 Delay_ms(1000);


}
void main() {

 MCU_Init();
 MPU_Init();
 while(1) {
 while(INT != 1)
  ;
 MPU_I2C_Read_Int(mpu_I2C_ADDR, mpu_rm_ACCEL_XOUT_H, 7, &raw_data);
 Extract_Readings();
 Convert_Readings_To_String();
 Print_Readings();
}


}   
    
pregunta Kamil Gumusoglu

1 respuesta

1

El problema que tiene es la precisión del punto flotante. Como regla general, NO use puntos flotantes si puede evitarlo.

Se ha escrito mucho sobre por qué no usarlos, por lo que no voy a entrar en demasiados detalles. Consulte el enlace .

Lo que probablemente esté obteniendo es redondeo de errores y probablemente se esté quedando sin pila y montón. Por ejemplo, 0.1, el número decimal más simple que se pueda imaginar, se ve así en un binario de 32 bits:

0.1 (Most accurate representation) = 1.00000001490116119384765625E-1e
Exponent        Mantessa
01111011        10011001100110011001101

En realidad, este número continúa redondeando al infinito.

Solución simple, NO use flotadores, simplemente multiplique todas las lecturas de su sensor por 1000 para deshacerse del decimal y léalas con la precisión Milli

    
respondido por el Tinez

Lea otras preguntas en las etiquetas