Search code examples
csensorsi2cproximity

How to get silabs Si1141 out of suspended mode


Trying to read the PS1 values. But as im running the following code it keeps saying on "chip_stat" that its suspended.

main (void){

    init(); // Configuration initialization
    si1141_init(); // Si1141 sensor initialization

    __delay_ms(30); // Delay to ensure Si1141 is completely booted, must be atleast 25ms

    si1141_WriteToRegister(REG_IRQ_STATUS, 0xFF); // Clear interrupt source

    signed int status;

    while(1){

        WriteToI2C(0x5A<<1); // Slave address
        PutByteI2C(0x30); // chip_stat
        ReadFromI2C(0x5A<<1); // Slave address
        if((status = GetByteI2C(0x30)) == Sw_I2C_ERROR) // chip_stat
        {
            return Sw_I2C_ERROR;
        }
        Stop_I2C();
        status++;;
    }
}

The code im using to read the PS1 values is the following. Im reading the value 16705. Which keeps being the same on all measurements.

The value should go up and down from 0 - 32767, as it measures more or less movement.

signed int si1141_ReadFromRegister(unsigned char reg){
    signed int data;

    WriteToI2C(0x5A<<1); // Slave address
    ReadFromI2C(0x5A<<1); // Slave address
    if((data = GetByteI2C(Sw_I2C_LAST)) == Sw_I2C_ERROR)
    {
        return Sw_I2C_ERROR;
    }
    Stop_I2C();
    return data;
}

main (void){

    init(); // Configuration initialization
    si1141_init(); // Si1141 sensor initialization

    __delay_ms(30); // Delay to ensure Si1141 is completely booted, must be atleast 25ms

    si1141_WriteToRegister(REG_IRQ_STATUS, 0xFF); // Clear interrupt source

    signed int PS1;

    while(1){        

    PS1 = si1141_ReadFromRegister(REG_PS1_DATA0) + (256 * si1141_ReadFromRegister(REG_PS1_DATA1)); // Proximity CH1

    }
}

I linked the files for the i2c communication.

https://www.dropbox.com/s/q41vw444gjvj0qa/swi2c.c?dl=0 https://www.dropbox.com/s/1mshyz88o15hz8c/swi2c.h?dl=0


Solution

  • Rule out I2C errors first. Your software I2C library is no help at all.

    Make sure you read registers PART_ID, REV_ID, SEQ_ED first and that the values match the data sheet resp. your expected values. This is to rule out I2C errors.

    You have to take quite a few steps to get a single reading to get started.

    Reset the Si114x. Program the HW_KEY. Program PS_LED21 to a sensible value. The ANs tell you how. Do not program a higher value than what your components can handle and what your design can support. This might destroy something if done incorrectly. Do not get any funny ideas about PS_ADC_GAIN either, or you will fry your device. Read the AN. Do not program PS_ADC_GAIN at this point.

    Clear PSLED21_SELECT -- only PS2_LED, keep PS1_LED set for LED1, obviously -- and PSLED3_SELECT. This is probably optional, but the datasheet tells you to do it, so do it.

    Next, program CH_LIST to PS1_EN, then send a PS_FORCE command.** Now read PS1 data from PS1_DATA0 and PS1_DATA1. Done.

    It may be easier to test with ALS first to rule out saturating your sensor with some stray infrared (think setting sun as you work through the night).

    ** For the command protocol, you have to implement the command/response protocol laid out in the datasheet. I suggest you test with reset and nop first to verify your code.