Keine Messdaten vom BME 280 Umweltsenor

werner mehl
Benutzer
Avatar
Gender:
Age: 68
Posts: 49
Registered: 02 / 2012
Subject:

Keine Messdaten vom BME 280 Umweltsenor

 · 
Posted: 26.02.2018 - 10:15  ·  #1
Hallo Zusammen,
mich treibt gerade ein BME280 Sensor in den Wahnsinn, ich kann keine Messdaten aud dem Chip auslesen. Das IC ist am Bus, ID bekomme ich richtig, wie auch die Kalibrierdaten. Zumindest gehe ich davon aus, dass die Kalibrierdaten stimmen.
Ich gehe davon aus, dass ich das Problem bin. Vielleicht hat schon mal jemand von euch erfolgreich mit dem Chip gearbeitet und kann mich auf den richtigen Weg bringen.

Hier meine Ausleseversuche und die ausgegebenen Ergebnisse

Besten Dank schon mal

Code

program BME280_Control;

{$NOSHADOW}
{$WG}                      {global Warnings on}

Device = xmega256A3U, VCC=3.3;
{ $BOOTRST $20000}         {Reset Jump to $20000}

Define_Fuses
//  Override_Fuses;
  NoteBook   = J;
  COMport    = USB;
  LockBits0  = [];
  FuseBits0  = [];
  FuseBits1  = [];
  FuseBits2  = [];
  ProgMode   = PDI;

Import SysTick, SerPortC1, SerPortD1, I2Cport;

From System Import LongInt, Float;


Define
// The XMegas don't provide any Oscillator fuses.
// So the application must setup the desired values
// possible OSC types: extXTAL, extClock, ext32kHz, int32Khz, int2MHz, int32MHz
  OSCtype        = extXTAL=16000000,
                   PLLmul  = 4,
                   prescB  = 1,
                   prescB  = 1, overdrive;

  SysTick        = 10;             {msec}

  SerPortC1      = 2400, Stop1; {9600 Baud, 1Stopbit}
  TxBufferC1     = 32, iData; {8 Byte Buffer und Int}
  RxBufferC1     = 32, iData; {8 Byte Buffer und Int}

  SerPortD1      = 57600, Stop1; {9600 Baud, 1Stopbit}
  TxBufferD1     = 64, iData; {8 Byte Buffer und Int}
  RxBufferD1     = 64, iData; {8 Byte Buffer und Int}

  StackSize      = $00FA, iData;
  FrameSize      = $00C8, iData;

  I2Cport        = PortC;
  I2Cdat         = 0;
  I2Cclk         = 1;

//Uses
Implementation

{$IDATA}




{--------------------------------------------------------------}
{ Type Declarations }

type

