Strange error when programming PIC for BMP280

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Hi,
Here are the results from 4x different BMP280 modules.
I think this tells us that the CALC has an error somewhere. I'm pretty sure that the calc is the same as a correct READing one, so I assume this error is somewhere around the Compensation parameters.
C
 

Attachments

jjw

Joined Dec 24, 2013
823
The compensation parameters look odd, as the last 14 are the same in each bm280.
I think the chip is in burst mode and it skips every other value and the last values are from variables in ram.
Try reading without dummy byte in the loop.
DIscard the first value and read past the last address.
Dim b(25) as byte.
The first value is b(1) and the last b(24)
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
The compensation parameters look odd, as the last 14 are the same in each bm280.
I think the chip is in burst mode and it skips every other value and the last values are from variables in ram.
Try reading without dummy byte in the loop.
DIscard the first value and read past the last address.
Dim b(25) as byte.
The first value is b(1) and the last b(24)
Hi J,
First I'll show you the READ section of the program (right), plus an old OSH SW good READings program (leftish) plus a READout.

See CODE for FUNCTION
C
Code:
Function rd_nxt_reg() As Byte
WaitUs 1
    SSPBUF = 0
    While Not SSPSTAT.BF
    Wend
    rd_nxt_reg = SSPBUF
End Function
 

Attachments

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Show the whole code reading the compensation parameters.
Hi J,
Here it is:
C
Code:
Proc rd_init_altmtr()  'BMP280 READ Compensation parameters that have just been WRITTEN.
For i = 0 To 23
    rd_Byte = b(i)
    Hserout "Comp PAR =", #b(i), CrLf  '?????????????COMP
Next i
End Proc                                         

Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 23
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1
        SSPBUF = 0  'Dummy BYTE
        While Not SSPSTAT.BF
        Wend
        periph_rd_alt = SSPBUF
        b(i) = periph_rd_alt
    Next i

'Temp coefficents
    t1.LB = b(0)
    t1.HB = b(1)
    t2.LB = b(2)
    t2.HB = b(3)
    t3.LB = b(4)
    t3.HB = b(5)
'pressure coefficients
    p1.LB = b(6)
    p1.HB = b(7)
    p2.LB = b(8)
    p2.HB = b(9)
    p3.LB = b(10)
    p3.HB = b(11)
    p4.LB = b(12)
    p4.HB = b(13)
    p5.LB = b(14)
    p5.HB = b(15)
    p6.LB = b(16)
    p6.HB = b(17)
    p7.LB = b(18)
    p7.HB = b(19)
    p8.LB = b(20)
    p8.HB = b(21)
    p9.LB = b(22)
    p9.HB = b(23)
'convert to singles with sign
    dig_t1 = t1
    dig_t2 = t2
    If dig_t2 > 32767 Then
        dig_t2 = dig_t2 - 65536
    Endif
    dig_t3 = t3
    If dig_t3 > 32767 Then
        dig_t3 = dig_t3 - 65536
    Endif
    dig_p1 = p1
    dig_p2 = p2
    If dig_p2 > 32767 Then
        dig_p2 = dig_p2 - 65536
    Endif
    dig_p3 = p3
    If dig_p3 > 32767 Then
        dig_p3 = dig_p3 - 65536
    Endif
    dig_p4 = p4
    If dig_p4 > 32767 Then
        dig_p4 = dig_p4 - 65536
    Endif
    dig_p5 = p5
    If dig_p5 > 32767 Then
        dig_p5 = dig_p5 - 65536
    Endif
    dig_p6 = p6
    If dig_p6 > 32767 Then
        dig_p6 = dig_p6 - 65536
    Endif
    dig_p7 = p7
    If dig_p7 > 32767 Then
        dig_p7 = dig_p7 - 65536
    Endif
    dig_p8 = p8
    If dig_p8 > 32767 Then
        dig_p8 = dig_p8 - 65536
    Endif
    dig_p9 = p9
        If dig_p9 > 32767 Then
    dig_p9 = dig_p9 - 65536
    Endif

End Proc                                         

'-------------------------------READ SPI PERIPHERALS------------------------------------------
Proc read_altmtr()

