Pytrack LIS2HH12 Interrupts make I2c bus freeze



  • I'm trying to use the FIFO buffer of the accelerometer together with interrupts generated from it.

    #appended to the __init__ method of LIS2HH12
            # set fifo mode in stream mode. and threshold to 24 (if overflow samples are discarded silently)
            self.i2c.readfrom_mem_into(ACC_I2CADDR, FIFO_CTRL_REG, self.reg)
            self.reg[0] |= 0b01011000
            self.i2c.writeto_mem(ACC_I2CADDR, FIFO_CTRL_REG, self.reg)
    
            # enable fifo, use threshold
            self.i2c.readfrom_mem_into(ACC_I2CADDR, CTRL3_REG, self.reg)
            self.reg[0] |= 0b11000000
            self.i2c.writeto_mem(ACC_I2CADDR , CTRL3_REG, self.reg)
    
    

    This works fine as long as I do not want to use the interrupts generated from the accelerometer.
    If I enable interrupts on pin 1:

            self.i2c.readfrom_mem_into(ACC_I2CADDR, CTRL3_REG, self.reg)
            self.reg[0] |= 0b11000010
            self.i2c.writeto_mem(ACC_I2CADDR , CTRL3_REG, self.reg)
    

    everything is fine for a short period of time (reading acceleration values is possible). but then (I suspect after the interrupt actually triggered) I2c communication no longer works and the pytrack needs powercycling (rebooting the esp32 does not help to recover from this i2c error) =(.

    OSError: I2C bus error

    I tried to follow the trace on the pcb from P13 but not sure how it actually is connected =( probably there is a pull-up resistor to 3.3 v sensor and a diode but I am not sure about this...

    Anyone else figured out how to use interrupts generated from the accelerometer?

    And yes, I am on the latest fw's:

    >>> os.uname()
    (sysname='LoPy', nodename='LoPy', release='1.7.9.b3', version='v1.8.6-747-gc4ec6110 on 2017-08-09', machine='LoPy with ESP32', lorawan='1.0.0')
    >>> py.read_fw_version()
    4
    

    pytrack.py: __version__ = '1.1.0'

    For completness here is the whole init including the register definitions:

    class LIS2HH12:
    
        ACC_I2CADDR = const(30)
    
        PRODUCTID_REG = const(0x0F)
        CTRL1_REG = const(0x20)
        CTRL3_REG = const(0x22)
        CTRL4_REG = const(0x23)
        FIFO_CTRL_REG = const(0x2E)
        FIFO_SRC_REG = const(0x2F)
    
        ACC_X_L_REG = const(0x28)
        ACC_X_H_REG = const(0x29)
        ACC_Y_L_REG = const(0x2A)
        ACC_Y_H_REG = const(0x2B)
        ACC_Z_L_REG = const(0x2C)
        ACC_Z_H_REG = const(0x2D)
    
        SCALE = const(8192)
    
        def __init__(self, pysense=None, sda='P22', scl='P21'):
            if pysense is not None:
                self.i2c = pysense.i2c
            else:
                from machine import I2C
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
    
            self.reg = bytearray(1)
            self.data = memoryview(bytearray(32*6))
    
    
            self.x = 0
            self.y = 0
            self.z = 0
    
            whoami = self.i2c.readfrom_mem(ACC_I2CADDR , PRODUCTID_REG, 1)
            if (whoami[0] != 0x41):
                raise ValueError("Incorrect Product ID")
    
            # enable acceleration readings
            self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL1_REG, self.reg)
            self.reg[0] &= ~0b01110000
            self.reg[0] |= 0b00110000 # 100 Hz
            self.i2c.writeto_mem(ACC_I2CADDR , CTRL1_REG, self.reg)
    
            # change the full-scale to 4g
            self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL4_REG, self.reg)
            self.reg[0] &= ~0b00110000
            self.reg[0] |= 0b00100000
            self.i2c.writeto_mem(ACC_I2CADDR , CTRL4_REG, self.reg)
    
            # setup fifo
            # Be aware, it can remember only 32xyz values
    
            # set fifo mode in stream mode. and threshold to 24 (if overflow, samples are discarded silently)
            self.i2c.readfrom_mem_into(ACC_I2CADDR, FIFO_CTRL_REG, self.reg)
            self.reg[0] |= 0b01011000
            self.i2c.writeto_mem(ACC_I2CADDR, FIFO_CTRL_REG, self.reg)
    
            # enable fifo, use threshold, ##### generate threshold signal on int1
            self.i2c.readfrom_mem_into(ACC_I2CADDR, CTRL3_REG, self.reg)
            # self.reg[0] |= 0b11000000
            self.reg[0] |= 0b11000010
            self.i2c.writeto_mem(ACC_I2CADDR , CTRL3_REG, self.reg)
    
            # enable interrupt on threshold and register callback function.
            self.int_pin = Pin('P13', mode=Pin.IN)
            # self.int_pin.callback(trigger=Pin.IRQ_RISING, handler=self.read_fifo)
            # discard the 16 first samples
            for i in range(16):
                print(self.acceleration())
    


  • By the way, one error which presists is, that I get a lot of false interrupts especially during wifi activity. The only workaround I found was to check in the isr if the pin really is low..
    Not sure if this is an electrical problem or an sw problem...



  • Okay, got this working, acc fifo, and interrupt on the pyboard with the pytrack:

    There are a few stones in the way to get this working:

    1. The above error seems to originate from a short circuit due to the reason, that the interrupt is routed to the pyboard and the PIC. If on the PIC this pin is not configured as input its hold low which on interrupt is a short circuit. There might be another cause for short circuit, see 4.

    2. There seems to be a diode between the accelerometer and the pyboard kathode in direction to the accelerometer, so you can not use interrupt on raising edge.

    3. @bucknall seems not to know his own hardware :-o despite the cited quote in the last comment the interrupt from the accelerometer is routed to the pyboard pin13!

    4. I'm actually not sure if this really applies nevertheless it looks like both interrupt pins on the accelerometer are connected together. So open-drain is required on the accelerometer.



  • Ah, just found this:

    @bucknall wrote:

    Yes, the interrupts are currently connected to the onboard PIC of the Pytrack, which makes it a bit more difficult to manage regarding simply connecting the accelerometer to the ESP32 interrupts. We're working on this and will let you know when it's ready!

    in https://forum.pycom.io/topic/1409/power-consumption-on-pytrack-with-sipy/6

    Does not actually solve the problem but creates one more =/



  • Ah, trying to follow the traces from the accelerometer it seems, that unlike the pinout of the pytrack, which says interrupts from the accelerometer are routed to P13 they are actually routed to the PIC. @daniel can you confirm this? Is the idea here, that PIN13 gets managed from software on the PIC?


Log in to reply
 

Pycom on Twitter