Skip to main content

Test BME280 on Sensor Booster Pack

Related image

From the datasheet and  it's Guide Manual http://www.ti.com/lit/ug/slau666b/slau666b.pdf
BME280 has a slave address: 0x77;

To control it we need to config several register as below:

Control Humidity Register (ADDR: 0xF2) Default 0x00 not activate
Control Measure Register (ADDR: 0xF4) Default 0x00 not activate
           b[7:5]: control temperature measurement
           b[4:2]: control pressure measurement
           b[1-0]: Control IC mode
                         00: sleep mode
                         01,10: force mode
                         11: normal mode
Control filter Register (ADDR: 0xF5) Default 0x00
           b[7:5]: control standby time
           b[4:2]: control  IRR filter
           b[0]   : config SPI in 3 wires ('1') /4 wires ('1')

default ID:  ADDR: 0xD0   Value: 0x60 (96)

This example to test read humidity from IC
Setup I2C in CC2640:

    int32_t        hum;
    uint16_t       adc_H;
    uint8_t         id;
    //uint8_t         pow;
    uint8_t         txBuffer[2];  //BME280 require ADDR Register>> Command Register
    uint8_t         rxBuffer[8];
    I2C_Handle      i2c;
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;

    I2C_init();
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(Board_I2C_TMP, &i2cParams);
    if (i2c == NULL) {
        Display_printf(display, 0, 0, "Error Initializing I2C\n");
        while (1);
    }
    else {
        Display_printf(display, 0, 0, "I2C Initialized!\n");
    }

Config control register
    /* Common I2C transaction setup */
    i2cTransaction.writeBuf   = txBuffer;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf    = rxBuffer;
    i2cTransaction.readCount  = 1;

    i2cTransaction.slaveAddress = BME280_ADDR;
    //READ ID device
    txBuffer[0] = 0xD0;
    if (I2C_transfer(i2c, &i2cTransaction))
    {
        //light = (rxBuffer[0] << 8) | (rxBuffer[1]);
        id = rxBuffer[0];
        Display_printf(display, 0, 0, "Device ID: %d (C)",
                        id);

    }

// Configuration for measuring
    i2cTransaction.writeCount = 2;
    txBuffer[0] = 0xF5;
    //  |b7    |b6     |b5      |b4     |b3     |b2     |b1     |b0     |
    //  | time to sleep         |filter                 |not    |'1':SPI 3,'0':SPI 4|
    txBuffer[1] = 0x2C; //0x2Ct_sb =  62.5ms,filter = 011  see p.30 of data sheet
    //txBuffer[2] = 0x10;
    if (I2C_transfer(i2c, &i2cTransaction))
                    {
                        //light = (rxBuffer[0] << 8) | (rxBuffer[1]);
                        id = rxBuffer[0];
                        Display_printf(display, 0, 0, "Measure After Configuration : %d (C)",
                                        id);
                    }

// Configuration hum measure:
        i2cTransaction.writeCount = 2;
        txBuffer[0] = 0xF2;
        txBuffer[1] = 0x03; //00: skip, 01: oversamplingx1, 10: oversamplingx2
            //txBuffer[2] = 0x10;
            if (I2C_transfer(i2c, &i2cTransaction))
                            {
                                //light = (rxBuffer[0] << 8) | (rxBuffer[1]);
                id = rxBuffer[0];
                Display_printf(display, 0, 0, "Hum register After Configuration : %d (C)",
                                                id);
                            }

// Configuration MODE 00: sleep, 01,10: Force, 11: Normal
    i2cTransaction.writeCount = 2;
    txBuffer[0] = 0xF4;
    txBuffer[1] = 0x03; //t_sb =  10ms,filter = 2  see p.30 of datashhet
        //txBuffer[2] = 0x10;
        if (I2C_transfer(i2c, &i2cTransaction))
                        {
                            //light = (rxBuffer[0] << 8) | (rxBuffer[1]);
            id = rxBuffer[0];
            Display_printf(display, 0, 0, "Mode After Configuration : %d (C)",
                                            id);
                        }

 /* Read Calib coefficient of Humidity*/
    // READ dig_H1
    i2cTransaction.writeCount = 1;
    txBuffer[0] = 0xA1;
    if (I2C_transfer(i2c, &i2cTransaction))
    {

        dig_H1 = rxBuffer[0];
        Display_printf(display, 0, 0, "Coefficient dig_H1 : %u (C)",
                                                dig_H1);
     }
    //READ dig_H2 - digH6
    txBuffer[0] = 0xE1;
    i2cTransaction.readCount  = 7;
    if (I2C_transfer(i2c, &i2cTransaction))
       {

           dig_H2 = ((rxBuffer[1]<<8)|rxBuffer[0]);
           Display_printf(display, 0, 0, "Coefficient dig_H2 : %d (C)",
                          dig_H2);
           dig_H3 = rxBuffer[2];
                      Display_printf(display, 0, 0, "Coefficient dig_H3 : %u (C)",
                          dig_H3);
           dig_H4 = ((rxBuffer[3]<<4)|(0x0F&rxBuffer[4]));
           Display_printf(display, 0, 0, "Coefficient dig_H4 : %d (C)",
                          dig_H4);
           dig_H5 = ((rxBuffer[5]<<4)|((0xF0&rxBuffer[4])>>4));
           Display_printf(display, 0, 0, "Coefficient dig_H5 : %d (C)",
                          dig_H5);
           dig_H6 = rxBuffer[6];
           Display_printf(display, 0, 0, "Coefficient dig_H6 : %d (C)",
                          dig_H6);
        }