altmtr_cs = 0  'CHIP SELECT BMP280 ON
    rd_adr = 0xf7
    WaitUs 1
    SSPBUF = rd_adr
    While Not SSPSTAT.BF
    Wend
    
    p_raw.3B = rd_nxt_reg()  'Altimeter
    p_raw.HB = rd_nxt_reg()  'Altimeter
    p_raw.LB = rd_nxt_reg()  'Altimeter
    t_raw.3B = rd_nxt_reg()  'Altimeter
    t_raw.HB = rd_nxt_reg()  'Altimeter
    t_raw.LB = rd_nxt_reg()  'Altimeter
altmtr_cs = 1  'CHIP SELECT BMP280 OFF

    t_raw = ShiftRight(t_raw, 4)
    adc_t = t_raw
    p_raw = ShiftRight(p_raw, 4)
    adc_p = p_raw

Call calca()  'ALTMTR BMP280

    strtp = #tp
    strpr = #pr
'altmtr_cs = 1  'CHIP SELECT BMP280 OFF
End Proc                                         

'SHOW ALTIMETER MEASUREMENTS + TEMPERATURE + PRESSURE
Proc show_altmtr()  'BMP280
'If Len(strtx1) <> 0 Then  'Commented out to work???
    
    Hserout "ALT SHOW ", "P_MSB =", #p_raw.3B, " - ", "P_LSB =", #p_raw.HB, " - ", "P_XLSB =", #p_raw.LB, " - ", "T_MSB =", #t_raw.3B, " - ", "T_LSB =", #t_raw.HB, " - ", "T_XLSB =", #t_raw.LB, CrLf
    Hserout "TP=  ", #tp, "  ", "PR=  ", #pr, CrLf
'Endif
End Proc                                         

'ALTITUDE TEMP CALC
Proc calca()  'ALTMTR BMP280
    'Calculate temperature
    var1 = ((adc_t / 16384 - (dig_t1 / 1024))) * dig_t2
    var2 = (((adc_t) / 131072 - (dig_t1) / 8192) * (adc_t / 131072 - dig_t1 / 8192) * dig_t3)
    t_fine = var1 + var2
    tp = (var1 + var2) / 5120
    'Calculate pressure
    var1 = t_fine / 2 - 64000
    var2 = var1 * var1 * dig_p6 / 32768
    var2 = var2 + var1 * dig_p5 * 2
    var2 = var2 / 4 + dig_p4 * 65536
    var1 = ((dig_p3) * var1 * var1 / 524288 + dig_p2 * var1) / 524288
    var1 = (1 + var1 / 32768) * dig_p1
    pr = 1048576 - adc_p
    pr = (pr - (var2 / 4096)) * 6250 / var1
    var1 = dig_p9 * pr * pr / 2147483648
    var2 = pr * dig_p8 / 32768
    pr = pr + (var1 + var2 + dig_p7) / 16
End Proc   
=========================================================================

Function rd_nxt_reg() As Byte
WaitUs 1
    SSPBUF = 0
    While Not SSPSTAT.BF
    Wend
    rd_nxt_reg = SSPBUF
End Function                                      
'-------------------------------SPI FUNCTIONS-------------------------------------------------
Function periph_wr(wr_adr As Byte, wr_data As Byte) As Byte

WaitUs 1  '/// maybe not needed
SSPBUF = wr_adr
While Not SSPSTAT.BF  'PIC
Wend
WaitUs 1
SSPBUF = wr_data
While Not SSPSTAT.BF  'PIC
Wend

End Function                                      

Function periph_rd(rd_adr As Byte) As Byte
WaitUs 1
SSPBUF = rd_adr
While SSPSTAT.BF  'PIC
Wend
WaitUs 1
SSPBUF = 0  'Dummy BYTE
While Not SSPSTAT.BF  'PIC
Wend
periph_rd = SSPBUF

'While drdy_pin  'ADDED??????????????????????????
'Wend

End Function                                      

'############################################'******ADDED**************?????????
Function periph_rd_alt(rd_adr As Byte) As Byte

