2020-03-24 06:59 PM
Hello,
I am trying to implement 6D mode. I am following 1:1 the code documented in the design tip DT0097.
I have been trying for a while: I2C interface is working and other modes of LIS2DH work properly.
As a safety measure, during the init I reset all registers back to their default value.
I read IRQ_SRC as soon as the INT1 line is raised.
However, the behavior is not as expected:
I do get interrupts when I move the board, but:
In the interrupt, I simply read INT1_SRC, that should be enough, right?
This is an example of events I get while flipping the Z axis of the board. Val is the (hex) value of INT1_SRC, while the rest is the string is my decoding of it.
Do you have any hint or fully-fledged example?
val:66 XU YD ZU
val:15 XD YD ZD
val:65 XD YD ZU
val:15 XD YD ZD
val:66 XU YD ZU
val:15 XD YD ZD
val:56 XU YD ZD
val:15 XD YD ZD
val:69 XD YU ZU
val:15 XD YD ZD
val:59 XD YU ZD
val:15 XD YD ZD
2020-03-25 04:15 AM
2020-03-25 08:33 AM
Thank you Eleon.
Yes, I read also that one document, it is not of any help.
This is my initalization code
void accel_flip_detection(void)
{
uint8_t i2cdata[2];
twi_master_init();
ADDR = 0x30;
i2cdata[0] = CTRL_REG5;
i2cdata[1] = BOOT; //reset memory
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = CTRL_REG1;
i2cdata[1] = 0x00; //Stop
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = CTRL_REG2;
i2cdata[1] = 0x00; //default
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
//CTRL_REG3
i2cdata[0] = CTRL_REG3;
i2cdata[1] = I1_AOI1; // AOI1 interrupt generation is routed to INT1 pin.
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
//CTRL_REG4
i2cdata[0] = CTRL_REG4;
i2cdata[1] = 0; //+-2g
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = CTRL_REG5;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = CTRL_REG6;
i2cdata[1] = 0x00; //default
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
//INT1_CFG -> interrupts on INT1
i2cdata[0] = INT1_CFG;
i2cdata[1] = AOI | d6D | ZHIE | ZLIE | YHIE | YLIE | XHIE | XLIE;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
uint8_t ths = 0x21;
i2cdata[0] = INT1_THS;
i2cdata[1] = ths;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
uint8_t duration = 0x20;
i2cdata[0] = INT1_DURATION;
i2cdata[1] = duration;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
//not needed, added as safety measure
i2cdata[0] = REFERENCE;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true); //write address to read
i2cdata[0] = FIFO_CTRL_REG;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x34;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x35;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x36;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x37;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x38;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3a;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3b;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3c;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3d;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3e;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
i2cdata[0] = 0x3f;
i2cdata[1] = 0x00;
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
//CTRL_REG1 start Low power
i2cdata[0] = CTRL_REG1;
i2cdata[1] = ODR_25 | LPen | Zen | Yen | Xen; // Set LIS3DH to low power mode with ODR = 25Hz.
twi_master_transfer(ADDR | WRITE, i2cdata, 2, true);
delay_ms(1);
}
And this is the ISR routine
void ACCEL_releaseInt1(void)
{
static uint8_t last_orientation = 0x00;
uint8_t i2cdata[2];
ADDR = 0x30;
twi_master_init();
i2cdata[0] = INT1_SRC;
twi_master_transfer(ADDR | WRITE, i2cdata, 1, false);
twi_master_transfer(ADDR | READ, i2cdata, 1, true);
uint8_t ir = (i2cdata[0] & 0b00111111); //current orientation
// 0b000100, //a
// 0b000010, //b
// 0b000001, //c
// 0b001000, //d
// 0b100000, //e
// 0b010000 //f
char str[10];
if (ir != last_orientation)
{
PRu8hex(str, i2cdata[0]);
uart_putstring_buf((uint8_t*)"val:");
uart_putstring_buf((uint8_t*)str);
if (ir & 0b000010)
uart_putstring_buf((uint8_t*)" XU");
else if (ir & 0b000001)
uart_putstring_buf((uint8_t*)" XD");
else
uart_putstring_buf((uint8_t*)" X-");
if (ir & 0b0001000)
uart_putstring_buf((uint8_t*)" YU");
else if (ir & 0b000100)
uart_putstring_buf((uint8_t*)" YD");
else
uart_putstring_buf((uint8_t*)" Y-");
if (ir & 0b100000)
uart_putstring_buf((uint8_t*)" ZU");
else if (ir & 0b10000)
uart_putstring_buf((uint8_t*)" ZD");
else
uart_putstring_buf((uint8_t*)" Z-");
uart_putstring_buf((uint8_t*)"\n");
}
last_orientation = ir;
}
But I tried dozen of different combinations with no better outcome...
2020-03-26 01:17 AM
Good morning,
I tried to achieve the same result doing a simple inertial wake up on axis z, as per the application note you posted. So, I expect an interrupt when axis Z value is above a certain value (so the board is laying on one of the two faces).
The results are the same: I get 2 IRQs every time, and the INT1_SRC doesn't show the real condition. It's almost like hp filter is active, because I always end up with lower poart of INT1_SRC = 0x15 (all the "low" IRQs).
2020-03-26 01:37 AM
Hi @vcaia.1 , thank you for the detailed analysis. Can you try with modifying the interrupt duration? You can do it either latching the interrupt, i.e. setting to '1' the LIR_INT1 of the CTRL_REG5 (24h) register or directly changing the duration of the interrupt itself, by modifying the register content in the INT1_DURATION (33h) register. Regards
2020-03-26 06:01 AM
I tried that, but I tried again now based on my code posted above.
LIR_INT1 has no effect, I see no difference.
Duration is already 0x20. (that should be 1280ms @25hz). Even if I put that one to 0x7f (5s!)I see no increased delay between events.
I understand the duration register as the time the event has to last in order to trigger the interrupt (e.g. the Z axis must be > the threshold for 5s) is it correct?
Or is it just the duration of the pulse on INT1 and it's enough to have one sample over the threshold?
2020-03-26 06:09 AM
So one problem looks to be that ISR routine was called both on rising and falling edge. This has been solved now, but I still get some unwanted results, when moving the board really slow.