Witam.

Czy ma ktoś pomysł jak mógłbym zrobić kompensację przechyleń w czujniku HMC5883L to co znalazłem na necie nie za bardzo działa.
Układ pochylany będzie tylko w jednej osi, czyli wokół osi y. Znany jest kąt przechylenia i wartości x,y,z z kompasu.
Nie za bardzo rozumiem pomiary z x, wg. mnie powinno być tak, że wartość x jest taka sama dla przechylenia +30 stopni i -30 stopni. Niestety tak nie jest.
W załączniku jest plik z pomiarami w excelu, pomiary były robione z płytką skierowaną cały czas w tą samą stronę tak więc kąt (kompasu) powinien być taki sam cały czas.

Ja przeliczałem to w ten sposób:

int getHeadingHMC_TiltComp(float pitch, float roll)
{
	uint8_t raw_xh = 0;
	uint8_t raw_xl = 0;
	
	uint8_t raw_yh = 0;
	uint8_t raw_yl = 0;
	
	uint8_t raw_zh = 0;
	uint8_t raw_zl = 0;
	long x,y,z;

	i2c_start(HMC5883L_WRITE);
	i2c_write(0x03); //set pointer to X-axis MSB
	i2c_stop();

	i2c_rep_start(HMC5883L_READ); 

	raw_xh = i2c_readAck();
	raw_xl = i2c_readAck();

	raw_zh = i2c_readAck();
	raw_zl = i2c_readAck();

	raw_yh = i2c_readAck();
	raw_yl = i2c_readNak();

	i2c_stop();
	
	x = raw_xl|(raw_xh<<8);
	y = raw_yl|(raw_yh<<8);
	z = raw_zl|(raw_zh<<8);
	
	//float err = 0.5 * pitch;
	
	double Xh = (double)x * cos(M_PI*pitch/180) + (double)z * sin(M_PI*pitch/180);
	double Yh = (double)y;
	int headingDegrees = (double)(atan2(Yh,Xh)* 57 + 180);

	char buf[40];
	sprintf(buf,"%4.i : %4.i : %4.i : %4.i\n",(int)x, (int)y, (int)z, (int)pitch);
	USART_send_string(buf);

	return headingDegrees;
}

Ale nie za bardzo się to sprawdziło.

Pomyślałem żeby zrobić kalibrację czujnika ale nie bardzo wiem jak ona działa. Mam taki kod:

void HMC5883L_ScaleFactorCalib(void)
{
	int16_t raw_x = 0;
	int16_t raw_y = 0;
	int16_t raw_z = 0;

	int err=i2c_start(HMC5883L_WRITE); 
	i2c_write(0x00); // set pointer to CRA
	i2c_write(0x11); // Self test operation
	i2c_stop();
	
	i2c_start(HMC5883L_WRITE); 
	i2c_write(0x01); // set pointer to CRA
	i2c_write(0x20); // Self test operation
	i2c_stop();
	
	i2c_start(HMC5883L_WRITE); 
	i2c_write(0x02); // set pointer to measurement mode
	i2c_write(0x01); // Single measurment mode
	i2c_stop();


	i2c_start(HMC5883L_WRITE);
	i2c_write(0x03); //set pointer to X-axis MSB
	i2c_stop();

	i2c_rep_start(HMC5883L_READ); 

	raw_x = ((uint16_t)i2c_readAck())<<8;
	raw_x |= i2c_readAck();

	raw_z = ((uint16_t)i2c_readAck())<<8;
	raw_z |= i2c_readAck();

	raw_y = ((uint16_t)i2c_readAck())<<8;
	raw_y |= i2c_readNak();

	i2c_stop();
	
	char buf[40];
	sprintf(buf,"Calib: %4.i : %4.i : %4.i\n",raw_x, raw_z, raw_y);
	USART_send_string(buf);
	
	return 0;
}	

Dostaję jakieś tam wyniki ale nie wiem co z nimi zrobić :).