BME280

Suche Hilfe zum BME280

  • 1
  • 2
  • Page 1 of 2
rage
Benutzer
Avatar
Gender: n/a
Age: 65
Homepage: processanalytik.de
Posts: 237
Registered: 02 / 2007
Subject:

BME280

 · 
Posted: 21.04.2017 - 11:32  ·  #1
Guten Tag

Bevor mir die grauen Haare ausgehen, frag ich hier mal in die Runde, ob mit dem Bosch-Sensor schon jemand was gemacht hat und mir dabei ein paar Sourceschnipsel zur Verfügung stellen kann. Ich habe Probleme mit dem Feuchteanteil, wenn ich den Teil ausschalte bekomme ich fein $8000 zurück geliefert (also deaktiviert), wenn ich ihn einschalte immer nur $0000.
Beim Rest also dem Umsetzen des C_Source in Pascal bin ich mir auch nicht sicher, ob das so korrekt ist. Wobei die Werte schlüssig sind.

Code

const
  BMx280a                : Byte = %1110110;
  BMx280b                : Byte = %1110111;
  BMP280_REG_DIG_T1      : Byte = $88;
  BMP280_REG_DIG_T2      : Byte = $8A;
  BMP280_REG_DIG_T3      : Byte = $8C;

  BMP280_REG_DIG_P1      : Byte = $8E;
  BMP280_REG_DIG_P2      : Byte = $90;
  BMP280_REG_DIG_P3      : Byte = $92;
  BMP280_REG_DIG_P4      : Byte = $94;
  BMP280_REG_DIG_P5      : Byte = $96;
  BMP280_REG_DIG_P6      : Byte = $98;
  BMP280_REG_DIG_P7      : Byte = $9A;
  BMP280_REG_DIG_P8      : Byte = $9C;
  BMP280_REG_DIG_P9      : Byte = $9E;

  BMP280_REG_DIG_H1      : Byte = $A1;
  BMP280_REG_DIG_H2      : Byte = $E1;
  BMP280_REG_DIG_H3      : Byte = $E3;
  BMP280_REG_DIG_H4      : Byte = $E4;
  BMP280_REG_DIG_H5      : Byte = $E5;
  BMP280_REG_DIG_H6      : Byte = $E7;

  BMP280_REG_CHIPID      : Byte = $D0;
  BMP280_REG_VERSION     : Byte = $D1;
  BMP280_REG_SOFTRESET   : Byte = $E0;

  BMP280_REG_CAL26       : Byte = $E1;  // R calibration stored in 0xE1-0xF0


  BME280_REG_CONTROLHUMID: Byte = $F2;
  BME280_REG_STATUS      : Byte = $F3;
  BMP280_REG_CONTROLMEAS : Byte = $F4;
  BMP280_REG_CONFIG      : Byte = $F5;
  BMP280_REG_PRESSUREDATA: Byte = $F7;
  BMP280_REG_TEMPDATA    : Byte = $FA;
  BME280_REG_HUMIDDATA   : Byte = $FD;

type
  TBMP280CalibData=Record
    dig_T1  : LongInt;
    dig_T2  : LongInt;
    dig_T3  : LongInt;

    dig_P1  : LongInt;
    dig_P2  : LongInt;
    dig_P3  : LongInt;
    dig_P4  : LongInt;
    dig_P5  : LongInt;
    dig_P6  : LongInt;
    dig_P7  : LongInt;
    dig_P8  : LongInt;
    dig_P9  : LongInt;

    dig_H1  : LongInt;
    dig_H2  : LongInt;
    dig_H3  : LongInt;
    dig_H4  : LongInt;
    dig_H5  : LongInt;
    dig_H6  : LongInt;
  end;//bmp280_calib_data;
var
  t_fine           : LongInt;
  BMx280Flag         : Byte;
  BMx280AOK     [@BMx280Flag,0]: Bit;
  BME280AOK     [@BMx280Flag,1]: Bit;
  BME280ACalibOK[@BMx280Flag,2]: Bit;
  BMx280BOK     [@BMx280Flag,4]: Bit;

  BMP280CalibData:TBMP280CalibData;

Function  ReadBMPRegister(I2CAdr:Byte;Reg:Byte):Word;
var Res1,Res2:Byte;
var Res:Word;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res1);   //Register lesen
   I2C_Inp(I2CAdr, Res2);   //Register lesen
   Res:=(Word(Res2) shl 8)+Word(Res1);
   Return(Res);
