BME680

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Hallo liebes Forum,

      ich bin mal wieder zu blöd...

      Seit Montag versuche ich nun, dem BME680 von Bosch (Temp, Hyg, Druck und Gas) per 3-Wire-SPI Daten zu entlocken...soweit geht das auch.

      Aber wenn ich die Rohdaten, also den Sensorwert (hier zunächst nur die Temperatur) mit den im Sensor gespeicherten Kalibrierwerten, zu einem Temperaturwert zu verrechen versuche, kommt nur Käse dabei heraus.

      Es kommen sich änderende Werte für den Temp-ADC rüber, die Kalibrierwerte sind auch da und immer gleich (muss ja auch), plausibel sind die auch, hoffe ich.
      Aber die Formel, nach der die Werte verrechnet werden sollen, bekomme ich nicht zum Laufen (Datenblatt Seite 17, Link unten).

      Am Ende habe ich immer 64°C....was blöd ist, weil das überhaupt nicht stimmt und eigentlich zwei Nachkommawerte dabei sein sollten (auch, wenn das ja eigentlich sinnlos ist von wegen der Sensorgenauigkeit, ist aber so).
      Eigentlich müsste sowas wie z.B. 2356 herauskommen, was dann für 23,56°C stehen würde. Außerdem ist die "64" festgenagelt.

      Das ist natürlich ein Problem mit den Variablen bzw. deren Zahlenformaten und der ganzen Shifterei mit "signed" und "unsigned" usw., das dabei nötig ist.
      Aber es kann doch nicht wahr sein, dass ich das nicht hinbekomme....uarg....
      Ich gehe genau nach Datenblatt vor, meinte ich eigentlich...

      Hat hier einer schon mal den BME680 verarbeitet?

      Die LCD-Texte unten im Code sind für mich nur zur Kontrolle, die eigentliche "Formel" geht von 196...218.

      Datenblatt ist hier: bosch-sensortec.com/media/bosc…eets/bst-bme680-ds001.pdf

      Quellcode

      1. Sub Hygro_1_ini_spi_aussenluft
      2. Dim Status As Byte
      3. Dim Par_t1 As Word
      4. Dim Par_t2 As Word
      5. Dim Par_t3 As Byte
      6. Dim Var_1 As Long
      7. Dim Var_2 As Long
      8. Dim Var_3 As Long
      9. Local X As Long
      10. Dim Temp_adc As Dword
      11. Dim T_comp As Long
      12. Dim T_fine As Long
      13. 'Spi Commands senden
      14. '--------------------------------
      15. 'Memory Map Page...
      16. ' Bit 7: write = "0", read = "1"
      17. Adresse = &B01110011 'Memory Map Page
      18. Clk_hyg1 = 1
      19. Cs_hyg1 = 0
      20. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      21. Waitus 10
      22. Adresse = &B00000000 '0 ins Register, damit Memory Map page "0" aktiviert wird...
      23. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      24. Waitus 10
      25. Cs_hyg1 = 1
      26. '3-wire-Mode init...
      27. Adresse = &B01110101 ' 3-wire mode
      28. Clk_hyg1 = 1
      29. Cs_hyg1 = 0
      30. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      31. Waitus 10
      32. Adresse = 1 '1 ins Register, damit der 3wire aktiviert wird...
      33. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      34. Waitus 10
      35. Cs_hyg1 = 1
      36. 'who_am_I einlesen...
      37. Adresse = &B11010000 'who am I
      38. Clk_hyg1 = 1
      39. Cs_hyg1 = 0
      40. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      41. Waitus 10
      42. Shiftin Sinp_hyg1 , Clk_hyg1 , Who_am_i , 1 , 8 , 10
      43. Cs_hyg1 = 1
      44. 'Memory Map Page auf "1"
      45. Adresse = &B01110011 ' Memory Map page in Bit4
      46. Clk_hyg1 = 1
      47. Cs_hyg1 = 0
      48. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      49. Waitus 10
      50. Adresse = &B00010000 '1 in Bit4 ins Register, damit Memory Map page "1" aktiviert wird...
      51. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      52. Waitus 10
      53. Cs_hyg1 = 1
      54. 'Messung starten (Forced Mode auf H74)
      55. Adresse = &B01110100 ' Force Sample
      56. Clk_hyg1 = 1
      57. Cs_hyg1 = 0
      58. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      59. Waitus 10
      60. Adresse = &B10010001 'Oversampling "100" - Hum=8x, "100" - Temperatur=8x und "01" ins Register, für "Forced Mode" oder "sample probe"
      61. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      62. Waitus 10
      63. Cs_hyg1 = 1
      64. 'Waitms 5
      65. 'Messung fertig? Statusregister lesen...
      66. Status_lesen:
      67. Adresse = &B10011101 ' Statusregister: Messung fertig?
      68. Clk_hyg1 = 1
      69. Cs_hyg1 = 0
      70. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      71. Waitus 10
      72. Shiftin Soutp_hyg1 , Clk_hyg1 , Status , 1 , 8 , 10
      73. Cs_hyg1 = 1
      74. If Status.5 = 0 Then
      75. Waitms 1
      76. Goto Status_lesen
      77. End If
      78. '*****************************************************************************
      79. '******************* ****************
      80. '******************* Beginn der eigentlichen Datenauslesung ****************
      81. '******************* ****************
      82. '*****************************************************************************
      83. '*****************************************************************************
      84. '******************* Temperatur einlesen...MSB first! ****************
      85. '*****************************************************************************
      86. Adresse = &B10100010
      87. Clk_hyg1 = 1
      88. Cs_hyg1 = 0
      89. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      90. Waitus 10
      91. Shiftin Sinp_hyg1 , Clk_hyg1 , Msb , 1 , 8 , 10
      92. Shiftin Sinp_hyg1 , Clk_hyg1 , Lsb , 1 , 8 , 10
      93. Shiftin Sinp_hyg1 , Clk_hyg1 , Xlsb , 1 , 8 , 10
      94. Cs_hyg1 = 1
      95. Temp_adc = Msb
      96. Shift Temp_adc , Left , 8
      97. Temp_adc = Temp_adc + Lsb
      98. Shift Temp_adc , Left , 8
      99. Temp_adc = Temp_adc + Xlsb
      100. Shift Temp_adc , Right , 4
      101. Call Lcd_clear(black)
      102. Call Lcd_text( "Whois: " + Str(who_am_i) + " - " + "H" + Hex(who_am_i) , 3 , 1 , 2)
      103. Call Lcd_text( "MSB: " + Str(msb) , 3 , 13 , 2)
      104. Call Lcd_text( "LSB: " + Str(lsb) , 3 , 25 , 2)
      105. Call Lcd_text( "XLSB:" + Str(xlsb) , 3 , 37 , 2)
      106. Call Lcd_text( "T_ADC: " + Str(temp_adc) , 3 , 49 , 2)
      107. Call Lcd_show()
      108. Wait 10
      109. '**************************************************************
      110. '************* Korrekturwerte einlesen... *******************
      111. '**************************************************************
      112. '********************** Par_t1 ******************************
      113. Adresse = &B11101001
      114. Clk_hyg1 = 1
      115. Cs_hyg1 = 0
      116. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      117. Waitus 10
      118. Shiftin Sinp_hyg1 , Clk_hyg1 , Lsb , 1 , 8 , 10
      119. Shiftin Sinp_hyg1 , Clk_hyg1 , Msb , 1 , 8 , 10
      120. Cs_hyg1 = 1
      121. Par_t1 = Makeint(lsb , Msb)
      122. '********************** Par_t2und Par_t3 ******************************
      123. Adresse = &B10001010
      124. Clk_hyg1 = 1
      125. Cs_hyg1 = 0
      126. Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse , 0 , 8 , 10
      127. Waitus 10
      128. Shiftin Sinp_hyg1 , Clk_hyg1 , Lsb , 1 , 8 , 10
      129. Shiftin Sinp_hyg1 , Clk_hyg1 , Msb , 1 , 8 , 10
      130. Shiftin Sinp_hyg1 , Clk_hyg1 , Par_t3 , 1 , 8 , 10
      131. Cs_hyg1 = 1
      132. Par_t2 = Makeint(lsb , Msb)
      133. '********************* Temp-Berechnung nach Sensor-Formel *******************
      134. Call Lcd_clear(black)
      135. Call Lcd_text( "Temp_adc:" + Str(temp_adc) , 3 , 5 , 2)
      136. Call Lcd_text( "Par_T1: " + Str(par_t1) , 3 , 15 , 2)
      137. Call Lcd_text( "Par_T2: " + Str(par_t2) , 3 , 30 , 2)
      138. Call Lcd_text( "Par_T3: " + Str(par_t3) , 3 , 45 , 2)
      139. Call Lcd_show()
      140. Wait 3
      141. Var_1 = Temp_adc
      142. Shift Var_1 , Right , 3 , Signed
      143. X = Par_t1
      144. Shift X , Left , 1 , Signed
      145. Var_1 = Var_1 - X
      146. Var_2 = Var_1 * Par_t2
      147. Shift Var_2 , Right , 11 , Signed
      148. X = Var_1
      149. Shift X , Right , 1 , Signed
      150. Var_3 = X * X
      151. Shift Var_3 , Right , 12 , Signed
      152. X = Par_t3
      153. Shift X , Left , 4 , Signed
      154. Var_3 = Var_3 * X
      155. Shift Var_3 , Right , 14 , Signed
      156. T_fine = Var_2 + Var_3
      157. T_comp = T_fine * 5
      158. T_comp = T_comp + 128
      159. Shift T_comp , Right , 8 , Signed
      160. Temp_aussenluft_hyg = T_comp
      161. Call Lcd_clear(black)
      162. Call Lcd_text( "Var_1: " + Str(var_1) , 3 , 1 , 2)
      163. Call Lcd_text( "Var_2: " + Str(var_2) , 3 , 14 , 2)
      164. Call Lcd_text( "Var_3: " + Str(var_3) , 3 , 27 , 2)
      165. Call Lcd_text( "T_fine:" + Str(t_fine) , 3 , 40 , 2)
      166. Call Lcd_text( "Temp: " + Str(t_comp) , 3 , 51 , 2)
      167. Call Lcd_show()
      168. Wait 11
      169. End Sub
      Alles anzeigen
    • Peer Gehrmann schrieb:

      Sub Hygro_1_ini_spi_aussenluft
      Dim Status As Byte

      Dim Par_t1 As Word
      Dim Par_t2 As Word
      Dim Par_t3 As Byte

      Dim Var_1 As Long
      Dim Var_2 As Long
      Dim Var_3 As Long

      Local X As Long

      Dim Temp_adc As Dword
      Dim T_comp As Long
      Dim T_fine As Long
      Man sollte allerdings in Subroutinen nur Variablen nur mit Local dimensionieren oder am Besten gleich am Anfang des Programms und nicht in der Sub.
      Es könnte auch sein, dass deine Stackwerte zu klein sind - gerade wenn du Variablen in einer Sub hast, solltes du die nicht zu klein wählen.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Hi djmsc,

      die Deklaration war nur "qick and dirty", weil der Code recht lang ist und ich die Routine ganz am Ende des Codes aufbaue.
      Die Vars sollen bei Fertigstellung nach oben wegsortiert werden.
      Ich werde das aber morgen gleich mal vorziehen.
      Die Stacks sind von mir schon extem groß eingestellt:

      $hwstack = 700
      $swstack = 700
      $framesize = 700

      Die Werte muss ich auch nochmal in Angriff nehmen, die habe ich lange nicht mehr aufgeräumt...ist ein bisschen stochern im Trüben.
      Aber die sollten eigentlich ausreichen, aber das sind auch alles Long-Variablen.

      Versuch macht kluch.
      Danke für die Anregungen...
    • Hallo Murmel, das kommt daher, dass da vorher ein anderer Hygro auf dem Platz war, der nur spi hatte. Wir konnten auf dem Controllerboard den BME680 packen, weil der den gleichen Footprint hatte. Daher das gruselige Bitbanging mit eigener spi zu Fuss... Könnte ich dss auch über soft i2c auslesen?
      Und überhaupt: Hast du eine Routine für den BME680?
      Ich weiss echt nicht, was dss Problem ist... Daten kann ich lesen, der who_is klappt, Werte kommen, ich lasse die Clock recht langsam laufen, timing sollte eigentlich kein Problem sein...
    • Scheint ja selten zu sein. Ein paar Schuß ins blaue. Mal
      Shiftout Soutp_hyg1 , Clk_hyg1 , Adresse ,1 , 8 , 10
      oder Shiftin Sinp_hyg1 , Clk_hyg1 , Lsb , 0 , 8 , 10
      oder Clk_hyg1 = 0
      versucht?
      Cs_hyg1 wird sicher niemals unbeabsichtigt Low ? (portx=xx)

      Peer Gehrmann schrieb:

      Könnte ich dss auch über soft i2c auslesen?
      das Board ist eine Eigenentwicklung
      Klar um auszuschließen das defect ist.
      Das Display funtioniert auch über Spi ? - dann wird das Board kaum schuld sein. Das Display hat ein CS beschaltet? Das auch immer abgeschaltet ist wenn mit dem BME gesprochen wird?
    • Hi Murmel, ja, vielen Dank für den Link. Ich habe alles inhaliert, was zu finden war.
      Genau das mache ich auch, nur über SPI und mit allen Korrekturwerten.
      Was aber im Bosch-Datenblatt so richtig Sch....e ist, ist, dass die nicht richtig auf den "Pagewechsel" beim Auslesen vom DAC und den Korrekturregistern hinweisen.
      Denn die Korrekturwerte liegen bei SPI auf "Page0", die DAC-Werte aber auf Page1. Die Adressen sind in den Tabellen aber ohne jeden Hinweis auf den Pagewechsel einfach untereinander weg geschrieben.
      Leider sind aber die meisten Register in der im Datenblatt vorhandenen, grafischen Tabelle nur auf die Controll- und Datenregister bezogen.
      Die Korrekturwert-Register sind aber gar nicht in einer solchen Übersicht erwähnt. Die Adressen für diese Werte sind immer nur kurz mal hinter den Formeln aufgelistet...aber ohne jeden Hinweis darauf, dass sie auf "Page0", und nicht auf "Page1" liegen.
      Nur mit detektivischem Gespühr findet man einen verschämten Hinweise im Datenblatt, dass (aber nur im SPI-Mode) die Adressen von w-x auf Page0 und die von y-z auf Page1 liegen.
      Danke, danke, danke! an die Pfeifen von Bosch.
      Für den ganzen Käse habe ich dann 5 Tage verschwendet, um das alles herauszufinden.

      Hinzu kommt auch noch, dass das im Tabellen-Header die Reihenfolge von LSB und MSB anders hintereinander stehen, als die Adressen einzulesen sind.
      Nochmal totaler Mist!

      Man muss wirklich jedes Wort im Datenblatt auf die Goldwaage legen.
      Warum auch einfach, logisch und klar, wenn man es dem User so richtig schön schwer machen kann!!!
      Ich bin echt sauer über soviel Blödheit der Datenblattersteller von Bosch, und das sollen Profis sein?

      Und jetzt kann ich die Korrekturwerte einlesen, und die ADC-Werte kommen nicht mehr aus der Kiste raus.
      Ich könnte spucken!
    • So Leute, es ist geschafft...
      Ich poste hier die Routinen, damit Ihr nicht die selben Probleme bekommt, wenn Ihr den Sensor mal benutzen möchtet.
      Denn eigentlich ist der ja richtig nett, sonst hätte ich ihn ja auch nicht ausgesucht.
      Ein echter Allrounder.
      Wenn ich ganz fertig bin und auch die Gasauslesung passt (das ist noch so eine Sache mit sehr wenig, oder keinen Infos zu den Parametern), mache ich da mal ein schönes Code-Snippet...
      Vielen Dank für Eure Unterstützung.
      Wenn man eine Woche lang zu "blöd" ist incl. "freundlcher Unterstützung" vom Hersteller, macht sich dann am Ende doch ein wenig Entspannung breit...

      Viele Grüße
      Peer
    • Hallo Counter,
      danke für den Tip, bin aber nun auch selbst "Profi" mit dem BME, habe den also gut im Griff.

      Nur die VOC-Gasauswertung ist noch auf der Liste. Hier gibt es kaum Unterlagen zu den Einstellungen der Vorheizzeiten, Messtemperaturen usw.
      Da hält das Datenblatt sich mal wieder recht...bedeckt, genau genommen schweigt es dazu beständig. Eine Beispieltabelle würde mir dabei sehr entgegen kommen, habe dazu nur was von einem Spezi im Netz gefunden, aber auch hier ohne jede Erklärung. Bosch geht wohl davon aus, dass wir alle solche Dinge wie die Auswertung katalytischer Gasanalyse beherrschen. Klar, ist ja fünfte Klasse Physik, Lachnummer...
      Am Anfang habe ich mich sogar gefragt, warum ich überhaupt diese Daten auswählen muss, und das auch noch mit mehreren Konstellationen, deren Ergebinsse dann in einer Tabelle gespechert werden, um am Ende die VOC-Belastung vorliegen zu haben.
      Aber ich glaube nun zu wissen, worum es dabei geht: Bei verschiedenen Vorheiztemperatur-Targets werden unterschiedliche Gase gemessen, die eigentlich nicht in die Atemluft gehören.
      Daraus ergibt sich am Ende eine Gesamt-VOC-Belastung in der Umgebungsluft. Wie genau man diese Parameter setzt, erschließt sich mir aber noch nicht so ganz. Oder ich liege ganz falsch...
      Da muss ich wohl noch mal zur Uni...

      Weiß das Forum dazu was zu sagen? Bitte gerne...
    • Hi djmsc, ja, das sind die Ergebniswerte aus dem Datenblatt. Aber wie und warum man verschiedene Temp-Target einrichten muss, erschließt sich mir noch nicht. Könnte mir vorstellen, dass verschiedene Gase bei verschiedenen Temperturen mit der Elektrode katalyse betreiben. Am ende hat man so eine Mischung aus mehreren Messungen, damit auch möglichst viele störende Gase gemessen werden...

      Ein andere Frage (OK, den BME680-Profi muss ich erstmal zurückstellen :-/ ) .
      Ich habe hier im Datenblatt den C-Code für die Auslesung des Drucks und komme mit diesen casting nicht weiter. Am Ende messe ich immer sowas um 1350 hPa, was nicht sein kann.

      Der Code aus dem Datenblatt:

      ------------------------------------------------------------------------------
      int32_t var1;
      int32_t var2;
      int32_t var3;
      int32_t pressure_comp;


      var1 = (((int32_t)dev->calib.t_fine) >> 1) - 64000;
      var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) *
      (int32_t)dev->calib.par_p6) >> 2;
      var2 = var2 + ((var1 * (int32_t)dev->calib.par_p5) << 1);
      var2 = (var2 >> 2) + ((int32_t)dev->calib.par_p4 << 16);
      var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
      ((int32_t)dev->calib.par_p3 << 5)) >> 3) +
      (((int32_t)dev->calib.par_p2 * var1) >> 1);
      var1 = var1 >> 18;
      var1 = ((32768 + var1) * (int32_t)dev->calib.par_p1) >> 15;
      pressure_comp = 1048576 - pres_adc;
      pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125));
      if (pressure_comp >= BME680_MAX_OVERFLOW_VAL)
      pressure_comp = ((pressure_comp / var1) << 1);
      else
      pressure_comp = ((pressure_comp << 1) / var1);
      var1 = ((int32_t)dev->calib.par_p9 * (int32_t)(((pressure_comp >> 3) *
      (pressure_comp >> 3)) >> 13)) >> 12;
      var2 = ((int32_t)(pressure_comp >> 2) *
      (int32_t)dev->calib.par_p8) >> 13;
      var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) *
      (int32_t)(pressure_comp >> 8) *
      (int32_t)dev->calib.par_p10) >> 17;


      pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 +
      ((int32_t)dev->calib.par_p7 << 7)) >> 4);


      return (uint32_t)pressure_comp;
      -------------------------------------------------------------------------------------------

      Vor allem ab Zeile 16 ff. geht es mit einem "uint32_t" casting los:

      pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125));

      Was genau muss man dann machen?
      Ich bin absoluter Blödmann, was C angeht.

      Für mich sind das teils intrinsische (also überflüssige?) Bezeichner, zumindest nicht gleich logisch zu verstehen.
      Wenn also vor einer Konstante, wie hier z.B. "(uint32_t) 3125" steht.
      Ja toll...und nun? die blöde Konstante gibt ihr Format doch vor, sonst ist es ja keine Konstante.
      Außerdem ist die Zahl nicht uint32, sondern ein Word würde es auch tun, gibt die Zahl ja vor.
      Was bitte soll das? Was muss ich damit anfangen?
      Ich hasse C...wahrscheinlich hat dieses "casting" gar nichts mit der Zahl unmittelbar zu tun, oder?
      Würde schön zu C passen, ist halt sch....
      Ich verstehe kein Wort.
      Logisch ist dieser ganze C-Kram für mich nicht, ist ja auch der Grund, warum ich C seit 40 Jahren meide, wie die Pest.
      Kann mir da einer weiterhelfen?
      Ich vermute hier meinen Fehler in den Abgleichberechnungen...

      Solange man als Arduino-Nutzer und Lib-Installierer (Programmierer kann man bei den zu 99% wohl eher nicht sagen) wird das dann ja funktionieren.
      Wenn man das aber selbst durchdringen und verstehen muss, wird die Luft dünn.
      Vor allem, wenn diese bescheuerte C-Nomenklatur in seiner ekligsten Ausprägung durchsuppt...