{--------------------------------------------------------------}
{ Const Declarations }
Const

  BME280_REG_DIG_T1      : Byte = $88;
  BME280_REG_DIG_T2      : Byte = $8A;
  BME280_REG_DIG_T3      : Byte = $8C;

  BME280_DIG_P1      : Byte = $8E;
  BME280_DIG_P2      : Byte = $90;
  BME280_DIG_P3      : Byte = $92;
  BME280_DIG_P4      : Byte = $94;
  BME280_DIG_P5      : Byte = $96;
  BME280_DIG_P6      : Byte = $98;
  BME280_DIG_P7      : Byte = $9A;
  BME280_DIG_P8      : Byte = $9C;
  BME280_DIG_P9      : Byte = $9E;

  BME280_DIG_H1      : Byte = $A1;
  BME280_DIG_H2      : Byte = $E1;
  BME280_DIG_H3      : Byte = $E3;
  BME280_DIG_H4      : Byte = $E4;
  BME280_DIG_H5      : Byte = $E5;
  BME280_DIG_H6      : Byte = $E7;

  BME280_CHIPID      : Byte = $D0;
  BME280_VERSION     : Byte = $D1;
  BME280_SOFTRESET   : Byte = $E0;

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

  BME280_CONTROLHUMID: Byte = $F2;
  BME280_STATUS      : Byte = $F3;
  BME280_CONTROLMEAS : Byte = $F4;
  BME280_CONFIG      : Byte = $F5;
  BME280_PRESSUREDATA: Byte = $F7;
  BME280_TEMPDATA    : Byte = $FA;
  BME280_HUMIDDATA   : Byte = $FD;

  Reg_hum_set_0xF2       : Byte = %00000001;   // Humidity Oversampling = 1
  Reg_meas_set_0xF4      : Byte = %00100011;   // Pressure and Temperature Oversampling = 4, Mode = Normal
  Reg_sleep_set_0xF4     : Byte = %00100100;   // Pressure and Temperature Oversampling = 4, Mode = Sleep mode
  Reg_config_0xF5        : Byte = %10101000;   //
  Reg_Calib_25           : Byte = $88;
  Reg_Calib_41           : Byte = $E1;
  Reg_Start_Meas_0xF7    : Byte = $F7;
  
  Timer1_Interval : Word = 50;
  
  Not_Found  : Word = 10001;    // I2C Fehler
  Read_Err   : Word = 10002;    // I2C Fehler
  Wrong_ID   : Word = 10003;    // I2C Fehler

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;//BME280_calib_data;

  
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
Var

//  t_fine           : LongInt;
  BMx280Flag         : Byte;
  BMx280AOK     [@BMx280Flag,0]: Bit;
  BME280AOK     [@BMx280Flag,1]: Bit;
  BME280ACalibOK[@BMx280Flag,2]: Bit;
  BMx280BOK     [@BMx280Flag,4]: Bit;


  B28_SensData : Array[$F7..$FE] of Byte;  // $F7 - $FE   Sensordaten
//  B28_TempData : Array[$FA..$FC] of Byte;  // $F2 - $FE   Sensordaten Temperatur
  Calib_25     : Array[$88..$A1] of Byte;  // $88 - $A1
  Calib_41     : Array[$E1..$F0] of Byte;  // $E1 - $F0


lv_com   : Byte;               // Laufvariable für Kommandosequenz
lc       : Byte;               //
Dummy    : String[20];         // für was auch immer

BME280_Adr : Byte;             // Adresse des BME 280 Moduls
BME280_ID  : Byte;             // ID des Moduls, normal $60
BME280_Stat: Byte;             // Statusbyte $73
I2C_Err    : Word;             // Fehler beim lesen oder ...
Ctrl_Meas  : Byte;             // $F4 Reg Ctrl_Meas

BME280_Busy[@BME280_Stat,3]: Bit;
Timer1 : Systimer;

//------------------------------------->>
{ functions }

//------------------------------------->>
Procedure Init_System;
begin
  EnableInts($87);
   For lc := $F7 to $FE do         // Daten am Anfang auf Null setzen
     B28_SensData[lc] := 0;
   Endfor;

  I2C_Err := 0;
  
  Dummy    := '';
  FlushBuffer(RxBufferC1);    // Empfangspuffer C1 leeren
  FlushBuffer(RxBufferD1);    // Empfangspuffer D1 leeren
  lv_com := 0;
end;
//------------------------------------->>
Function Get_BME280_Adr:Byte;
begin
  BME280_Adr := 0;                // Adr voreinstellen
  I2C_Err    := Not_Found;        // Fehler Voreinstellung Chip nicht gefunden
  If I2CStat($76) Then            // wenn Adr = $76
    BME280_Adr := $76;            // Adr zuweisen
    I2C_Err    := 0;              // I2C Fehler löschen
   else
    If I2CStat($77) Then          // wenn Adr = $77
      BME280_Adr := $77;          // Adr zuweisen
      I2C_Err    := 0;            // I2C Fehler löschen
    EndIf;
  EndIf;
  If BME280_Adr = 0 Then
    I2C_Err   := Not_Found;
    // Fehler in Ü-Datensatz schreiben
  EndIf;
  Return(BME280_Adr);             // Adr zurückliefern
