BME280 via I2C?


+ Reply to Thread
Results 1 to 7 of 7

Thread: BME280 via I2C?

  1. #1
    Join Date
    Feb 2013
    Posts
    1,099

    Default BME280 via I2C?

    Hello.
    I know there is a library for BME280 via SPI, but most recent modules are I2C only. Is there a way to adapt that code to I2C bus?

    Name:  bmeee.jpg
Views: 146
Size:  84.5 KB

    I asked AI to generate code for I2C, but it won't compile - "Redefiniton of label dim" (I see it has issues with label definition) and also seems to be incomplete...

    Code:
    ' PicBasic Pro Code to Read Pressure, Temperature, and Humidity from BME280
    
    
    ' Define I2C pins
    DEFINE I2C_SCL PORTC.3  ' Define SCL pin (use appropriate pin)
    DEFINE I2C_SDA PORTC.4  ' Define SDA pin (use appropriate pin)
    
    
    ' Define BME280 I2C address
    Symbol BME280_Address = $EC    ' BME280 I2C address (write mode, default 0x76)
    Symbol BME280_Read = $ED       ' BME280 I2C address (read mode)
    
    
    ' Define BME280 registers
    Symbol BME280_Reg_Control_Hum = $F2 ' Humidity control register
    Symbol BME280_Reg_Control_Meas = $F4 ' Measurement control register
    Symbol BME280_Reg_Config = $F5       ' Configuration register
    Symbol BME280_Reg_Pressure_MSB = $F7 ' Pressure MSB register
    
    
    ' Variables for raw sensor data
    Dim dig_T1 As Word, dig_P1 As Word, dig_H1 As Byte, dig_H2 As Integer
    Dim dig_T2 As Integer, dig_T3 As Integer
    Dim dig_P2 As Integer, dig_P3 As Integer, dig_P4 As Integer, dig_P5 As Integer
    Dim dig_P6 As Integer, dig_P7 As Integer, dig_P8 As Integer, dig_P9 As Integer
    Dim dig_H3 As Byte, dig_H4 As Integer, dig_H5 As Integer, dig_H6 As Integer
    
    
    Dim adc_T As Long, adc_P As Long, adc_H As Word
    Dim t_fine As Long
    
    
    ' Subroutine to read an unsigned 16-bit value from a register
    Sub ReadUInt16(ByVal Reg As Byte, Dim ByRef Result As Word)
        Dim MSB As Byte
        Dim LSB As Byte
        
        I2CWRITE BME280_Address, Reg            ' Send register address
        I2CREAD BME280_Read, MSB, [LSB]         ' Read MSB and LSB
        Result = (MSB << 8) + LSB               ' Combine MSB and LSB into a 16-bit word
    End Sub
    
    
    ' Subroutine to read a signed 16-bit value from a register
    Sub ReadInt16(ByVal Reg As Byte, Dim ByRef Result As Integer)
        Dim MSB As Byte
        Dim LSB As Byte
        
        I2CWRITE BME280_Address, Reg            ' Send register address
        I2CREAD BME280_Read, MSB, [LSB]         ' Read MSB and LSB
        Result = (MSB << 8) + LSB               ' Combine MSB and LSB into a 16-bit integer
    End Sub
    
    
    ' Subroutine to read an 8-bit value from a register
    Sub ReadUInt8(ByVal Reg As Byte, Dim ByRef Result As Byte)
        I2CWRITE BME280_Address, Reg            ' Send register address
        I2CREAD BME280_Read, Result             ' Read 8-bit value
    End Sub
    
    
    ' Subroutine to read calibration data
    Sub ReadCalibrationData()
        ReadUInt16($88, dig_T1)
        ReadInt16($8A, dig_T2)
        ReadInt16($8C, dig_T3)
        ReadUInt16($8E, dig_P1)
        ReadInt16($90, dig_P2)
        ReadInt16($92, dig_P3)
        ReadInt16($94, dig_P4)
        ReadInt16($96, dig_P5)
        ReadInt16($98, dig_P6)
        ReadInt16($9A, dig_P7)
        ReadInt16($9C, dig_P8)
        ReadInt16($9E, dig_P9)
        ReadUInt8($A1, dig_H1)
        ReadInt16($E1, dig_H2)
        ReadUInt8($E3, dig_H3)
        dig_H4 = (ReadUInt8($E4) << 4) + (ReadUInt8($E5) & $0F)
        dig_H5 = (ReadUInt8($E6) << 4) + (ReadUInt8($E5) >> 4)
        ReadInt8($E7, dig_H6)
    End Sub
    
    
    ' Subroutine to start the BME280 measurement
    Sub StartMeasurement()
        I2CWRITE BME280_Address, BME280_Reg_Control_Hum, [$01]  ' Set humidity oversampling to x1
        I2CWRITE BME280_Address, BME280_Reg_Control_Meas, [$27] ' Set temp and pressure oversampling to x1, mode to normal
        I2CWRITE BME280_Address, BME280_Reg_Config, [$A0]       ' Set standby time to 1000ms
    End Sub
    
    
    ' Subroutine to read raw data from the sensor
    Sub ReadRawData()
        Dim data(8) As Byte
        
        I2CWRITE BME280_Address, BME280_Reg_Pressure_MSB         ' Set register pointer to pressure MSB
        I2CREAD BME280_Read, data[0], [data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]] ' Read 8 bytes of data
    
    
        adc_P = (data[0] << 12) + (data[1] << 4) + (data[2] >> 4) ' Pressure raw
        adc_T = (data[3] << 12) + (data[4] << 4) + (data[5] >> 4) ' Temperature raw
        adc_H = (data[6] << 8) + data[7]                          ' Humidity raw
    End Sub
    
    
    ' Subroutine to calculate true temperature
    Function CalculateTemperature() As Long
        Dim var1 As Long, var2 As Long, T As Long
        
        var1 = (((adc_T >> 3) - (dig_T1 << 1)) * dig_T2) >> 11
        var2 = (((((adc_T >> 4) - dig_T1) * ((adc_T >> 4) - dig_T1)) >> 12) * dig_T3) >> 14
        t_fine = var1 + var2
        T = (t_fine * 5 + 128) >> 8
        
        CalculateTemperature = T
    End Function
    
    
    ' Subroutine to calculate true pressure
    Function CalculatePressure() As Long
        Dim var1 As Long, var2 As Long
        Dim P As Long
        
        var1 = (t_fine >> 1) - 64000
        var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * dig_P6
        var2 = var2 + ((var1 * dig_P5) << 1)
        var2 = (var2 >> 2) + (dig_P4 << 16)
        var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((dig_P2 * var1) >> 1)) >> 18
        var1 = ((32768 + var1) * dig_P1) >> 15
        If var1 = 0 Then
            CalculatePressure = 0 ' Avoid division by zero
        Else
            P = (((1048576 - adc_P) - (var2 >> 12))) * 3125
            If P < $80000000 Then
                P = (P << 1) / var1
            Else
                P = (P / var1) * 2
            End If
            var1 = (dig_P9 * (((P >> 3) * (P >> 3)) >> 13)) >> 12
            var2 = (((P >> 2)) * dig_P8) >> 13
            P = P + ((var1 + var2 + dig_P7) >> 4)
            CalculatePressure = P
        End If
    End Function
    
    
    ' Subroutine to calculate true humidity
    Function CalculateHumidity() As Long
        Dim H As Long
        
        H = (t_fine - 76800)
        H = (((((adc_H << 14) - (dig_H4 << 20) - (dig_H5 * H)) + 16384) >> 15) * (((((((H * dig_H6) >> 10) * (((H * dig_H3) >> 11) + 32768)) >> 10) + 2097152) * dig_H2 + 8192) >> 14))
        H = H - (((((H >> 15) * (H >> 15)) >> 7) * dig_H1) >> 4)
        H = (H < 0) ? 0 : H
        H = (H > 419430400) ? 419430400 : H
        CalculateHumidity = (H >> 12)
    End Function
    
    
    ' Main program
    Start:
        ' Initialize the BME280 sensor
        ReadCalibrationData()  ' Read calibration coefficients
        StartMeasurement()      ' Start measurement
    
    
        ' Read raw data from the sensor
        ReadRawData()
    
    
        ' Calculate temperature, pressure,

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,470


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    does the AI have a big grin on its face when it tries to pass that off as pbp code ?
    Last edited by richard; - 23rd September 2024 at 09:09.
    Warning I'm not a teacher

  3. #3
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,947


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    Obviously it will not compile when you define variables like this

    Dim dig_T1 As Word, dig_P1 As Word, dig_H1 As Byte, dig_H2 As Integer

    Use the correct PBP syntax and try again.

    Ioannis

  4. #4
    Join Date
    Feb 2013
    Posts
    1,099


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    I asked to make corrections and he(or it?) created new code, this time with SWORD type variables
    when I asked what kind is SWORD variables is, it answered that these are variables not supported by PBP

    After some discussion, it finally generated more "normal" looking code, but this needs PBPL, I never used it, can microcode studio modified to launch PBPL automatically?

    Code:
    ' PicBasic Pro Code to Read Pressure, Temperature, and Humidity from BME280
    
    
    ' Define I2C pins
    DEFINE I2C_SCL PORTC.3  ' Define SCL pin (use appropriate pin)
    DEFINE I2C_SDA PORTC.4  ' Define SDA pin (use appropriate pin)
    
    
    ' Define BME280 I2C address
    Symbol BME280_Address = $EC    ' BME280 I2C address (write mode, default 0x76)
    Symbol BME280_Read = $ED       ' BME280 I2C address (read mode)
    
    
    ' Define BME280 registers
    Symbol BME280_Reg_Control_Hum = $F2 ' Humidity control register
    Symbol BME280_Reg_Control_Meas = $F4 ' Measurement control register
    Symbol BME280_Reg_Config = $F5       ' Configuration register
    Symbol BME280_Reg_Pressure_MSB = $F7 ' Pressure MSB register
    
    
    ' Variables for calibration and raw sensor data
    dig_T1 VAR WORD
    dig_P1 VAR WORD
    dig_H1 VAR BYTE
    dig_H2 VAR WORD
    dig_T2 VAR WORD
    dig_T3 VAR WORD
    dig_P2 VAR WORD
    dig_P3 VAR WORD
    dig_P4 VAR WORD
    dig_P5 VAR WORD
    dig_P6 VAR WORD
    dig_P7 VAR WORD
    dig_P8 VAR WORD
    dig_P9 VAR WORD
    dig_H3 VAR BYTE
    dig_H4 VAR WORD
    dig_H5 VAR WORD
    dig_H6 VAR BYTE
    
    
    adc_T VAR LONG
    adc_P VAR LONG
    adc_H VAR WORD
    t_fine VAR LONG
    
    
    ' Temporary variables for handling read data
    MSB VAR BYTE
    LSB VAR BYTE
    Result VAR WORD
    data0 VAR BYTE
    data1 VAR BYTE
    data2 VAR BYTE
    data3 VAR BYTE
    data4 VAR BYTE
    data5 VAR BYTE
    data6 VAR BYTE
    data7 VAR BYTE
    data8 VAR BYTE
    
    
    ' Subroutine to read an unsigned 16-bit value from a register
    ReadUInt16:
        I2CWRITE BME280_Address, [Reg]          ' Send register address
        I2CREAD BME280_Read, [MSB], [LSB]       ' Read MSB and LSB
        Result = (MSB << 8) + LSB               ' Combine MSB and LSB into a 16-bit word
    RETURN
    
    
    ' Subroutine to read a signed 16-bit value from a register
    ReadInt16:
        I2CWRITE BME280_Address, [Reg]          ' Send register address
        I2CREAD BME280_Read, [MSB], [LSB]       ' Read MSB and LSB
        Result = (MSB << 8) + LSB               ' Combine MSB and LSB into a 16-bit integer
    
    
        ' Handle signed 16-bit conversion
        IF Result > 32767 THEN
            Result = Result - 65536
        ENDIF
    RETURN
    
    
    ' Subroutine to read an 8-bit value from a register
    ReadUInt8:
        I2CWRITE BME280_Address, [Reg]          ' Send register address
        I2CREAD BME280_Read, [Result]           ' Read 8-bit value
    RETURN
    
    
    ' Subroutine to read calibration data
    ReadCalibrationData:
        Reg = $88 : GOSUB ReadUInt16 : dig_T1 = Result
        Reg = $8A : GOSUB ReadInt16 : dig_T2 = Result
        Reg = $8C : GOSUB ReadInt16 : dig_T3 = Result
        Reg = $8E : GOSUB ReadUInt16 : dig_P1 = Result
        Reg = $90 : GOSUB ReadInt16 : dig_P2 = Result
        Reg = $92 : GOSUB ReadInt16 : dig_P3 = Result
        Reg = $94 : GOSUB ReadInt16 : dig_P4 = Result
        Reg = $96 : GOSUB ReadInt16 : dig_P5 = Result
        Reg = $98 : GOSUB ReadInt16 : dig_P6 = Result
        Reg = $9A : GOSUB ReadInt16 : dig_P7 = Result
        Reg = $9C : GOSUB ReadInt16 : dig_P8 = Result
        Reg = $9E : GOSUB ReadInt16 : dig_P9 = Result
        Reg = $A1 : GOSUB ReadUInt8 : dig_H1 = Result
        Reg = $E1 : GOSUB ReadInt16 : dig_H2 = Result
        Reg = $E3 : GOSUB ReadUInt8 : dig_H3 = Result
        Reg = $E4 : GOSUB ReadUInt8 : MSB = Result
        Reg = $E5 : GOSUB ReadUInt8 : LSB = Result
        dig_H4 = (MSB << 4) + (LSB & $0F)
        Reg = $E6 : GOSUB ReadUInt8 : MSB = Result
        dig_H5 = (MSB << 4) + (LSB >> 4)
        Reg = $E7 : GOSUB ReadUInt8 : dig_H6 = Result
    RETURN
    
    
    ' Subroutine to start the BME280 measurement
    StartMeasurement:
        I2CWRITE BME280_Address, [BME280_Reg_Control_Hum, $01]  ' Set humidity oversampling to x1
        I2CWRITE BME280_Address, [BME280_Reg_Control_Meas, $27] ' Set temp and pressure oversampling to x1, mode to normal
        I2CWRITE BME280_Address, [BME280_Reg_Config, $A0]       ' Set standby time to 1000ms
    RETURN
    
    
    ' Subroutine to read raw data from the sensor
    ReadRawData:
        I2CWRITE BME280_Address, [BME280_Reg_Pressure_MSB]         ' Set register pointer to pressure MSB
        I2CREAD BME280_Read, [data0, data1, data2, data3, data4, data5, data6, data7, data8] ' Read 8 bytes of data
    
    
        adc_P = (data0 << 12) + (data1 << 4) + (data2 >> 4) ' Pressure raw
        adc_T = (data3 << 12) + (data4 << 4) + (data5 >> 4) ' Temperature raw
        adc_H = (data6 << 8) + data7                        ' Humidity raw
    RETURN
    
    
    ' Subroutine to calculate true temperature
    CalculateTemperature:
        var1 = (((adc_T >> 3) - (dig_T1 << 1)) * dig_T2) >> 11
        var2 = (((((adc_T >> 4) - dig_T1) * ((adc_T >> 4) - dig_T1)) >> 12) * dig_T3) >> 14
        t_fine = var1 + var2
        T = (t_fine * 5 + 128) >> 8
    RETURN T
    
    
    ' Subroutine to calculate true pressure
    CalculatePressure:
        var1 = (t_fine >> 1) - 64000
        var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * dig_P6
        var2 = var2 + ((var1 * dig_P5) << 1)
        var2 = (var2 >> 2) + (dig_P4 << 16)
        var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((dig_P2 * var1) >> 1)) >> 18
        var1 = ((32768 + var1) * dig_P1) >> 15
        IF var1 = 0 THEN
            P = 0 ' Avoid division by zero
        ELSE
            P = (((1048576 - adc_P) - (var2 >> 12))) * 3125
            IF P < $80000000 THEN
                P = (P << 1) / var1
            ELSE
                P = (P / var1) * 2
            ENDIF
            var1 = (dig_P9 * (((P >> 3) * (P >> 3)) >> 13)) >> 12
            var2 = (((P >> 2)) * dig_P8) >> 13
            P = P + ((var1 + var2 + dig_P7) >> 4)
        ENDIF
    RETURN P
    
    
    ' Subroutine to calculate true humidity
    CalculateHumidity:
        H = (t_fine - 76800)
        H = (((((adc_H << 14) - (dig_H4 << 20) - (dig_H5 * H)) + 16384) >> 15) * (((((((H * dig_H6) >> 10) * (((H * dig_H3) >> 11) + 32768)) >> 10) + 2097152) * dig_H2 + 8192) >> 14))
        H = H - (((((H >> 15) * (H >> 15)) >> 7) * dig_H1) >> 4)
        H = (H < 0) ? 0 : H
        H = (H > 419430400) ? 419430400 : H
    RETURN (H >> 12)
    
    
    ' Main program
    Start:
        ' Initialize the BME280 sensor
        GOSUB ReadCalibrationData  ' Read calibration coefficients
        GOSUB StartMeasurement     ' Start measurement
    
    
        ' Main loop: read data continuously
    MainLoop:
        GOSUB ReadRawData          ' Read raw data
        GOSUB CalculateTemperature ' Calculate true temperature
        GOSUB CalculatePressure    ' Calculate true pressure
        GOSUB CalculateHumidity    ' Calculate true humidity
    
    
        ' Display results (you can modify this to fit your output method)
        DEBUG "Temperature: ", DEC T, " C", 13, 10
        DEBUG "Pressure: ", DEC P, " Pa", 13, 10
        DEBUG "Humidity: ", DEC H, " %", 13, 10
    
    
        PAUSE 1000  ' Wait 1 second before the next reading
        GOTO MainLoop

  5. #5
    Join Date
    May 2013
    Location
    australia
    Posts
    2,470


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    H = (H > 419430400) ? 419430400 : H
    good luck getting the ternary operator to work with pbp

    RETURN (H >> 12)
    good luck getting pbp subroutines to return a value

    can microcode studio modified to launch PBPL
    just tick the box in the compile options
    Warning I'm not a teacher

  6. #6
    Join Date
    Feb 2013
    Posts
    1,099


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    Thanks, I'll squeeze every drop out of it

    It's just matter of curiosity, rather than actual need...

  7. #7
    Join Date
    Dec 2010
    Location
    Melbourne Australia
    Posts
    160


    Did you find this post helpful? Yes | No

    Default Re: BME280 via I2C?

    I've worked with the BMP180 with PBP, but not the BME280 IIRC.

    Troy

Similar Threads

  1. BME280 sensor.
    By HenrikOlsson in forum PBP3
    Replies: 19
    Last Post: - 18th October 2020, 06:46
  2. I2C two master on one I2C display
    By Kmt in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 22nd September 2014, 20:44
  3. I2C help Please
    By snuff28 in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 29th December 2011, 16:12
  4. I2C help!
    By linoko in forum mel PIC BASIC
    Replies: 1
    Last Post: - 24th December 2005, 09:13

Members who have read this thread : 8

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts