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.