end;

Function  ReadBMPRegisterS(I2CAdr:Byte;Reg:Byte):Integer;
var Res1,Res2:Byte;
var Res:Integer;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   //I2C_Inp(I2CAdr, Res);   //Register lesen
   I2C_Inp(I2CAdr, Res1);   //Register lesen
   I2C_Inp(I2CAdr, Res2);   //Register lesen
   //Swap(Res);
   Res:=(Integer(Res2) shl 8)+Integer(Res1);
   Return(Res);
end;
{var Res:Integer;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res);   //Register lesen
   Return(Res);
end;}

Function  ReadBMPRegisterByte(I2CAdr:Byte;Reg:Byte):Byte;
var Res:Byte;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res);   //Register lesen
   Return(Res);
end;

Function  ReadBMPRegisterH5(I2CAdr:Byte;Reg:Byte):Word;
var Res1,Res2:Byte;
var Res:Word;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res1);   //Register lesen
   I2C_Inp(I2CAdr, Res2);   //Register lesen
   Res1:=(Res1 shr 4) and $0F;
   Res:=(Word(Res2) shl 4) or Word(Res1);
   Return(Res);
end;

Function  ReadBMPRegisterH4(I2CAdr:Byte;Reg:Byte):Word;
var Res1,Res2:Byte;
var Res:Word;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res1);   //Register lesen
   I2C_Inp(I2CAdr, Res2);   //Register lesen
   Res2:=Res2 and $0F;
   Res:=(Word(Res1) shl 4) or Word(Res2);
   Return(Res);
end;

Procedure ReadBMPConfig(I2CAdr:Byte);
var Res:Integer;
Begin
  BMP280CalibData.dig_T1 := LongInt(ReadBMPRegister(I2CAdr,BMP280_REG_DIG_T1));
  BMP280CalibData.dig_T2 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_T2));
  BMP280CalibData.dig_T3 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_T3));

  BMP280CalibData.dig_P1 := LongInt(ReadBMPRegister(I2CAdr,BMP280_REG_DIG_P1));
  BMP280CalibData.dig_P2 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P2));
  BMP280CalibData.dig_P3 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P3));
  BMP280CalibData.dig_P4 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P4));
  BMP280CalibData.dig_P5 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P5));
  BMP280CalibData.dig_P6 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P6));
  BMP280CalibData.dig_P7 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P7));
  BMP280CalibData.dig_P8 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P8));
  BMP280CalibData.dig_P9 := LongInt(ReadBMPRegisterS(I2CAdr,BMP280_REG_DIG_P9));
  
  BMP280CalibData.dig_H1 := LongInt(ReadBMPRegisterByte(I2CAdr,BMP280_REG_DIG_H1));
  BMP280CalibData.dig_H2 := LongInt(ReadBMPRegisterS   (I2CAdr,BMP280_REG_DIG_H2));
  BMP280CalibData.dig_H3 := LongInt(ReadBMPRegisterByte(I2CAdr,BMP280_REG_DIG_H3));
  BMP280CalibData.dig_H4 := LongInt(ReadBMPRegisterH4  (I2CAdr,BMP280_REG_DIG_H4));
  BMP280CalibData.dig_H5 := LongInt(ReadBMPRegisterH5  (I2CAdr,BMP280_REG_DIG_H5));
  BMP280CalibData.dig_H6 := LongInt(ReadBMPRegisterByte(I2CAdr,BMP280_REG_DIG_H6));

end;

Function  Read24(I2CAdr:Byte;Reg:Byte):LongInt;
var Res:Byte;
    Temp,Temp1,Temp2,Temp3:LongInt;
Begin
   I2C_Out(I2CAdr, Reg);   //Adress auf Register 0
   I2C_Inp(I2CAdr, Res);   //Register lesen
   Temp1:=LongInt(Res);
   I2C_Inp(I2CAdr, Res);   //Register lesen
   Temp2:=LongInt(Res);
   I2C_Inp(I2CAdr, Res);   //Register lesen
   Temp3:=LongInt(Res);
   Temp:=(Temp1 shl 16) or (Temp2 shl 8) or Temp3;
   Return(Temp);