'WaitUs 1
SSPBUF = rd_adr
While Not SSPSTAT.BF  'PIC
Wend
'WaitUs 1'Below
While STATUS.3  'Must have this or WAIT
Wend

SSPBUF = 0  'Dummy BYTE
While Not SSPSTAT.BF  'PIC
Wend
periph_rd_alt = SSPBUF

End Function                                      
'#######################################
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Try first #62
Hi J,
I think you're on the right lines, as the CALC READings changed a lot. I don't think I iterpeted your suggestion correctly.
It would be easier for me to understand all the settings if you would change the CODE in #65, and I'll try that please.
C.
 
Last edited:

jjw

Joined Dec 24, 2013
823
Hi J,
Here it is:
C
Code:
Proc rd_init_altmtr()  'BMP280 READ Compensation parameters that have just been WRITTEN.
For i = 0 To 23
    rd_Byte = b(i)
    Hserout "Comp PAR =", #b(i), CrLf  '?????????????COMP
Next i
End Proc                                       

Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 23
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1
        SSPBUF = 0  'Dummy BYTE
        While Not SSPSTAT.BF
        Wend
        periph_rd_alt = SSPBUF
        b(i) = periph_rd_alt
    Next i

'Temp coefficents
    t1.LB = b(0)
    t1.HB = b(1)
    t2.LB = b(2)
    t2.HB = b(3)
    t3.LB = b(4)
    t3.HB = b(5)
'pressure coefficients
    p1.LB = b(6)
    p1.HB = b(7)
    p2.LB = b(8)
    p2.HB = b(9)
    p3.LB = b(10)
    p3.HB = b(11)
    p4.LB = b(12)
    p4.HB = b(13)
    p5.LB = b(14)
    p5.HB = b(15)
    p6.LB = b(16)
    p6.HB = b(17)
    p7.LB = b(18)
    p7.HB = b(19)
    p8.LB = b(20)
    p8.HB = b(21)
    p9.LB = b(22)
    p9.HB = b(23)
'convert to singles with sign
    dig_t1 = t1
    dig_t2 = t2
    If dig_t2 > 32767 Then
        dig_t2 = dig_t2 - 65536
    Endif
    dig_t3 = t3
    If dig_t3 > 32767 Then
        dig_t3 = dig_t3 - 65536
    Endif
    dig_p1 = p1
    dig_p2 = p2
    If dig_p2 > 32767 Then
        dig_p2 = dig_p2 - 65536
    Endif
    dig_p3 = p3
    If dig_p3 > 32767 Then
        dig_p3 = dig_p3 - 65536
    Endif
    dig_p4 = p4
    If dig_p4 > 32767 Then
        dig_p4 = dig_p4 - 65536
    Endif
    dig_p5 = p5
    If dig_p5 > 32767 Then
        dig_p5 = dig_p5 - 65536
    Endif
    dig_p6 = p6
    If dig_p6 > 32767 Then
        dig_p6 = dig_p6 - 65536
    Endif
    dig_p7 = p7
    If dig_p7 > 32767 Then
        dig_p7 = dig_p7 - 65536
    Endif
    dig_p8 = p8
    If dig_p8 > 32767 Then
        dig_p8 = dig_p8 - 65536
    Endif
    dig_p9 = p9
        If dig_p9 > 32767 Then
    dig_p9 = dig_p9 - 65536
    Endif

End Proc                                       

'-------------------------------READ SPI PERIPHERALS------------------------------------------
Proc read_altmtr()

altmtr_cs = 0  'CHIP SELECT BMP280 ON
    rd_adr = 0xf7
    WaitUs 1
    SSPBUF = rd_adr
    While Not SSPSTAT.BF
    Wend
  
    p_raw.3B = rd_nxt_reg()  'Altimeter
    p_raw.HB = rd_nxt_reg()  'Altimeter
    p_raw.LB = rd_nxt_reg()  'Altimeter
    t_raw.3B = rd_nxt_reg()  'Altimeter
    t_raw.HB = rd_nxt_reg()  'Altimeter
    t_raw.LB = rd_nxt_reg()  'Altimeter
altmtr_cs = 1  'CHIP SELECT BMP280 OFF

    t_raw = ShiftRight(t_raw, 4)
    adc_t = t_raw
    p_raw = ShiftRight(p_raw, 4)
    adc_p = p_raw