/* Take 20 samples and print them out onto the console */
     //i2cTransaction.writeBuf   = txBuffer;
     i2cTransaction.writeCount = 1;
     //i2cTransaction.readBuf    = rxBuffer;
     i2cTransaction.readCount  = 2;

    txBuffer[0] = 0xFD;

for (sample = 0; sample < 20; sample++) {
        if (I2C_transfer(i2c, &i2cTransaction)) {
            /*
             * Extract degrees C from the received data;
             * see TMP116/006 datasheet
             */
            //temperature = (rxBuffer[0] << 8) | (rxBuffer[1]);
            //temperature *= 0.0078125;

            /*
             * If the MSB is set '1', then we have a 2's complement
             * negative value which needs to be sign extended
             */
            //if (rxBuffer[0] & 0x80) {
            //    temperature |= 0xF000;

            //display ambient level light
            /*
            pow = (rxBuffer[0] >> 4) ;
            light = ((rxBuffer[0]&0x0F) << 8) | (rxBuffer[1]);
            while(pow!=0)
            {
                pow -=1;        // Multiply 2^n by left shifting to n times
                light <<=1;
            }
            light *=0.01;
            */
            adc_H = ((rxBuffer[0] << 8) | (rxBuffer[1]));
            hum = bme280_compensate_H_int32((int32_t)adc_H);
            hum >>=10;
            Display_printf(display, 0, 0, "Sample %u: %d (%c)",
                sample, hum,'%'); //temperature
        }
        else {
            Display_printf(display, 0, 0, "I2C Bus fault.");
        }

        /* Sleep for 1 second */
        sleep(1);
    }

    I2C_close(i2c);
    Display_printf(display, 0, 0, "I2C closed!");

    return (NULL);
}

When we read from I2C we got a raw value of humidity from two Register 0xFD (High Byte) 0xFE(Low Byte). The value will transfer to rxbuffer[0] and rxbuffer[1] respectively.
Next, we need to convert to real value using a compensation function as describe in P25-P26 of the datasheet

uint32_t bme280_compensate_H_int32(int32_t adc_H)
{
    int32_t v_x1_u32r;

    v_x1_u32r = t_fine - ((int32_t)76800);
    v_x1_u32r = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) *
            v_x1_u32r))+ ((int32_t)16384)) >> 15) * (((((((v_x1_u32r*
            ((int32_t)dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)dig_H3)) >> 11) +
            ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)dig_H2) +
                    8192) >> 14));
    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
            ((int32_t)dig_H1)) >> 4 ));
    v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
    v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
    return (uint32_t)(v_x1_u32r>>12);
}
Notice: The values of calibration are fixed and we can store some elsewhere to reuse rather than access it each time we want to use BME280 to read humidity value.

dig_H1 = 0
dig_H2 = 379
dig_H3 = 0
dig_H4 = 281
dig_H5 = 50
dig_h6 = 30 

Comments

Popular posts from this blog

Experiment Sensor Booster Pack with CC2650 In this experiment, we use CC2650 rather CC2640Rx2 to read light level from OTP3001 on the sensor board. It follows the Task 3, Task 4 from TI tutorial http://dev.ti.com/tirex/content/simplelink_academy_cc2640r2sdk_1_13_02_07/modules/ble_02_thermostat/ble_02_thermostat.html Here we need some modified like last post to make the project run. First, to define the board CC2650 in file Board.h #define     Board_I2C_TMP           CC2650_LAUNCHXL_I2C0 Also, define IC address in file otp3001.c( replaced for tmp007.c) #define Board_TMP_ADDR   0x47 #if defined(ONBOARD_TMP006) #define TMP_REGISTER TMP_DIE_TEMP #define TMP_ADDR     Board_TMP_ADDR #else #define TMP_REGISTER TMP_OBJ_TEMP #define CONF_REGISTER 0x01 #define TMP_ADDR     Board_TMP_ADDR #endif Declare two new variables for reading exponent part and result uint16_t       ...
Serial Port Profile with CC2650 and CC2640R2 (part 2) Modified to transfer ADC values up to PC Step 1:  Include ACD.h library #include <ti/drivers/ADC.h>  Step 2: Insert period event in order to update ADC read values from the potentiometer #define SSSS_ICALL_EVT                         ICALL_MSG_EVENT_ID // Event_Id_31 #define SSSS_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30 #define SSSS_PERIODIC_EVT                      Event_Id_00 //SOLUTION // Bitwise OR of all events to pend on #define SSSS_ALL_EVENTS                        (SSSS_ICALL_EVT        | \                                ...
Serial Port Profile with CC2650 and CC2640R2 This test based on code from TI support under link: For CC2650: https://github.com/ti-simplelink/ble_examples/blob/ble_examples-2.2/docs/spp_ble.md For CC2640R2: https://github.com/ti-simplelink/ble_examples/blob/simplelink_cc2640r2_sdk-2.20/examples/rtos/CC2640R2_LAUNCHXL/bleapps/simple_serial_socket_client/readme.md In this experiment, I use CC2640R2 as Server (Peripheral) and CC2650 as Client (Central) as the image below: Step1: import project spp_ble_client_cc2650lp (app and stack) for CC2650 Step2: modify Code of Service in file serial_port_service:               C0E0 ==> C0C0               C0E1 ==> C0C1               C0E2 ==> C0C2 If you don't change, Two Blue Tooth Board cant know to service each other. Step 3: import project simple_serial_socket_client_CC2640r2 for CC2640R2 here we using RealTerm...