end;

Procedure ReadBMP280Temperature(I2CAdr:Byte);
Var adc_t,var1,var2 : LongInt;
    dig_T1,dig_T2,dig_T3:LongInt;
Begin
  adc_t:= Read24(I2CAdr,BMP280_REG_TEMPDATA);
  if adc_t=$800000 then
    SensorTemperatur:=-300.0;
  else
    adc_t:=adc_t shr 4;

    var1 := ((((adc_T shr 3) - (BMP280CalibData.dig_T1  shl 1))) * (BMP280CalibData.dig_T2)) shr 11;

    var2 := (((((adc_T shr 4) - (BMP280CalibData.dig_T1)) * ((adc_T shr 4) - (BMP280CalibData.dig_T1))) shr 12) * (BMP280CalibData.dig_T3)) shr 14;

    t_fine := var1 + var2;

    SensorTemperatur := Float((t_fine * 5 + 128) shr 8);
    SensorTemperatur := SensorTemperatur / 100;
    

    var1 := ((adc_T div  16384) - (BMP280CalibData.dig_T1 div 1024)) * BMP280CalibData.dig_T2;
    var2 := ((adc_T div 131072) - (BMP280CalibData.dig_T1 div 8192)) * ((adc_T div 131072) - (BMP280CalibData.dig_T1 div 8192)) * BMP280CalibData.dig_T3;
    t_fine := var1 + var2;
    //SensorTemperatur := Float(t_fine div 5120);
    var1 := ((((adc_T shr 3) - (BMP280CalibData.dig_T1 shl 1))) * (BMP280CalibData.dig_T2)) shr 11;
    var2 := (((((adc_T shr 4) - (BMP280CalibData.dig_T1)) * ((adc_T shr 4) - (BMP280CalibData.dig_T1))) shr 12) * (BMP280CalibData.dig_T3)) shr 14;
    t_fine := var1 + var2;
    SensorTemperatur := Float((t_fine * 5 + 128) shr 8);
  endif;
end;

Procedure ReadBMP280PressureEx(I2CAdr:Byte);
var adc_p,temp1,temp2:LongInt;
    p1:Fix64;
    p:Int64;
    var1,var2:Int64;
    temp64:int64;
    Result:Float;
begin
  adc_p:= Read24(I2CAdr,BMP280_REG_PRESSUREDATA);
  if adc_p=$800000 then
    SensorLuftDruck:=-300.0;
  else
    adc_p:= adc_p shr 4;

    var1 := Int64(t_fine) - 128000;
    var2 := var1 * var1 * int64(BMP280CalibData.dig_P6);
    var2 := var2 + ((var1*Int64(BMP280CalibData.dig_P5)) shl 17);
    var2 := var2 + (Int64(BMP280CalibData.dig_P4) shl 35);
    var1 := ((var1 * var1 * Int64(BMP280CalibData.dig_P3) shr 8) + (var1 * Int64(BMP280CalibData.dig_P2)) shl 12);
    var1 := (((1 shl 47)+var1) * (Int64(BMP280CalibData.dig_P1)) shr 33);

    if var1=0 then
      SensorLuftDruck:=0;
    else
      p   := 1048576 - Int64(adc_P);
      p   := (((p shl 31) - var2)*3125) div var1;
      
      var1:= (Int64(BMP280CalibData.dig_P9) * (p shr 13) * (p shr 13)) shr 25;
      var2:= (Int64(BMP280CalibData.dig_P8) * p) shr 19;

      p   := ((p + var1 + var2) shr 8) + (Int64(BMP280CalibData.dig_P7) shl 4);
      p   := p div 256;
    endif;
  endif;
 end;
 
Procedure ReadBMP280Pressure(I2CAdr:Byte);
var adc_p,press1, press2,v1,v2:LongInt;
    P:LongInt;
