'****************************************** ' BME280 Beispiel Code ' (c) 2015 by Michael Lehmann ' Siehe http://www.mikrocontroller.net/topic/384287?goto=new#new ' '******************************************************************* '* Eigene Version für LCD und Runnerplatine /183600@gmail.com * '* V2.1 ohne Änderungen * '* V2.2 Anpassung an LCD, Atmega32A, * '* (Hum wir immer mit 0.0% angezeigt) * '* V2.3 Serielle Ausgaben entfernt * '* V2.4 Preasure_64bit entfernt * '* V2.5 Höhenkorrektur für Home eingefügt * '* V2.6 Automatische Druckkorrektur "auf Meereshöhe" * '* V2.7 Automatische Druckkorrektur mit Bisektionsverfahren * '******************************************************************* $regfile = "m32Adef.dat" $crystal = 16000000 $hwstack = 50 $swstack = 50 $framesize = 100 'I2C config Config Sda = Porta.2 Config Scl = Porta.1 '---------------- LCD - Displayausgabe konfigurieren ------------------------- Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.5 , Rs = Portb.4 Config Lcd = 24x2 : Config Lcdbus = 4 Cls : Lcd "BME280 V2.6" Waitms 100 '****************************************** ' Einstellungen für den BME280 Sensor Const Bme280_adress = &HEC 'Sensoradresse 'Oversampling Const Osrs_t = &B101 Const Osrs_p = &B101 Const Osrs_h = &B101 'Mode Register Const Mode_reg = &B11 'Normal Mode 't_sb Const T_sb = &B000 't_sb = 0.5ms 'IIR Filter Const Filter = &B100 'Filter = 16 'Allgemeine Variablen, für die Grundfunktionen des Sensors nicht notwendig Dim Txt As String * 16 Dim Alt As Long Dim Wert_array(24) As Byte 'Datenarray für die i2c komunikation 'Kalibrierwerte vom Sensor Dim Dig_t1 As Word Dim Dig_t2 As Integer Dim Dig_t3 As Integer Dim Dig_p1 As Word Dim Dig_p2 As Integer Dim Dig_p3 As Integer Dim Dig_p4 As Integer Dim Dig_p5 As Integer Dim Dig_p6 As Integer Dim Dig_p7 As Integer Dim Dig_p8 As Integer Dim Dig_p9 As Integer Dim Dig_h1 As Byte Dim Dig_h2 As Integer Dim Dig_h3 As Byte Dim Dig_h4 As Integer Dim Dig_h5 As Integer Dim Dig_h6 As Byte 'unkompensierte Sensor Werte Dim Ut As Long Dim Up As Long Dim Uh As Long 'Funktionsübergreifende Hilfsvariablen Dim T_fine As Long Dim P_old As Dword 'kompensierte Sensor Werte Dim T As Long Dim P_32 As Dword Dim H As Dword 'Automatische Druckkorrektur auf Meereshöhe Dim Dp As Dword , Delta_p As Dword , Alt_0 As Long , Delta_alt As Long 'SUBs und FUNCTONs declarieren Declare Sub I2c_write(byval Device_adres As Byte , Byval Reg_adres As Byte , Byval Wert As Byte) Declare Sub I2c_read(byval Device_adres As Byte , Byval Reg_adres As Byte , Byval Wert_count As Byte ) Declare Sub Setup_bme280() Declare Sub Read_bme280_value() Declare Function Temp() As Long Declare Function Pressure_32() As Dword Declare Function Humidity() As Dword 'sonstige Funktionen Declare Function Absolute_altitude(byval Pressure As Dword) As Long 'Initialisierung des BME280 Sensor Call Setup_bme280() 'Kalibrierwerte vom Sensor lesen, Filterwerte schreiben '*** Hauptprogramm ' Berechnung einer Höhenkorrektur für die Druckanzeige, iterativ ' Angezeigt wird der auf Meeresniveau erhöhte Druck Dp = 101325 'Normaldruck auf Meereshöhe in Pascal Delta_p = 16384 / 4 '=2^14 ergibt 14 Schritte Alt_0 = 42000 'Höhe der Messstation in cm (Einheit wegen Sensorauflösung) 'Reduzierung des Druckes um je 100Pa(=mBar), bis Alt_0 überschritten wird Do Alt = Absolute_altitude(dp) If Alt > Alt_0 Then Dp = Dp + Delta_p Else Dp = Dp - Delta_p End If Delta_p = Delta_p / 2 Delta_alt = Alt - Alt_0 Delta_alt = Abs(delta_alt) Locate 2 , 1 Lcd " DP=" ; Dp ; " " ; Alt ; " " ; Alt_0 ; " " ; Delta_alt ; " " Waitms 500 Loop Until Delta_p = 0 Or Delta_alt <= 10 'Abweichung <=10cm Dp = 101325 - Dp Cls Lcd "Korrekturwert:" ; Dp ; Wait 1 Do '** BME280 auslesen Call Read_bme280_value() 'List die unkompensierten Wert vom Sensor, 'diese werden in Ut, Up, Uh abgelegt '** Temperatur T = Temp() 'Gibt die Temperatur in °C zurück, die Auflösung beträgt 0.01°C 'Der Wert 2415 entspricht 24.15°C '** Luftdruck mit 32bit Berechnung P_32 = Pressure_32() 'Gibt den Luftdruck in hPa zurück, die Auflösung beträgt 0.01hPa 'Der Wert 96386 entspricht 963.86hPa P_32 = P_32 + Dp '** Luftfeuchte H = Humidity() 'Gibt die Luftfeuchtigkeit in % zurück, die Auflösung beträgt 0.001hPa 'Der Wert 46333 entspricht 46.333% H = H / 100 '** Höhe über Meer Alt = Absolute_altitude(p_32) 'Gibt die Höhe über Meer in meter zurück, die Auflösung beträgt bei 64bit Luftdruckberechnung 0.01m 'Der Wert 52078 entspricht 520.78m 'Für die Berechnung mit 32bit Luftdruck müssen in der Function ABSOLUTE_ALTITUDE die beiden Faktoren umkomentiert werden. Alt = Alt_0 '** Messwerte ausgeben ' Lcd "Ut:" ; Ut ; " Up:" ; Up ; " Uh:" ; Uh ' Wait 1 Wait 1 : Cls Txt = Str(t) Txt = Format(txt , "00.00") Locate 1 , 1 Lcd "T:" ; Txt Txt = Str(p_32) Txt = Format(txt , "00.00") Locate 1 , 9 Lcd "P32:" ; Txt Txt = Str(h) Txt = Format(txt , "00.0") Locate 2 , 1 Lcd "Hum:" ; Txt ; "%" Txt = Str(alt) Txt = Format(txt , "00.00") Locate 2 , 9 Lcd "Alt:" ; Txt ; "m" Loop End Sub I2c_write(device_adres As Byte , Reg_adres As Byte , Wert As Byte) I2cstart I2cwbyte Device_adres I2cwbyte Reg_adres I2cwbyte Wert I2cstop Waitms 10 End Sub Sub I2c_read(device_adres As Byte , Reg_adres As Byte , Wert_count As Byte ) Local X As Byte Local Y As Byte Y = Wert_count - 1 I2cstart 'Start I2C I2cwbyte Device_adres 'Sende Slave Adresse I2cwbyte Reg_adres 'Register Adresse I2cstart Incr Device_adres I2cwbyte Device_adres 'sende Slave Adresse +1 für Lesen If Wert_count > 1 Then For X = 1 To Y I2crbyte Wert_array(x) , Ack 'lese Wert Next End If I2crbyte Wert_array(wert_count) , Nack 'lese Wert I2cstop Waitms 10 End Sub Sub Read_bme280_value() Call I2c_read(bme280_adress , &HF7 , 8 ) 'unkompensierter Druckwert Up = Wert_array(1) Shift Up , Left , 8 Up = Up + Wert_array(2) Shift Up , Left , 8 Up = Up + Wert_array(3) Shift Up , Right , 4 'unkompensierter Temperaturwert Ut = Wert_array(4) Shift Ut , Left , 8 Ut = Ut + Wert_array(5) Shift Ut , Left , 8 Ut = Ut + Wert_array(6) Shift Ut , Right , 4 'unkompensierter Feuchtewert Uh = Wert_array(7) Shift Uh , Left , 8 Uh = Uh + Wert_array(8) End Sub Function Temp() As Long Local Var1 As Long Local Var2 As Long Local X As Long Var1 = Ut Shift Var1 , Right , 3 , Signed X = Dig_t1 Shift X , Left , 1 , Signed Var1 = Var1 - X Var1 = Var1 * Dig_t2 Shift Var1 , Right , 11 , Signed Var2 = Ut Shift Var2 , Right , 4 , Signed Var2 = Var2 - Dig_t1 Var2 = Var2 * Var2 Shift Var2 , Right , 12 , Signed Var2 = Var2 * Dig_t3 Shift Var2 , Right , 14 , Signed T_fine = Var1 + Var2 Temp = T_fine * 5 Temp = Temp + 128 Shift Temp , Right , 8 , Signed End Function Function Pressure_32() As Dword Local Var1 As Long Local Var2 As Long Local X As Long Local Y As Long Local Z As Dword Var1 = T_fine Shift Var1 , Right , 1 , Signed Var1 = Var1 - 64000 X = Var1 Shift X , Right , 2 Var2 = X * X Shift Var2 , Right , 11 , Signed Var2 = Var2 * Dig_p6 X = Var1 * Dig_p5 Shift X , Left , 1 , Signed Var2 = Var2 + X X = Var2 Shift X , Right , 2 , Signed Y = Dig_p4 Shift Y , Left , 16 , Signed Var2 = X + Y X = Var1 Shift X , Right , 2 , Signed X = X * X Shift X , Right , 13 , Signed X = X * Dig_p3 Shift X , Right , 3 , Signed Y = Dig_p2 * Var1 Shift Y , Right , 1 , Signed Var1 = X + Y Shift Var1 , Right , 18 , Signed Var1 = 32756 + Var1 Var1 = Var1 * Dig_p1 Shift Var1 , Right , 15 , Signed If Var1 = 0 Then Pressure_32 = P_old Exit Function End If X = 1048576 - Up Y = Var2 Shift Y , Right , 12 , Signed X = X - Y Pressure_32 = X * 3125 If Pressure_32 < &H80000000 Then Shift Pressure_32 , Left , 1 , Signed Pressure_32 = Pressure_32 / Var1 Else Pressure_32 = Pressure_32 / Var1 Pressure_32 = Pressure_32 * 2 End If Z = Pressure_32 Shift Z , Right , 3 , Signed Z = Z * Z Shift Z , Right , 13 , Signed Z = Z * Dig_p9 Shift Z , Right , 12 , Signed Var1 = Z Z = Pressure_32 Shift Z , Right , 2 , Signed Z = Z * Dig_p8 Shift Z , Right , 13 , Signed Var2 = Z Z = Var1 + Var2 Z = Z + Dig_p7 Shift Z , Right , 4 , Signed Pressure_32 = Pressure_32 + Z P_old = Pressure_32 End Function Function Humidity() As Dword Local Var1 As Long Local X As Long Local Y As Long Local Z As Long Var1 = T_fine - 76800 X = Uh Shift X , Left , 14 , Signed Y = Dig_h4 Shift Y , Left , 20 , Signed X = X - Y Y = Dig_h5 * Var1 X = X - Y X = X + 16384 Shift X , Right , 15 , Signed Y = Var1 * Dig_h6 Shift Y , Right , 10 , Signed Z = Var1 * Dig_h3 Shift Z , Right , 11 , Signed Z = Z + 32768 Y = Y * Z Shift Y , Right , 10 , Signed Y = Y + 2097152 Y = Y * Dig_h2 Y = Y + 8192 Shift Y , Right , 14 , Signed Var1 = X * Y X = Var1 Shift X , Right , 15 , Signed X = X * X Shift X , Right , 7 , Signed X = X * Dig_h1 Shift X , Right , 4 , Signed Var1 = Var1 - X If Var1 < 0 Then Var1 = 0 End If If Var1 > 419430400 Then Var1 = 419430400 End If Shift Var1 , Right , 12 , Signed Humidity = Var1 / 1.024 End Function Sub Setup_bme280() Local X As Byte 'Warten bis der Sensor die Startup Prozedur abgeschlossen hat Waitms 5 'BME280 schreibe Filter Wert und t_sb Einstellung X = T_sb Shift X , Left , 3 X = X + Filter Shift X , Left , 2 Call I2c_write(bme280_adress , &HF5 , X) 'BME280 schreibe OSRS_h Wert (ctrl_hum register) Call I2c_write(bme280_adress , &HF2 , Osrs_h) 'BME280 schreibe OSRS_t, OSRS_p, Mode Wert (ctrl_meas register) X = Osrs_t Shift X , Left , 3 X = X + Osrs_p Shift X , Left , 2 X = X + Mode_reg Call I2c_write(bme280_adress , &HF4 , X) 'BME280 lese Kalibrierwerte Call I2c_read(bme280_adress , &H88 , 24 ) Dig_t1 = Wert_array(2) Shift Dig_t1 , Left , 8 Dig_t1 = Dig_t1 + Wert_array(1) Dig_t2 = Wert_array(4) Shift Dig_t2 , Left , 8 Dig_t2 = Dig_t2 + Wert_array(3) Dig_t3 = Wert_array(6) Shift Dig_t3 , Left , 8 Dig_t3 = Dig_t3 + Wert_array(5) Dig_p1 = Wert_array(8) Shift Dig_p1 , Left , 8 Dig_p1 = Dig_p1 + Wert_array(7) Dig_p2 = Wert_array(10) Shift Dig_p2 , Left , 8 Dig_p2 = Dig_p2 + Wert_array(9) Dig_p3 = Wert_array(12) Shift Dig_p3 , Left , 8 Dig_p3 = Dig_p3 + Wert_array(11) Dig_p4 = Wert_array(14) Shift Dig_p4 , Left , 8 Dig_p4 = Dig_p4 + Wert_array(13) Dig_p5 = Wert_array(16) Shift Dig_p5 , Left , 8 Dig_p5 = Dig_p5 + Wert_array(15) Dig_p6 = Wert_array(18) Shift Dig_p6 , Left , 8 Dig_p6 = Dig_p6 + Wert_array(17) Dig_p7 = Wert_array(20) Shift Dig_p7 , Left , 8 Dig_p7 = Dig_p7 + Wert_array(19) Dig_p8 = Wert_array(22) Shift Dig_p8 , Left , 8 Dig_p8 = Dig_p8 + Wert_array(21) Dig_p9 = Wert_array(24) Shift Dig_p9 , Left , 8 Dig_p9 = Dig_p9 + Wert_array(23) Call I2c_read(bme280_adress , &HA1 , 1 ) Dig_h1 = Wert_array(1) Call I2c_read(bme280_adress , &HE1 , 8 ) Dig_h2 = Wert_array(2) Shift Dig_h2 , Left , 8 Dig_h2 = Dig_h2 + Wert_array(1) Dig_h3 = Wert_array(3) Dig_h4 = Wert_array(4) Shift Dig_h4 , Left , 4 X = Wert_array(5) X = X And &HF Dig_h4 = Dig_h4 + X Dig_h5 = Wert_array(6) Shift Dig_h5 , Left , 4 X = Wert_array(5) Shift X , Right , 4 Dig_h5 = Dig_h5 + X Dig_h6 = Wert_array(7) End Sub Function Absolute_altitude(byval Pressure As Dword) Local X As Single 'höhe = 288.15/0.0065*(1-(pressure/1013.25)^(1/5.255)); X = Pressure X = X / 101325 '32bit X = X ^ 0.1902949 X = 1 - X X = 44330.76923 * X X = X * 100 '32bit Absolute_altitude = X End Function