Call calca()  'ALTMTR BMP280

    strtp = #tp
    strpr = #pr
'altmtr_cs = 1  'CHIP SELECT BMP280 OFF
End Proc                                       

'SHOW ALTIMETER MEASUREMENTS + TEMPERATURE + PRESSURE
Proc show_altmtr()  'BMP280
'If Len(strtx1) <> 0 Then  'Commented out to work???
  
    Hserout "ALT SHOW ", "P_MSB =", #p_raw.3B, " - ", "P_LSB =", #p_raw.HB, " - ", "P_XLSB =", #p_raw.LB, " - ", "T_MSB =", #t_raw.3B, " - ", "T_LSB =", #t_raw.HB, " - ", "T_XLSB =", #t_raw.LB, CrLf
    Hserout "TP=  ", #tp, "  ", "PR=  ", #pr, CrLf
'Endif
End Proc                                       

'ALTITUDE TEMP CALC
Proc calca()  'ALTMTR BMP280
    'Calculate temperature
    var1 = ((adc_t / 16384 - (dig_t1 / 1024))) * dig_t2
    var2 = (((adc_t) / 131072 - (dig_t1) / 8192) * (adc_t / 131072 - dig_t1 / 8192) * dig_t3)
    t_fine = var1 + var2
    tp = (var1 + var2) / 5120
    'Calculate pressure
    var1 = t_fine / 2 - 64000
    var2 = var1 * var1 * dig_p6 / 32768
    var2 = var2 + var1 * dig_p5 * 2
    var2 = var2 / 4 + dig_p4 * 65536
    var1 = ((dig_p3) * var1 * var1 / 524288 + dig_p2 * var1) / 524288
    var1 = (1 + var1 / 32768) * dig_p1
    pr = 1048576 - adc_p
    pr = (pr - (var2 / 4096)) * 6250 / var1
    var1 = dig_p9 * pr * pr / 2147483648
    var2 = pr * dig_p8 / 32768
    pr = pr + (var1 + var2 + dig_p7) / 16
End Proc 
=========================================================================

Function rd_nxt_reg() As Byte
WaitUs 1
    SSPBUF = 0
    While Not SSPSTAT.BF
    Wend
    rd_nxt_reg = SSPBUF
End Function                                    
'-------------------------------SPI FUNCTIONS-------------------------------------------------
Function periph_wr(wr_adr As Byte, wr_data As Byte) As Byte

WaitUs 1  '/// maybe not needed
SSPBUF = wr_adr
While Not SSPSTAT.BF  'PIC
Wend
WaitUs 1
SSPBUF = wr_data
While Not SSPSTAT.BF  'PIC
Wend

End Function                                    

Function periph_rd(rd_adr As Byte) As Byte
WaitUs 1
SSPBUF = rd_adr
While SSPSTAT.BF  'PIC
Wend
WaitUs 1
SSPBUF = 0  'Dummy BYTE
While Not SSPSTAT.BF  'PIC
Wend
periph_rd = SSPBUF

'While drdy_pin  'ADDED??????????????????????????
'Wend

End Function                                    

'############################################'******ADDED**************?????????
Function periph_rd_alt(rd_adr As Byte) As Byte

'WaitUs 1
SSPBUF = rd_adr
While Not SSPSTAT.BF  'PIC
Wend
'WaitUs 1'Below
While STATUS.3  'Must have this or WAIT
Wend

SSPBUF = 0  'Dummy BYTE
While Not SSPSTAT.BF  'PIC
Wend
periph_rd_alt = SSPBUF

End Function                                    
'#######################################
Code:
Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 23
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1
        SSPBUF = 0  'Dummy BYTE
        While Not SSPSTAT.BF
        Wend
        periph_rd_alt = SSPBUF
        b(i) = periph_rd_alt
    Next i

Change the looping part of proc_init... to:

Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 24 '  <-----
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1    
        b(i) = SSPBUF
    Next i