End;

//------------------------------------->>
Function Get_BME280_ID:Byte;
begin
  BME280_ID := 0;                   // ID voreinstellen
  I2COut(BME280_Adr, $D0);          // Adr der Chip ID setzen
  If I2CInp(BME280_Adr, BME280_ID) Then    // ID lesen
   else                             // wenn nicht möglich
    I2C_Err   := Wrong_ID;          // ID = 0, nicht gefunden
    // Fehler in Ü-Datensatz schreiben
  EndIf;
  Return(BME280_ID);
End;

//------------------------------------->>
Procedure Set_BME280_Reg(r : Byte);
begin
  I2COut(BME280_Adr, r);            // Register auf Adr schreiben
End;

//------------------------------------->>
Procedure Get_meas_Reg;
begin
  I2COut(BME280_Adr, Reg_Start_Meas_0xF7);    // Adr der Messdaten setzen
  If I2CInp(BME280_Adr, B28_SensData) Then    // Sensordaten lesen
   else                                       // wenn nicht möglich
    I2C_Err   := Read_Err;                    // Lesefehler
    // Fehler in Ü-Datensatz schreiben
  EndIf;
end;
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>
//------------------------------------->>



{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
// Rel0[@PortA,0] : Bit;


begin
  EnableInts($87);
//  1 = Ausgang !!!
//  DDRB :=  %00000000;
  DDRB :=  %11111111;

  Init_System;
// ScanI2CBus;
  WriteLn(SerOutD1,' Alive ');
  mdelay(20);
  BME280_Adr := Get_BME280_Adr;
  WriteLn(SerOutD1,' Adr:  '+ByteToHex(BME280_Adr));
  WriteLn(SerOutD1,'');
  //mdelay(20);
  BME280_ID := Get_BME280_ID;
  WriteLn(SerOutD1,' ID :  '+ByteToHex(BME280_ID));
  WriteLn(SerOutD1,'');
  //mdelay(20);

  Set_BME280_Reg(Reg_sleep_set_0xF4);  // Sleepmode setzen
  mdelay(10);

  Set_BME280_Reg(Reg_config_0xF5);    // meine Standardeinstellungen setzen
  mdelay(10);
  Set_BME280_Reg(Reg_hum_set_0xF2);   // meine Standardeinstellungen setzen
  mdelay(10);
  Set_BME280_Reg(Reg_meas_set_0xF4);  // meine Standardeinstellungen setzen
  mdelay(10);

  loop
  
    If IsSysTimerZero(Timer1) then       // Zeit zu ende, neue Messung starten

      WriteLn(SerOutD1,' Adr:  '+ByteToHex(Get_BME280_Adr));
      WriteLn(SerOutD1,'');
      mdelay(20);
      WriteLn(SerOutD1,' ID :  '+ByteToHex(Get_BME280_ID));
      WriteLn(SerOutD1,'');
      mdelay(20);

      Set_BME280_Reg(Reg_Calib_25);             // Startadresse setzen
      If I2CInp(BME280_Adr, Calib_25) Then      // Kalibrierdaten auslesen
       else
        WriteLn(SerOutD1,'Fehler 25');
      EndIf;
      WriteLn(SerOutD1,' ---->> Calib 25');     // Kalibrierdaten ausgeben
      For lc := $88 to $A1 do
        WriteLn(SerOutD1,'$'+bytetoHex(lc)+'  '+bytetostr(Calib_25[lc]:4));
      Endfor;

      Set_BME280_Reg(Reg_Calib_41);             // Startadresse setzen
      If I2CInp(BME280_Adr, Calib_41) Then      // Kalibrierdaten auslesen
       else
        WriteLn(SerOutD1,'Fehler 1');
      EndIf;
      WriteLn(SerOutD1,' ---->> Calib 41');     // Kalibrierdaten ausgeben
      For lc := $E1 to $F0 do
        WriteLn(SerOutD1,'$'+bytetoHex(lc)+'  '+bytetostr(Calib_41[lc]:4));
      Endfor;

      Set_BME280_Reg(BME280_CONTROLMEAS);             // Startadresse setzen
      If I2CInp(BME280_Adr, Ctrl_Meas) Then     // Ctrl_Meas Register lesen
       else
        WriteLn(SerOutD1,'Fehler Read Ctrl_Meas');
      EndIf;
      WriteLn(SerOutD1,' ---->> Ctrl_Measure Register');
      WriteLn(SerOutD1,bytetoHex(BME280_CONTROLMEAS)+'  '+bytetoBin(Ctrl_Meas));    // immer %00110111  ???
      WriteLn(SerOutD1,' ---->> Ctrl_Measure Register');
      WriteLn(SerOutD1,'');

      Set_BME280_Reg(Reg_Start_Meas_0xF7);      // Startadresse setzen
      If I2CInp(BME280_Adr, B28_SensData) Then
       else
        WriteLn(SerOutD1,'Fehler 1');
      EndIf;
      mdelay(20);
      WriteLn(SerOutD1,' ---->> Messdaten');
      For lc := $F7 to $FE do
        WriteLn(SerOutD1,'$'+bytetoHex(lc)+'   $'+bytetoHex(B28_SensData[lc]));
      Endfor;
      SetSysTimer(Timer1, 300);          // Timeout bis zur nächsten Abfrage setzen
      WriteLn(SerOutD1,'');
      WriteLn(SerOutD1,'');


    EndIf;

  endloop;
end.




Und hier sind die ausgegebenen Ergebnisse

Code

 Adr:  77<CR><LF>
<CR><LF>
 ID :  60<CR><LF>
<CR><LF>
 ---->> Calib 25<CR><LF>
$88   179<CR><LF>
$89   109<CR><LF>
$8A   102<CR><LF>
$8B   102<CR><LF>
$8C    50<CR><LF>
$8D     0<CR><LF>
$8E    34<CR><LF>
$8F   145<CR><LF>
$90    39<CR><LF>
$91   214<CR><LF>
$92   208<CR><LF>
$93    11<CR><LF>
$94   159<CR><LF>
$95    31<CR><LF>
$96   106<CR><LF>
$97   255<CR><LF>
$98   249<CR><LF>
$99   255<CR><LF>
$9A    12<CR><LF>
$9B    48<CR><LF>
$9C    32<CR><LF>
$9D   209<CR><LF>
$9E   136<CR><LF>
$9F    19<CR><LF>
$A0     0<CR><LF>
$A1    75<CR><LF>
 ---->> Calib 41<CR><LF>
$E1    79<CR><LF>
$E2     1<CR><LF>
$E3     0<CR><LF>
$E4    24<CR><LF>
$E5    38<CR><LF>
$E6     3<CR><LF>
$E7    30<CR><LF>
$E8    99<CR><LF>
$E9    65<CR><LF>
$EA   255<CR><LF>
$EB   255<CR><LF>
$EC   255<CR><LF>
$ED   255<CR><LF>
$EE   255<CR><LF>
$EF   255<CR><LF>
$F0   255<CR><LF>
 ---->> Ctrl_Measure Register<CR><LF>
F4  00000000<CR><LF>
 ---->> Ctrl_Measure Register<CR><LF>
<CR><LF>
 ---->> Messdaten<CR><LF>
$F7   $80<CR><LF>
$F8   $00<CR><LF>
$F9   $00<CR><LF>
$FA   $80<CR><LF>
$FB   $00<CR><LF>
$FC   $00<CR><LF>
$FD   $80<CR><LF>
$FE   $00<CR><LF>
<CR><LF>
<CR><LF>

mc-electronic
Benutzer
Avatar
Gender: n/a
Location: Sauerland NRW
Posts: 372
Registered: 03 / 2008
Subject:

Re: Keine Messdaten vom BME 280 Umweltsenor

 · 
Posted: 26.02.2018 - 15:14  ·  #2
Hallo Werner,

ich arbeite seit kurzem mit dem BME680. Dort lassen sich die Meßwertregister auslesen. Ich habe über Deine Software nur oberflächlich drüber gesehen. Beim BME680 muß jede Messung über das Ctr_meas Register, Bits "Mode" explizit gestartet werden. Die $80er Werte kenne ich, daß sind die Standard-Werte, die der CHip ausgibt, wenn die Messungen nicht gestartet wurden. Die hatte ich auch, weil ich vergessen hatte, das Oversampling zu aktivieren (wenigstens auf 1 setzen!)

[code]
               lPos := $D0;
               lBy := GetBME680ByteRegister (cBME680Adr, lPos);
               WritelnTerm('BME680 Reg[$'+ByteToHex(lPos)+'] = $'+ByteToHex(lBy),lTerminal);

               If SetBME680ByteRegister(cBME680Adr,$72,1) Then                  // Setze das Oversampling für Feuchte
                 For lCnt := 1 To 100 Do
                  If SetBME680ByteRegister(cBME680Adr,$74,%00100101) Then       // Setze das Oversampling für Druck und Temperatur und starte die Messung
                     mDelay(30);
                     lPos := $22;
                     lWo := GetBME680WordRegister (cBME680Adr, lPos);
                     WritelnTerm('BME680 Temp Reg[$'+ByteToHex(lPos)+'] = $'+IntToHex(lWo),lTerminal);
                  EndIf;
                 EndFor;
               EndIf;
[/code]

Sorry für das blöde Layout, bei mir hat der Code-Butten noch nie funktioniert
werner mehl
Benutzer
Avatar
Gender:
Age: 68
Posts: 49
Registered: 02 / 2012
Subject:

Re: Keine Messdaten vom BME 280 Umweltsenor

 · 
Posted: 26.02.2018 - 16:16  ·  #3
Hallo mc-electronic
besten Dank für die Antwort.
Ich habe wie du das Oversampling auf 1, du arbeitest im Forced mode.
Ich habe anfangs auch den Forced mode gesetzt, da ich nur 1/minute lese(n möchte)
Leider hat das nicht funktioniert, sodass ich den Normal Mode gesetzt habe, weil er mir einfacher schien.
Ich persönlich habe den Eindruck, dass ich beim Setup vor der Loop irgendwas übersehe.
Auch merkwürdig finde ich, dass das Statusregister $F3 beim lesen immer 0 ist. Wobei natürlich bei den wenigen samples keine große Gefahr für kollisionen besteht.
werner mehl
Benutzer
Avatar
Gender:
Age: 68
Posts: 49
Registered: 02 / 2012
Subject:

Re: Keine Messdaten vom BME 280 Umweltsenor

 · 
Posted: 28.02.2018 - 09:42  ·  #4
Guten Morgen
Der Sensor funktioniert, das hat er wie von mir vermutet auch immer getan :)
Ich hatte auch vermutet, dass ich selbst das Problem bin. Das hat sich bestätigt.
Copy & Paste ist keine gute Erfindung, das hat sich hier wieder gezeigt.

Den Ausdruck - I2COut(BME280_Adr, RegAdr); // Adr setzen

habe ich benutzt um zum lesen eines Registers die Adresse des Registers zu setzen.
dann wollte ich (später)die Betriebszustände einstellen und habe mir, "weil ich das ja schon habe"
per Copy & Paste den Ausdruck in die Procedur zum Einstellen der Register kopiert.
und habe dabei nicht bemerkt, dass ich nie Daten reingeschrieben habe.

Mit dem Ausdruck - I2COut(BME280_Adr, RegAdr, Data); // Daten schreiben

funktioniert das ganze plötzlich auf fast magische Weise.
Ich wollte euch das nicht vorenthalten. :)

Werner
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: 15 · Cache Hits: 14   80   94 · Page-Gen-Time: 0.0314s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI