spacecraft-design-lab-2019 / documentation

Wiki lives in here
https://github.com/spacecraft-design-lab-2019/documentation/wiki
12 stars 3 forks source link

Wrap BMX160 in circuitpython #83

Open tomerarnon opened 4 years ago

tomerarnon commented 4 years ago

See: https://github.com/adafruit/Adafruit_CircuitPython_BMP3XX/blob/fc01520a3c285bf8e6ce6f9ad935badc8d8fa4a6/adafruit_bmp3xx.py#L235

https://github.com/adafruit/Adafruit_CircuitPython_LSM9DS1/tree/7e30aadf70daac0f9f8ea651a414a201d27a41a3

maholli commented 4 years ago

@tomerarnon Here's another good reference. This is a sensor library I threw together for a capacitance sensor. Its a good example of picking and choosing things I wanted access to (plus it's i2c) https://github.com/maholli/CircuitPython_FDC221x/blob/master/fdc2212.py

An excerpt from the FDC221X library that's relevant is:

    def _read16(self, address):
        # Read a 16-bit unsigned value for from the specified address.
        self._read_into(address, self._BUFFER, count=2)
        _raw = self._BUFFER[0] << 8 | self._BUFFER[1]        
        return _raw

👆 is an example of me reading a 16bit value that's comprised of an LSB and MSB register (8 bits each).

maholli commented 4 years ago

Library Setup

This is what you'll likely need to import:

from micropython import const
from adafruit_bus_device.i2c_device import I2CDevice
import time

then you can setup your registers as:

#registers
FDC2212_DEVICE_ID            =const(0x7F)
FDC2212_MUX_CONFIG           =const(0x1B)
FDC2212_CONFIG               =const(0x1A)
FDC2212_RCOUNT_CH0           =const(0x08)

etc...

maholli commented 4 years ago

Hardware Sanity Check

confirmed the BMX160 breakout boards work over I2C: image

wired according to the terrible pinout diagram for the shuttle board: image

using a feather M4, it looks like this: image

code to scan the I2C bus (don't forget the pull-up resistors as shown below)

import time, board, busio

i2c = busio.I2C(board.SCL, board.SDA)

while not i2c.try_lock():
    pass

while True:
    print("I2C addresses found:", [hex(device_address) for device_address in i2c.scan()])
    time.sleep(2)

image

image

maholli commented 4 years ago

cross-post from slack:

Approaching giant intimidating datasheets:

Quick skim through the BMX160 datasheet yielded some things I'd look into:

  1. Register 0x7E (COMMAND REGISTER) seems promising. Are we using this? how does the c code use it?
  2. Skim thru page 53-54. It's a high level table should all the registers. Read the register names- anything stand out?
  3. See what the deal with the FIFO is. Do you need to set this before the data registers start populating?
  4. When in doubt, loop thru and read the ENTIRE register map then compare to the default values shown on page 53. Anything stand out?
tomerarnon commented 4 years ago

Update before heading off to break: The BMX160 repo has been in development here. I have been closely following the C implementation of the BMI160 (predecessor chip) here in terms of the low level interfaces, in combination with the BMX's datasheet.

So far the library can initialize all the sensors on the chip and provides an easy interface to get/decode data from them over I2C or SPI. The "settings" API is still terrible and needs to be rethought in light of new understanding of the mag vs. gyro/accel interface (initially assumed to be similar but actually quite different). There are also still some suspicious maybe-bugs going on (i.e. even though we decode sensor-time the same as the in the C code, I still suspect the output isn't right; something in the byte-shifts is fishy), but even so it is already useable for sensor characterization.

I recorded some hours of 10Hz data (programmed for 10 but maybe I got only 8; the sensor-time thing is throwing me off so can't know for sure without some analysis). I haven't yet run the allan variance script on it but I'll link to that here in an edit when I get the chance to sit down with it again (in a day or two hopefully).

Once the settings API is done, the driver is essentially ready for widespread use (with more esoteric chip functionality exposable over time as needed). Once that's the case, I will document the entire design and usage on its own repo. It would be worth it at that point to also consider "safety features" like try-excepts (or a python equivalent to the null-pointer/null-return checks the C-code has all over) so that the BMX160 can never error-out a project due to bad input or bad return.