begin
  adc_p:= Read24(I2CAdr,BMP280_REG_PRESSUREDATA);
  if adc_p=$800000 then
    SensorLuftDruck:=-300.0;
  else
    adc_p:= adc_p shr 4;

    v1 := (t_fine div 2) - 64000;
    v2 := (((v1 div 4) * (v1 div 4)) div 2048) * BMP280CalibData.dig_P6;
    v2 := v2 + ((v1 * BMP280CalibData.dig_P5) * 2);
    v2 := (v2 div 4) + (BMP280CalibData.dig_P4 * 65536);
    v1 := (((BMP280CalibData.dig_P3 * (((v1 div 4) * (v1 div 4)) div 8192)) div 8)  + ((BMP280CalibData.dig_P2 * v1) div 2)) div 262144;
    v1 := ((32768 + v1) * BMP280CalibData.dig_P1) div 32768;

    if v1 = 0 then
      SensorLuftDruck:=0;
    else
      p:= ((1048576 - adc_P) - (v2 div 4096)) * 3125;
      if p < $80000000 then
        p := (p * 2) div v1;
      else
        p := (p div v1) * 2;
      endif;
      v1 := (BMP280CalibData.dig_P9 * (((p div 8) * (p div 8)) div 81920)) div 4096;
      v2 := ((p div 4) * BMP280CalibData.dig_P8) div 8192;
      p  := p + ((v1 + v2 + BMP280CalibData.dig_P7) div 16);
      SensorLuftDruck:=Float(p) / 100;
    endif;

  endif;
 end;

Procedure Read280Humidity(I2CAdr:Byte);
var adc_H,varh:Longint;
Begin
  adc_H := LongInt(ReadBMPRegister(I2CAdr,BME280_REG_HUMIDDATA));
  if adc_h=$8000 then
    SensorLuftFeuchte:=-200.0;
  else

    varh := t_fine - 76800;
    if varh = 0 then
      SensorLuftFeuchte:=0;
    else
      varh := (adc_H - (BMP280CalibData.dig_H4 * 64 + BMP280CalibData.dig_H5 div 16384 * varh)) * (BMP280CalibData.dig_H2 div 65536 * (1 + BMP280CalibData.dig_H6 div 67108864 * varh * (1 + BMP280CalibData.dig_H3 div 67108864 * varh)));
      varh := varh * (1 - BMP280CalibData.dig_H1 * varh div 524288);
      if varh > 100 then
        varh := 100;
      elsif varh < 0 then
        varh := 0;
      endif;
      SensorLuftFeuchte:=Float(varh) / 100;
    endif;
  endif;
end;

 (**************************************************************************)
(*!
    @brief Result:= true if chip is busy reading cal data
*)
(**************************************************************************)
Function BMP280isReadingCalibration(I2CAdr:Byte):Boolean;
var rStatus:Byte;
    res:Boolean;
Begin
  Res:=False;
  if I2C_Out(I2CAdr,BME280_REG_STATUS) then
    if I2C_Inp(I2CAdr,rStatus) then                                  //Register lesen
      Res:=(rStatus and 1) <> 0;
    endif;
  endif;
  Return(Res);
end;

Function BMP280isReady(I2CAdr:Byte):Boolean;
var rStatus:Byte;
    res:Boolean;
Begin
  Res:=False;
  if I2C_Out(I2CAdr,BME280_REG_STATUS) then
    if I2C_Inp(I2CAdr,rStatus) then                                  //Register lesen
      Res:=rStatus = 0;
    endif;
  endif;
  Return(Res);
end;

Function CheckBMx280:Boolean;
var ID:Byte;
Begin
  BMx280Flag:=0;
  BMx280AOK :=I2C_Stat(BMx280a);                                    //Test ob BMx280 vorhanden
  if not BMx280AOK then
    BMx280BOK :=I2C_Stat(BMx280b);                                  //Test ob BMx280 vorhanden
  endif;
  if BMx280AOK then
    if I2C_Out(BMx280a, BMP280_REG_CHIPID) then                     //Adress auf Register 0
      if I2C_Inp(BMx280a, ID) then                                  //Register lesen
        BME280AOK:=ID=$60;
        if BME280AOK then
          I2C_Out(BMx280a,BMP280_REG_SOFTRESET, $B6);
          mDelay(300);                                              // 300 ms warten
          ID:=0;
          while BMP280isReadingCalibration(BMx280a) and (ID<10) do
            Inc(ID);
            mDelay(100);
          endwhile;
          if ID<10 then
            BME280ACalibOK:=True;
            ReadBMPConfig(BMx280a);                                   // Config lesen
            I2C_Out(BMx280a,BME280_REG_CONTROLHUMID, %00000001);      //
            I2C_Out(BMx280a,BMP280_REG_CONFIG      , %01000000);
            I2C_Out(BMx280a,BMP280_REG_CONTROLMEAS , %00111111);
          endif;
        endif;
      endif;
    endif;
  endif;
  Return(BMx280AOK or BMx280BOK);