Change Dim b(24) to Dim b(25)
Change
T1 = b(1)
T2 = b(2)
etc.
P9 = b(24)
I checked the calculations and they seem to be right.
Print the compensation parameters after this change.
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Code:
Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 23
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1
        SSPBUF = 0  'Dummy BYTE
        While Not SSPSTAT.BF
        Wend
        periph_rd_alt = SSPBUF
        b(i) = periph_rd_alt
    Next i

Change the looping part of proc_init... to:

Proc init_altmtr_comppar()  'READ and SET Compensation parameters

        For i = 0 To 24 '  <-----
        rd_adr = 0x88 + i  '00=WRITE 80=READ
        WaitUs 1
        SSPBUF = rd_adr
        While Not SSPSTAT.BF
        Wend
        WaitUs 1   
        b(i) = SSPBUF
    Next i

Change Dim b(24) to Dim b(25)
Change
T1 = b(1)
T2 = b(2)
etc.
P9 = b(24)
I checked the calculations and they are seem to be right.
Print the compensation parameters after this change.
Hi J,
Well done. all seems correct NOTE: TP and PR
cheers, C :)
 

Attachments

Thread Starter

camerart

Joined Feb 25, 2013
3,730
The temperature does'nt change much.
Try to warm the bmp280 a little bit.
Hi J,
The temperature is app 18° and 1001 mB
Here are READings fro 2x modules.
Note the temp rises as they 'warm' up.
They show slightly diferent TP, but if need be I'l calibrate them later.
Thanks.

Can you tell me how you knew to shift up 1x READ and not use zero?
C
 

Attachments

jjw

Joined Dec 24, 2013
823
...
Can you tell me how you knew to shift up 1x READ and not use zero?
C
Because the last 14 parameters were the same in four bmp280, so they had to come from variables in RAM ( or bmp addresses after the last address) -> the readings had skipped every other parameter.

In #72 they also have the same values ( last 7 ) so something is still wrong.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Because the last 14 parameters were the same in four bmp280, so they had to come from variables in RAM ( or bmp addresses after the last address) -> the readings had skipped every other parameter.

In #72 they also have the same values ( last 7 ) so something is still wrong.
Hi J,
Could the error be related to the the settings, e,g,
------------------------------------------------------------
'CTRL_MEAS
'WaitMs 50
altmtr_cs = 0
wr_adr = 0x74 'WRITE 0xF4 %01110100 Control CTRL_MEAS reg addr
wr_byte = 0xb7 '0xB7 %10110111 P/ON T/ON Px16 Tx2 Normal Mode
Call periph_wr(wr_adr, wr_byte)
'-------------------------------
'CONFIG
wr_adr = 0x75 'WRITE 0xF5 %01110101 Control CONFIG reg addr
wr_byte = 0x10 '%00010000 t_sb 0.5ms Table 11-11R filter x16 table 6

Call periph_wr(wr_adr, wr_byte)
-----------------------------------------------------------
C
 

jjw

Joined Dec 24, 2013
823
You could test the pressure by going to attic.
I don't remember anymore how much it should change, but there are calculators in the net for pressure vs. height


Here are some settings from a (working?)python library.
with _bmp280.CTRL_MEAS as reg:
mode('normal')
osrs_t(16) # 16x temperature oversampling
osrs_p(16) # 16x pressure oversampling


with _bmp280.CONFIG as reg:
t_sb(500)
filter(2)
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
You could test the pressure by going to attic.
I don't remember anymore how much it should change, but there are calculators in the net for pressure vs. height


Here are some settings from a (working?)python library.
with _bmp280.CTRL_MEAS as reg:
mode('normal')
osrs_t(16) # 16x temperature oversampling
osrs_p(16) # 16x pressure oversampling


with _bmp280.CONFIG as reg:
t_sb(500)
filter(2)
Hi J,
You calculated the height of my stairs before, and I've been seaching for it, but so far failed. Leave it for now, and I'll let you know if I find it.
I did the READings again, in case we find how you did it before:
Down stairs TP 20.30 PR 102393
Upstairs TP 1994 PR 102360

CTRL_MEAS and CONFIG settings are commented and are similar to the ones you posted, but for my application, where there will be turbulence. I think they are ok.
I may have to recheck later.
C.
 
Top