MarkSherstan / MPU-6050-9250-I2C-CompFilter

MPU6050/9250 I2C and SPI interface. Sensor fusion using a complementary filter yields sensor Euler angles and is implemented in five different languages.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Note: AK8963 is set up as slave, not using direct access.

WillemD61 opened this issue · comments

You are making reference to Kris Winer's C programs. Thank you for translating these to Python so I don't have to do it myself.

It is worth noting that on Kris' site the communication with the AK8963 normally is done using direct addressing on main AK8963 address 0C. The host reads the magnometer values directly from the AK8963. The 0C address is also visible with i2cdetect.

Only in a subfolder he explains and shows the setup with the AK8963 as slave, and this is what you are using in your Python programs. This does not work on my MPU9250 and I am not sure why. (maybe it only works for MPU6050?). I am going to change it back to direct communication.

I think it is worth making a note about this in your documentation.

Probably not the best way to share this, but here are the two changed methods to communicate with the AK8963 in direct access mode instead of the slave setup.

def setUpMAG(self):
	# Check to see if there is a good connection with the mag
	try:
		whoAmI = self.bus.read_byte_data(self.AK8963_ADDRESS, self.WHO_AM_I_AK8963)
	except:
		print('whoAmI MAG read failed')
		return

	if (whoAmI == 0x48):
		# Connection is good! Begin the true initialization
		self.bus.write_byte_data(self.AK8963_ADDRESS, self.AK8963_CNTL, 0x00);                      # Power down magnetometer
		time.sleep(0.05)
		self.bus.write_byte_data(self.AK8963_ADDRESS, self.AK8963_CNTL, 0x0F);                      # Enter fuze mode
		time.sleep(0.05)

		# Read the x, y, and z axis calibration values
		try:
			rawData = self.bus.read_i2c_block_data(self.AK8963_ADDRESS, self.AK8963_ASAX, 3)
		except:
			print('Reading MAG x y z calibration values failed')
			return

		# Convert values to something more usable
		self.magXcal =  float(rawData[0] - 128)/256.0 + 1.0
		self.magYcal =  float(rawData[1] - 128)/256.0 + 1.0
		self.magZcal =  float(rawData[2] - 128)/256.0 + 1.0

		self.bus.write_byte_data(self.AK8963_ADDRESS, self.AK8963_CNTL, 0x00);                      # Power down magnetometer
		# Configure the settings for the mag
		self.bus.write_byte_data(self.AK8963_ADDRESS, self.AK8963_CNTL, self.magHex);               # Set magnetometer for 14 or 16 bit continous 100 Hz sample rates
		time.sleep(0.05)

		# Display results to user
		print("MAG set up:")
		print("\tMagnetometer: " + hex(self.magHex) + " " + str(round(self.magScaleFactor,3)) + "\n")
	else:
		# Bad connection or something went wrong
		print("MAG WHO_AM_I was: " + hex(whoAmI) + ". Should have been " + hex(0x48))


def readRawMag(self):
	# Read 7 values [Low High] and one more byte (overflow check)
	try:
		rawData = self.bus.read_i2c_block_data(self.AK8963_ADDRESS, self.AK8963_XOUT_L, 7)
		#If overflow check passes convert the raw values to something a little more useful
		if not (rawData[6] & 0x08):
			self.mx = self.eightBit2sixteenBit(rawData[0], rawData[1])
			self.my = self.eightBit2sixteenBit(rawData[2], rawData[3])
			self.mz = self.eightBit2sixteenBit(rawData[4], rawData[5])	
	except:
		print('Read raw MAG data failed')

I am glad that you have found this repo helpful!

The MPU-6050 does not have a built in mag, but I have seen different behaviors depending on the breakout board used for the MPU-9250 (different pull up resistors, logic level conversion, etc...). Either way thank you for the note! I have added your methods and will complete the PR shortly.