end;

Procedure ReadBMx280;
var OutAdr:Byte;
Begin
  if BMx280AOK or BMx280BOK then
    OutAdr:=BMx280a;
    if BMx280BOK then
      OutAdr:=BMx280b;
    endif;
    //if BMP280isReady(OutAdr) then
      ReadBMP280Temperature(OutAdr);
      ReadBMP280Pressure(OutAdr);
      Read280Humidity(OutAdr);
    //endif;
  endif;
end;
miparo
Administrator
Avatar
Gender:
Location: Germany
Age: 58
Posts: 959
Registered: 09 / 2007
Subject:

Re: BME280

 · 
Posted: 21.04.2017 - 16:14  ·  #2
Hi rage,
wo hast du den die Umrechnung der Luftfeuchte her ?
In den Adafruit Treiberns wird das ja anders gerechnet .

Gruß
miparo
rage
Benutzer
Avatar
Gender: n/a
Age: 65
Homepage: processanalytik.de
Posts: 237
Registered: 02 / 2007
Subject:

Re: BME280

 · 
Posted: 23.04.2017 - 13:39  ·  #3
Hi miparo
das ist mir durchaus bewusst und ist auch definitiv nicht getestet. Mein Problem entsteht ja auch vorher. Wenn ich mit abgeschalteten H-Parameter den Chip lese
Code

  adc_H := LongInt(ReadBMPRegister(I2CAdr,BME280_REG_HUMIDDATA));
  if adc_h=$8000 then
    SensorLuftFeuchte:=-200.0;
  else 

bekomme ich ein $8000 zurück, was ja auch korekt ist. Schalte ich den H-Parameter zu, egal mit welchen Oversampling, bekomme ich immer nur ein $0000 zurück und damit kann man halt auch nichts testen.

cu rage
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: BME280

 · 
Posted: 26.04.2017 - 22:58  ·  #4
du liest anders aus als es im Datenblatt beschrieben steht. Vieleicht deswegen?
In deinem code

Code

  I2C_Inp(I2CAdr, Res1);   //Register lesen 
  I2C_Inp(I2CAdr, Res2);   //Register lesen 


werden die reads ja aufgetrennt.

Auszug Datenblatt
Quote

5.2.2 I2C read
To be able to read registers, first the register address must be sent in write mode (slave address
111011X0). Then either a stop or a repeated start condition must be generated. After this the
slave is addressed in read mode (RW = ‘1’) at address 111011X1, after which the slave sends
out data from auto-incremented register addresses until a NOACKM and stop condition occurs.
This is depicted in Figure 8, where two bytes are read from register 0xF6 and 0xF7.
rage
Benutzer
Avatar
Gender: n/a
Age: 65
Homepage: processanalytik.de
Posts: 237
Registered: 02 / 2007
Subject:

Re: BME280

 · 
Posted: 27.04.2017 - 17:00  ·  #5
Hallo Thomas,
Danke Dir für den Tip. Man klammert sich ja an alles, also habe ich das gerade ausprobiert, leider ist das nicht die Lösung, es bleibt bei $0000. Wobei das auch merkwürdig gewesen wäre, weil alle anderen Registerzugriffe sind korrekt. Ich werde mir mal ein paar Chips nachordern, vieleicht ist der mir vorliegende einfach nur defekt.

cu rage
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2134
Registered: 03 / 2003
Subject:

Re: BME280

 · 
Posted: 27.04.2017 - 18:46  ·  #6
Hallo rage,

hast du mal versucht das gleich als Word zu lesen?

Gruss
Harry
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: BME280

 · 
Posted: 27.04.2017 - 18:58  ·  #7
der BMP280 hat keinen Feuchtesensor, nur der BME280 hat diesen.
Welchen hast du?
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: BME280

 · 
Posted: 27.04.2017 - 20:45  ·  #8
Das ist ein bug im code bei read...H5:
Res:=(Word(Res2) shl 4) or Word(Res1);
Return(Res);
end;
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 14 · Cache Hits: 14   139   153 · Page-Gen-Time: 0.040046s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI