PDA

View Full Version : BME280 via I2C?



CuriousOne
- 22nd September 2024, 17:35
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?

9752

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...



' 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,

richard
- 23rd September 2024, 09:06
does the AI have a big grin on its face when it tries to pass that off as pbp code ?https://www.picbasic.co.uk/forum/images/icons/icon12.pnghttps://www.picbasic.co.uk/forum/images/icons/icon12.png

Ioannis
- 23rd September 2024, 18:14
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

CuriousOne
- 24th September 2024, 04:37
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 :D

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?



' 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

richard
- 24th September 2024, 04:55
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

CuriousOne
- 24th September 2024, 09:46
Thanks, I'll squeeze every drop out of it :)

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

rocket_troy
- 25th September 2024, 00:35
I've worked with the BMP180 with PBP, but not the BME280 IIRC.

Troy