Shop OBEX P1 Docs P2 Docs Learn Events
BMP280 interface — Parallax Forums

BMP280 interface

Does anyone have any P2 code that reads a BMP280 and returns temperature and pressure that is compatible with Flex?

This blasted thing is just kicking my butt and Bosch is less than helpful. Beer and eternal gratitude is available for all who can help. 🤣

Comments

  • You, me, and a whole lot of other people have found Bosch less that helpful with this device. It's irritating that they won't show the formulas, except in code.

  • JRoarkJRoark Posts: 1,215
    edited 2023-01-16 02:01

    @JonnyMac said:
    You, me, and a whole lot of other people have found Bosch less that helpful with this device. It's irritating that they won't show the formulas, except in code.

    My experience exactly. And if you ask them about it, they say “just use our libraries!”. And then when I ask for one for a Parallax chip, they get really quiet. 🙈

  • bob_g4bbybob_g4bby Posts: 401
    edited 2023-01-16 14:08

    I got so far with reading the BMP280 written in Taqoz Reloaded, the SD card resident forth system. My code for reading and converting temperature works fine - it checks out with the example values given on page 23 of Bosch's document BST-BMP280-DS001-11. I can read raw pressure OK - raising and lowering the device by an arm's length produces a change in the value, but there's a bug still in my conversion, which produces values that are consistently low. Here's my forth code so far:-

    --- BMP280 air pressure / temperature driver for TAQOZ 2.8
    --- Version 1
    --- N.B. requires the assembler loaded as part of the forth tool set
    
    ALIAS I2C.START <I2C
    
    --- cast signed word to signed long
    pub W>SL    ( word -- signedlong )
        DUP 32767 >
        IF
            65563 -
        THEN
        ;
    
    --- signed double maths 
    
    --- duplicate top 4 stack entries
    : 4DUP  ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2 n3 n4 )
        4 0 DO 4TH LOOP
    ;
    
    --- flg=true if d1=d2 else flg=false
    pub D=  ( d1 d2 -- flg )
    ROT = -ROT = + -2 =
    ;
    
    
    --- cast signed long to signed double
    pub L->D    ( n -- d )
        DUP 0<
        ;
    
    --- multiply two signed doubles, result is signed double
    pub D*  ( d1 d2 -- d3 )
    
    
      R SWAP >R
    
    
        2DUP UM* 2SWAP
        R> * SWAP R> * + +
        ;
    
    --- square signed double d2 = d1 squared
    pub DSQR    ( d1 -- d2 )
        2DUP D*
        ;
    
    --- d2 = absolute value of d1, flg = true if d1 was negative
    pub DABS    ( d1 -- d2 flg )
        DUP 0<
        IF
            -1 -1 D* 1
        ELSE
            0
        THEN
    ;
    
    --- d2 = -d1
    pub DNEGATE
        -1 -1 D*
    ;
    
    --- if flg is true, d2 = -d1
    pub ?DNEGATE    ( d1 flg -- d2 )
        0<>
        IF
            DNEGATE
        THEN
    ;
    
    --- print a signed double
    pub SD. ( d -- )
        DUP 0< IF
            SWAP
            -1 XOR 1+ DUP 0= >R
            SWAP
            -1 XOR R> IF 1+ THEN
            45 EMIT
        THEN
        D.                                      --- then print the absolute value
        ;
    
    --- logic shift double d1 left by 1 position
    pub D<shift ( d1 -- d2 )
        SWAP                --- Dhigh Dlow
        DUP 0< >R           --- is top bit of Dlow set?
        2* SWAP 2*          --- Dlow*2 Dhigh*2
        R> IF               --- if carry over to high long is reqd
            1+              --- Dhigh + 1
        THEN
    ;
    
    --- add signed doubles d3 = d1 + d2 
    code D+ ( d1 d2 -- d3 )
        add d,b wc
        addx c,a
        jmp #@2DROP
    end
    
    --- subtract signed doubles d3 = d1 - d2
    code D- ( d1 d2 -- d3 )
        sub d,b wc
        subx c,a
        jmp #@2DROP 
    end
    
    --- left shift UD until the MS bit is 1, leftshifts is the number of shifts
    pub UDNORMAL    ( UD1 -- UD2 leftshifts )
    0 >R                                --- set up shift count
    BEGIN
        DUP $80000000 AND 0=
    WHILE
        D<shift  R> 1+ >R
    REPEAT
    R>
    ;
    
     --- create a 'double' type variable (64 bits )
    pre double  ( -- )
        8 [C] [G] [C] bytes [C] [G]
        ;
    
    private
    double Quotient
    double Remainder
    double Divisor
    public
    
    --- quotient = d1 / d2 with remainder - all unsigned doubles
    pri (UD/)   ( dividend divisor -- remainder quotient )
            Divisor D!
            Quotient D!
            0. Remainder D!
            64 FOR
                Quotient D@  DUP 0< >R D<shift Quotient D!
                Remainder D@ D<shift R> IF 1. D+ THEN Remainder D!
                Remainder D@ Divisor D@ D-
                DUP $80000000 AND 0=
                IF
                    Remainder D!
                    Quotient D@ 1. D+ Quotient D!
                ELSE
                    2DROP
                THEN
            NEXT
            Remainder D@
            Quotient D@
    ;
    
    --- quotient = d1 / d2 with remainder - all unsigned doubles
    pub UD/MOD  ( dividend divisor -- remainder quotient )
        DUP 0=
        IF                          --- is divisor 32 bit or less?
            DROP UM// 0 -ROT
        ELSE
            (UD/)
        THEN
    ;
    
    --- quotient = d1 / d2 with remainder - all signed doubles
    pub D/MOD   ( dividend divisor -- remainder quotient )
        DABS 2* >R 2SWAP DABS R> + >R 2SWAP             --- convert d1 and d2 to +ve, remembering original signs
        UD/MOD
        R> SWITCH                                       --- bit1 set if divisor was -ve, bit0 = true for dividend 
            1 CASE DNEGATE 2SWAP DNEGATE 2SWAP BREAK
            2 CASE DNEGATE BREAK
    ;
    
    --- quotient = d1 / d2 - all signed doubles
    pub D/  ( dividend divisor -- quotient )
        D/MOD 2SWAP 2DROP
    ;
    
    
    --- BMP280 driver
    
    $EC := i2cadr                               --- set the BMP280 chip address
    3   := t_sb                                 --- time between readings 0 fastest 7 slowest 
    
    --- variables
    double var1
    double var2
    double calpress
    long rawpress
    long dig_T1
    long dig_T2
    long dig_T3
    long dig_P1
    long dig_P2
    long dig_P3
    long dig_P4
    long dig_P5
    long dig_P6
    long dig_P7
    long dig_P8
    long dig_P9
    long rawtemp
    long calibtemp
    long t_fine
    
    --- Read byte at i2c register adr
    pri I2CREAD ( adr -- byte )
        <I2C i2cadr I2C! I2C!                   --- select the register at 'addr' 
        <I2C i2cadr 1+ I2C! nakI2C@ I2C>        --- read the contents
        ;
    
    --- Write byte to i2c register adr
    pri I2CWRITE ( byte adr -- )
        <I2C i2cadr I2C! I2C! I2C! I2C>
        ;
    
    --- TEMPERATURE MEASUREMENT
    
    --- Read the temperature factory calibration constants
    pub READtempcal ( -- )
        $88 I2CREAD
        $89 I2CREAD 8 << OR
        dig_T1 !
        $8A I2CREAD
        $8B I2CREAD 8 << OR W>SL
        dig_T2 !
        $8C I2CREAD
        $8D I2CREAD 8 << OR W>SL
        dig_T3 !
        ;
    
    --- read 'measuring' in bit 3 and 'im_update' in bit 0
    pub READstatus ( -- status )
        $F3 I2CREAD
        ;
    
    --- Wait until measurement is complete
    pub MEASUREWAIT ( -- )
        BEGIN
            READstatus
            8 AND 0=
        UNTIL
        BEGIN
            READstatus
            8 AND 8 =
        UNTIL
        ;
    
    --- set up the BMP280 configuration to do one measurement per second 
    pub SETUP
        t_sb 5 <<   
        $F5 I2CWRITE
        5 5 <<          --- oversampling for temperature
        5 2 << OR       --- oversampling for pressure
        3 OR            --- power mode set to continuous measurement
        $F4 I2CWRITE
        ;
    
    --- display the three temperature factory calibration constants
    pub tempcal.    ( -- )
        READtempcal
        CRLF
        ." dig_T1=" dig_T1 @ . CRLF
        ." dig_T2=" dig_T2 @ . CRLF
        ." dig_T3=" dig_T3 @ . CRLF
        ;
    
    --- read the raw temperature, save in rawtemp
    pub READtemp    ( -- )
        $FA I2CREAD 16 <<
        $FB I2CREAD 8 << OR
        $FC I2CREAD OR 4 >>
        rawtemp !
        ;
    
    --- read rawtemp and calculate true temp, save in calibtemp
    --- shifts << or >> are not used as they don't work with signed longs
    pub CALCtemp    ( -- )
            rawtemp @ 8 /
            dig_T1 @ 2 * -
            dig_T2 @ *
            2048 /
            var1 !
            rawtemp @ 16 /
            dig_T1 @ -
            DUP * 4096 /
            dig_T3 @ *
            16384 /
            var2 !
            var1 @ var2 @ +
            DUP t_fine !
            5 * 128 +
            256 /
            calibtemp !
        ;
    
    --- display the raw and calibrated temperature until a key is pressed   
    pub READtemp.   ( -- )
        CRLF
        READtempcal
        SETUP
        BEGIN
            MEASUREWAIT
            READtemp 
            ." Raw temperature value =  " rawtemp @ . SPACE
            CALCtemp
            ." Calibrated temperature value = " calibtemp @ <# # # 46 HOLD #S #> PRINT$ CRLF
        KEY UNTIL
        ;
    
    --- PRESSURE MEASUREMENT
    
    --- read the raw pressure, save in rawpress
    pub READpress   ( -- )
        $F7 I2CREAD 16 <<
        $F8 I2CREAD 8 << OR
        $F9 I2CREAD OR 4 >>
        rawpress !
        ;
    
    --- Read the pressure factory calibration constants
    pub READpresscal ( -- )
        $8E I2CREAD
        $8F I2CREAD 8 << OR
        dig_P1 !
        $90 I2CREAD
        $91 I2CREAD 8 << OR W>SL
        dig_P2 !
        $92 I2CREAD
        $93 I2CREAD 8 << OR W>SL
        dig_P3 !
        $94 I2CREAD
        $95 I2CREAD 8 << OR W>SL
        dig_P4 !
        $96 I2CREAD
        $97 I2CREAD 8 << OR W>SL
        dig_P5 !
        $98 I2CREAD
        $99 I2CREAD 8 << OR W>SL
        dig_P6 !
        $9A I2CREAD
        $9B I2CREAD 8 << OR W>SL
        dig_P7 !
        $9C I2CREAD
        $9D I2CREAD 8 << OR W>SL
        dig_P8 !
        $9E I2CREAD
        $9F I2CREAD 8 << OR W>SL
        dig_P9 !
        ;
    
    --- display the pressure calibration constants
    pub presscal.   ( -- )
    READpresscal
        CRLF
        ." DIG_p1=" dig_P1 @ . CRLF
        ." DIG_p2=" dig_P2 @ . CRLF
        ." DIG_p3=" dig_P3 @ . CRLF
        ." DIG_p4=" dig_P4 @ . CRLF
        ." DIG_p5=" dig_P5 @ . CRLF
        ." DIG_p6=" dig_P6 @ . CRLF
        ." DIG_p7=" dig_P7 @ . CRLF
        ." DIG_p8=" dig_P8 @ . CRLF
        ." DIG_p9=" dig_P9 @ . CRLF
    ;
    
    --- set calibrations to test values for conversion calculation check as per page 23 of the DMP280 datasheet
    pub testcalset  ( -- )
        27504   dig_T1 !
        26435   dig_T2 !
        -1000   dig_T3 !
        36477   dig_P1 !
        -10685  dig_P2 !
        3024    dig_P3 !
        2855    dig_P4 !
        140     dig_P5 !
        -7      dig_P6 !
        15500   dig_P7 !
        -14600  dig_P8 !
        6000    dig_P9 !
        519888  rawtemp !
        415148  rawpress !
    ;
    
    --- convert rawpress to calpress, the true pressure in pascals
    pub CALCpress   ( -- )
        t_fine @ 2 / 64000 - var1 !                                                     --- var1 = ((t_fine)>>1) – 64000;
        var1 @ 4 / DUP * 2048 / dig_P6 @ * var2 !                                       --- var2 = (((var1>>2) * (var1>>2)) >> 11 ) * (dig_P6);
        var1 @ dig_P5 @ * 2 * var2 @ + var2 !                                           --- var2 = var2 + ((var1*(dig_P5))<<1);
        var2 @ 4 / dig_P4 65536 * + var2 !                                              --- var2 = (var2>>2)+((dig_P4)<<16);
        var1 @ 4 / DUP * 8192 / dig_P3 @ * 8 / dig_P2 @ var1 @ * 2 / + 262144 / var1 !  --- var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + (((dig_P2) * var1)>>1))>>18;
        var1 @ 32768 + dig_P1 @ * 32768 / var1 !                                        --- var1 =((((32768+var1))*(dig_P1))>>15);
        var1 @ 0=
        IF
            0 calpress !
        ELSE
            1048576 rawpress @ - var2 @ 4096 / - 3125 * calpress !                      --- p = ((((1048576)-adc_P)-(var2>>12)))*3125;
            calpress @ $80000000 <
            IF
                calpress @ 2 / var1 @ / calpress !                                      --- p = (p << 1) / (var1);
            ELSE
                calpress @ var1 @ / 2 * calpress !                                      --- p = (p / var1) * 2;
            THEN
            calpress @ 8 / DUP * 8192 / dig_P9 @ * 4096 / var1 !                        --- var1 = ((dig_P9) * ((((p>>3) * (p>>3))>>13)))>>12;
            calpress @ 4 / dig_P8 @ * 8192 / var2 !                                     --- var2 = (((p>>2)) * (dig_P8))>>13;
            var1 @ var2 @ + dig_P7 @ + 8 / calpress @ + calpress !                      --- p = (p + ((var1 + var2 + dig_P7) >> 4));
        THEN
        ;
    
    
    --- convert rawpress to calpress using mixture of 32 and 64 bit arithmetic as per page 22 of the BMP280 datasheet
    pub CALCpress1  ( --  )
        t_fine @ L->D 128000. D- var1 D!                                                    --- var1 = ((BMP280_S64_t)t_fine) – 128000;
        ." 1 var1 =  " var1 D@ SD. CRLF
        var1 D@ DSQR dig_P6 @ L->D D* var2 D!                                               --- var2 = var1 * var1 * (BMP280_S64_t)dig_P6;
        ." 2 var2 =  " var2 D@ SD. CRLF
        var1 D@ dig_P5 @ L->D D* 131072. D* var2 D@ D+ var2 D!                              --- var2 = var2 + ((var1*(BMP280_S64_t)dig_P5)<<17);
        ." 3 var2 =  " var2 D@ SD. CRLF
        dig_P4 @ L->D 34359738368. D* var2 D@ D+ var2 D!                                    --- var2 = var2 + (((BMP280_S64_t)dig_P4)<<35);
        ." 4 var2 =  " var2 D@ SD. CRLF
        var1 D@ DSQR dig_P3 @ L->D D* 256. D/ var1 D@ dig_P2 @ L->D D* 4096. D* D+ var1 D!  --- var1 = ((var1 * var1 * (BMP280_S64_t)dig_P3)>>8) + ((var1 * (BMP280_S64_t)dig_P2)<<12);
        ." 5 var1 =  " var1 D@ SD. CRLF
        $800000000000. var1 D@ D+ dig_P1 @ L->D D* 8589934592. D/ var1 D!                   --- var1 = (((((BMP280_S64_t)1)<<47)+var1))*((BMP280_S64_t)dig_P1)>>33;
        ." 6 var1 =  " var1 D@ SD. CRLF
        var1 D@ OR 0=
        IF
            0. calpress D!
        ELSE
            1048576 rawpress @ - L->D calpress D!                                           --- p = 1048576-adc_P;
            calpress D@ 2147483648. D* var2 D@ D- 3125. D* var1 D@ D/ calpress D!           --- p = (((p<<31)-var2)*3125)/var1;
            dig_P9 @ L->D calpress D@ 8192. D/ DSQR D* 33554432. D/ var1 D!                 --- var1 = (((BMP280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
            dig_P8 @ L->D calpress D@ D* 524288. D/ var2 D!                                 --- var2 = (((BMP280_S64_t)dig_P8) * p) >> 19;
            calpress D@ var1 D@ D+ var2 D@ D+ 256. D/ dig_P7 @ L->D 16. D* D+ calpress D!   --- p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)dig_P7)<<4);
        THEN
        ;
    
    --- display the raw pressure in Pascals until a key is pressed  
    pub READpress.  ( -- )
        CRLF
        READtempcal
        READpresscal
        SETUP
        BEGIN
            MEASUREWAIT
            READtemp                                --- needed to compensate the pressure reading
            READpress
            CALCpress
            ." Raw pressure value =  " rawpress @ . SPACE
            ." Calibrated pressure =  " calpress @ . ." Pascal" CRLF
        KEY UNTIL
        ;
    
        --- display the raw pressure in Pascals until a key is pressed  
    pub READpress1. ( -- )
        CRLF
        READtempcal
        READpresscal
        SETUP
        BEGIN
            MEASUREWAIT
            READtemp
            ." Calibrated temperature value = " calibtemp @ <# # # 46 HOLD #S #> PRINT$ CRLF
            CALCtemp
            READpress
            CALCpress1 .S CRLF
            ." Raw pressure value =  " rawpress @ . SPACE
            ." Calibrated pressure =  " calpress D@ 128. D/ SD. ."  units?" CRLF
        KEY UNTIL
        ;
    
    

    If you're not familiar with forth - think of each word as a call to machine code. This glossary might be helpful too. Download and open it, so that the bookmark sidebar is visible to quickly locate categories of words.

    Remember:-
    1. A forth word is anything separated by one or more spaces
    2. Stack comments e.g. ( n1 n2 -- n3 ) this would indicate two input longs n1 and n2 are needed on the stack and the word consumes them both and leaves n3 on the stack as the result
    3. Other comments are preceded by ---

    Cheers, Bob, ham radio call G4BBY

  • Hi
    Can you convert spin code?
    @avsa242 a prodigious driver writer has this
    https://github.com/avsa242/bmp280-spin
    Dave

  • avsa242avsa242 Posts: 426
    edited 2023-01-16 22:40

    Thanks for the mention, but I wouldn't recommend placing much faith in that...I started that years ago thinking "how hard could it be?" but as Jon pointed out, very. I don't even remember the last time I touched it or what state it was in, sorry :((edit: 2018...yikes)
    I thought before about maybe trying to use someone's C algorithm as a child object in flexspin, but I haven't really looked into it.

  • JRoarkJRoark Posts: 1,215
    edited 2023-01-17 00:43

    Thanks all for the good input!

    I looked at the @avsa242 repo, but I’m up against a steep learning curve as I really struggle with Spin. It just makes no sense to me. I have to support this code eventually and it doesnt seem fair to just steal code blindly with zero comprehension (I’m looking at you Arduino wags. Heheh). I have had good success translating @JonnyMac code into C and BASIC, and he’s indicated he may take swing at this too, so there may be light at the end of this tunnel! Or at least a high-octane dinner for Jon. 🤣

  • Have you taken another look at the datasheet

  • @DigitalBob Thank you for posting that data sheet as it is a bit more current than the one I had. Yup, I’ve seen it. Studied it pretty closely. It is closer to the mark, but there are still bugs.

    If you stare at that one long enough (just like its predecessors) you’ll find things like this:

    Page: 27
    “For details on how to read the temperature and pressure readings from the device, consult CHAPTER 0”. 
    

    That is not an isolated example. There is also the occasional term referenced but not defined.

    I’ll take another swing at it this weekend with your improved data sheet (thank you!) and report back. But jeeze, Bosch, why is this so complex and obscure when it could be so simple?!?

    I’ll make the following promise: if I get it working, I’ll post the code so nobody ever needs to guess at this mess again. 👍

  • Well… success! Of a sort. And a story too.

    I got the maths working after I had a look at some code from the amazing @JonnyMac. I translated it to BASIC and then I hooked-in some I2C comms in order to use live data. Epic fail. I had been using BMP280’s from a dodgy Amazon vendor and I couldnt get anything like a rational pressure. When I ran the numbers manually by hand, it became clear that my code was working fine but the data being returned from the sensors was junk. ALL THREE SENSORS WERE JUNK.

    In desperation I popped-in a BME-680 sensor breakout from Parallax, changed the code accordingly, and it now works flawlessly. (I had avoided this originally thinking it was a much more complex sensor. It really isnt).

    So once again I am reminded that there is a good reason to pay top-dollar for this stuff when it comes from a reputable vendor using top-grade parts! Thank you Parallax. And Jon!

  • Bosch has a library for driving this sensor and it compiles just fine in Flexprop which I have been using.

    Here is my github sample: P2 Custom Libraries

    They have since released the BME68X library for use with the new BME688 which is a warmed over BME680.

    Again to use their GAS sensor you need to use their tools and their compiled libraries to build an air quality sensor. They don't have a library for P2.

    They use AI to build a profile for whatever GAS your trying to smell.

    The library work just fine with Flexprop and you can read all the sensor values including the GAS sensor which make very little sense.

    I did however find a problem with Flexprop I2C driver as it did not work for me. Fortunately, I had built my own which works just fine.

    Sample program using Flexprop and Bosch library:

    /**
     * @brief BME68x Environmental Sensor
     * @author Michael Burmeister
     * @date December 7, 2019
     * @version 1.0
     * 
    */
    
    //#define DEBUG
    
    #include <stdio.h>
    #include <propeller.h>
    #include "simpletools.h"
    #include "i2c.h"
    #include "bme68x.h"
    
    #define SAMPLE_COUNT  UINT16_C(300)
    #define BMESCL 36
    #define BMESDA 37
    
    i2c_t *Bme;
    //i2c Bme;
    
    int main()
    {
    
        uint8_t dev_addr;
        uint16_t sample_count = 1;
        uint32_t del_period;
    
        /* Heater temperature in degree Celsius */
        uint16_t temp_prof[10] = { 100, 100, 200, 200, 200, 200, 320, 320, 320, 320 };
    
        /* Heating duration in milliseconds */
        uint16_t dur_prof[10] = { 280, 5740, 280, 1960, 1960, 1960, 280, 1960, 1960, 1960 };
    
        printf("Starting\n");
    
        //i2c_open(&Bme, BMESCL, BMESDA, 0);
        Bme = I2C_Init(BMESCL, BMESDA, I2C_FAST);
    
        struct bme68x_dev gas_sensor;
        struct bme68x_conf conf;
        struct bme68x_heatr_conf heatr_conf;
        struct bme68x_data data[3];
        uint32_t time_ms = 0;
        uint8_t n_fields;
        int ct;
    
        dev_addr = BME68X_I2C_ADDR_HIGH;
        gas_sensor.variant_id = BME68X_VARIANT_GAS_LOW;
        gas_sensor.intf = BME68X_I2C_INTF;
        gas_sensor.read = BME68xRead;
        gas_sensor.write = BME68xWrite;
        gas_sensor.delay_us = BME68xWait;
        gas_sensor.amb_temp = 25;
        gas_sensor.intf_ptr = &dev_addr;
    
        int8_t rslt = BME68X_OK;
        rslt = bme68x_init(&gas_sensor);
    
        printf("Results: %d\n", rslt);
    
        uint8_t set_required_settings;
        /* Set the temperature, pressure and humidity settings */
        conf.os_hum = BME68X_OS_16X;
        conf.os_pres = BME68X_OS_1X;
        conf.os_temp = BME68X_OS_2X;
        conf.filter = BME68X_FILTER_OFF;
        conf.odr = BME68X_ODR_NONE;
        rslt = bme68x_set_conf(&conf, &gas_sensor);
    
        /* Set the remaining gas sensor settings and link the heating profile */
        heatr_conf.enable = BME68X_ENABLE;
    
        /* Create a ramp heat waveform in 3 steps */
        heatr_conf.heatr_temp = 300; /* degree Celsius */
        heatr_conf.heatr_dur = 100; /* milliseconds */
        heatr_conf.heatr_temp_prof = temp_prof;
        heatr_conf.heatr_dur_prof = dur_prof;
        heatr_conf.profile_len = 10;
    
        rslt = bme68x_set_heatr_conf(BME68X_SEQUENTIAL_MODE, &heatr_conf, &gas_sensor);
    //  rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, &gas_sensor);
    
        printf("Config Results: %d\n", rslt);
    
        /* Trigger the next measurement if you would like to read data out continuously */
        rslt = bme68x_set_op_mode(BME68X_SEQUENTIAL_MODE, &gas_sensor);
    
        printf("Sample, TimeStamp(ms), Temp(deg C), Pressure(Pa), Humidity(%%), Gas resistance(ohm), Status, Gas Index, Index\n");
    
        ct = CNT;
        while(sample_count < SAMPLE_COUNT)
        {
            /* Trigger the next measurement if you would like to read data out continuously */
    //      rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &gas_sensor);
    
    //      del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, &gas_sensor) + (heatr_conf.heatr_dur * 1000);
            del_period = bme68x_get_meas_dur(BME68X_SEQUENTIAL_MODE, &conf, &gas_sensor) + (heatr_conf.heatr_dur * 1000);
    
            gas_sensor.delay_us(del_period, gas_sensor.intf_ptr);
    
            time_ms = CNT / st_msTicks;
    
    //      rslt = bme68x_get_data(BME68X_FORCED_MODE, &data, &n_fields, &gas_sensor);
            rslt = bme68x_get_data(BME68X_SEQUENTIAL_MODE, &data, &n_fields, &gas_sensor);
    
            for (int i = 0;i<n_fields;i++)
            {
                printf("%6u, %13lu, %11.2f, %12.2f, %11.2f, %19.2f, %6x, %10d, %4d\n",
                    sample_count, time_ms, data[i].temperature, data[i].pressure, data[i].humidity, 
                    data[i].gas_resistance, data[i].status, data[i].gas_index, data[i].meas_index);
    
                sample_count++;
            }
        }
    
    
      while(1)
      {
        _waitms(1000);
    
      }
    }
    
    uint8_t BME68xRead(uint8_t reg_addr, uint8_t *data, uint16_t len, void *intf_ptr)
    {
        int i;
    
        uint8_t dev_addr = *(uint8_t*)intf_ptr;
    
        //i = i2c_in(&Bme, dev_id, reg_addr, 1, data, len);
        i = I2C_In(Bme, dev_addr, reg_addr, 1, data, len);
    
    #ifdef DEBUG
        printf("Read> i:%d, addr: %x, reg:%x, Len:%d, (%x)", i, dev_addr, reg_addr, len, data[0]);
        for (int j=1;j<len;j++)
            printf(", (%x)", data[j]);
        printf("\n");
    #endif
    
        if (i > 0)
            return 0;
        else
            return -1;
    }
    
    uint8_t BME68xWrite(uint8_t reg_addr, uint8_t *data, uint16_t len, void *intf_ptr)
    {
        int i;
    
        uint8_t dev_addr = *(uint8_t*)intf_ptr;
    
        //i = i2c_out(&Bme, dev_id, reg_addr, 1, data, len);
        i = I2C_Out(Bme, dev_addr, reg_addr, 1, data, len);
    
    #ifdef DEBUG
        printf("Write> i:%d, id:%x, reg:%x, len:%d\n", i, dev_addr, reg_addr, len);
    #endif
    
        if (i > 0)
            return 0;
        else
            return -1;
    }
    
    void BME68xWait(uint32_t period, void *intf_ptr)
    {
        _waitus(period);
    }
    

    Mike

  • @iseries Thank you for that! I’ll queue that up this weekend and see if I can improve on what I have. For this design, I need a very accurate pressure and density altitude.

    A giggle: in a few weeks I’m leaving for Leadville, CO for a few days. Why? I need to test this creature and all of the code in a real-world “live fire” scenario over 10,000 feet. This should be FUN! 🤣

Sign In or Register to comment.