'Weather Station 'Barometer : BMP180 $regfile = "m32def.dat" $crystal = 7372800 'Intern Xtal $hwstack = 32 $swstack = 16 $framesize = 24 'Fuses : JTAGEN uitzetten ! $lib "glcd-Nokia3310.lib" 'Nokia 3310 $lib "I2C_TWI.LBX" 'TWI / I2C communicatie Config Graphlcd = 128x64sed , Rst = Portb.4 , Cs1 = Portb.3 , A0 = Portb.2 , Si = Portc.6 , Sclk = Portc.5 'Pinnen naar NOKIA 5110 'Pinning naar Nokia 5110 , Rst = B4, Sce = B3, D/C = B2, Sdi = C6, Sck = C5 'Const Negative_lcd = 1 'Inverting screen 'Const Rotate_lcd = 1 'Rotate screen to 180° 'I2C 'SCL = C0 (SCL) 'SDA = C1 (SDA) Declare Sub Initialize() Declare Sub Read_params_bmp180() 'Calibratiewaarden (rachtstreeks) Declare Sub Read_params() 'Calibratiewaarden (omweg) Declare Sub Read_press_bmp180() 'Read RAW pressure Declare Sub Read_temp_bmp180() 'Read RAW temp Declare Sub Calc_tp() 'Bereken P en T uit RAW-data Declare Sub Time_update() 'Nokia 5110 : Update tijd/datum Declare Sub Write_lcd() 'Aliasses Buzzer Alias Portd.4 'Piezobuzzer Dim Text As String * 16 Dim Hours As Byte , Minutes As Byte , Seconds As Byte , Secs As Byte Dim Lcd_counter As Byte 'BMP180 parameters Dim Param_int_bmp180(8) As Integer 'AC1, AC2, AC3, B1, B2, MB, MC, MD Dim Param_wrd_bmp180(3) As Word 'AC4, AC5, AC6 Dim I2c_byte(22) As Byte 'Calibratiewaarden uit BMP180 Dim Raw_temp As Integer 'Onbewerkte temp Dim Raw_press As Long 'Onbewerkte luchtdruk Dim Act_temp As Single 'Temp via calibratie Dim Act_press As Single 'LuchtDruk via calibratie 'Calibratiewaarden ophalen uit sensor ! Call Initialize() '***************************** Program ***************************************** Setfont Font6x8 'Setfont Font12x16dig Do If Secs > 0 Then 'minimaal 1 seconde voorbij ? Call Time_update() 'Tijd updaten en weergeven op scherm Incr Lcd_counter 'Naar volgende scherm If Lcd_counter > 3 Then Lcd_counter = 1 'Overloop, reset Setfont Font6x8 'Veeg scherm schoon Lcdat 1 , 1 , " " 'Schoonvegen regel Lcdat 2 , 1 , " " 'Schoonvegen regel Lcdat 3 , 1 , " " 'Schoonvegen regel 'Calib-waarden op scherm If Lcd_counter = 1 Then 'AA t/m B2 'Om aan te geven dat het om AA - B2 gaat, eerste regel inverterend Text = Str(i2c_byte(1)) + " " + Str(i2c_byte(2)) + " " + Str(i2c_byte(3)) Lcdat 1 , 1 , Text , 1 'Inverterend Text = Str(i2c_byte(4)) + " " + Str(i2c_byte(5)) + " " + Str(i2c_byte(6)) Lcdat 2 , 1 , Text Text = Str(i2c_byte(7)) + " " + Str(i2c_byte(8)) + " " + Str(i2c_byte(9)) Lcdat 3 , 1 , Text Else If Lcd_counter = 2 Then 'B3 t/m BB 'Om aan te geven dat het om B3 - BB gaat, tweede regel inverterend Text = Str(i2c_byte(10)) + " " + Str(i2c_byte(11)) + " " + Str(i2c_byte(12)) Lcdat 1 , 1 , Text Text = Str(i2c_byte(13)) + " " + Str(i2c_byte(14)) + " " + Str(i2c_byte(15)) Lcdat 2 , 1 , Text , 1 'Inverterend Text = Str(i2c_byte(16)) + " " + Str(i2c_byte(17)) + " " + Str(i2c_byte(18)) Lcdat 3 , 1 , Text Else 'BC t/m BF Text = Str(i2c_byte(19)) + " " + Str(i2c_byte(20)) + " " + Str(i2c_byte(21)) Lcdat 1 , 1 , Text Text = Str(i2c_byte(22)) Lcdat 2 , 1 , Text End If End If Else 'Dode wachttijd : ruimte voor andere processen End If Loop Sub Initialize() Ddrc.5 = 1 'C5 : Sck Ddrc.6 = 1 'C6 : Sdi Ddrb.2 = 1 'B2 : D/c Ddrb.3 = 1 'B3 : Sce Ddrb.4 = 1 'B4 : Rst Hours = 0 'Houdt uren bij Minutes = 0 'Houdt minuten bij Seconds = 0 'Houdt seconden bij Secs = 0 'seconden via timer Lcd_counter = 0 'Variabele voor data naar LCD 'Set 16-bit TIMER for Time-measuring Config Timer1 = Timer , Prescale = 256 'Timer1, set for 1 second Enable Timer1 Timer1 = 36716 On Timer1 1_sec Enable Interrupts 'I2C / TWI Config Twi = 400000 'set the I2C bus to 'fast' speed' I2cinit 'Initialiseer I2C bus 'LCD Initlcd 'Initialiseer LCD Glcdcmd 33 : Glcdcmd 190 'LCD Contrast Setfont Font6x8 'Selecteer font Cls Lcdat 3 , 1 , "Luchtdruk" 'Text 'Calibratie-waarden BMP180 ophalen Call Read_params() Call Read_temp_bmp180() Call Read_press_bmp180() 'Wacht 2 seconden (ivm text op beeldscherm) Wait 2 End Sub Sub Read_params() Dim I2c_counter As Byte , Temp_single As Single I2cstart I2cwbyte &HEE 'Adres voor opdracht BMP180 I2cwbyte &HAA 'Opdracht : lezen vanaf 0xAA I2cstart I2cwbyte &HEF 'Adres voor uitlezen waarden : BMP180 For I2c_counter = 1 To 22 '0xAA t/m 0xBF If I2c_counter < 22 Then I2crbyte I2c_byte(i2c_counter) , Ack 'en naar volgende Else I2crbyte I2c_byte(i2c_counter) , Nack 'Afsluiten Van Uitlezen End If Next I2cstop 'Afbreken communicatie 'Calibratiewaarden converteren 'Opm : onderstaande kan korter en sneller in een for-next loop 'AC1 Temp_single = I2c_byte(2) * 256 Temp_single = Temp_single + I2c_byte(1) Temp_single = Temp_single - 32768 Param_int_bmp180(1) = Temp_single 'AC2 Temp_single = I2c_byte(4) * 256 Temp_single = Temp_single + I2c_byte(3) Temp_single = Temp_single - 32768 Param_int_bmp180(2) = Temp_single 'AC3 Temp_single = I2c_byte(6) * 256 Temp_single = Temp_single + I2c_byte(5) Temp_single = Temp_single - 32768 Param_int_bmp180(3) = Temp_single 'AC4 Temp_single = I2c_byte(8) * 256 Temp_single = Temp_single + I2c_byte(7) Param_wrd_bmp180(1) = Temp_single 'AC5 Temp_single = I2c_byte(10) * 256 Temp_single = Temp_single + I2c_byte(9) Param_wrd_bmp180(2) = Temp_single 'AC6 Temp_single = I2c_byte(12) * 256 Temp_single = Temp_single + I2c_byte(11) Param_wrd_bmp180(3) = Temp_single 'B1 Temp_single = I2c_byte(14) * 256 Temp_single = Temp_single + I2c_byte(13) Temp_single = Temp_single - 32768 Param_int_bmp180(4) = Temp_single 'B2 Temp_single = I2c_byte(16) * 256 Temp_single = Temp_single + I2c_byte(15) Temp_single = Temp_single - 32768 Param_int_bmp180(5) = Temp_single 'MB Temp_single = I2c_byte(18) * 256 Temp_single = Temp_single + I2c_byte(17) Temp_single = Temp_single - 32768 Param_int_bmp180(6) = Temp_single 'MC Temp_single = I2c_byte(20) * 256 Temp_single = Temp_single + I2c_byte(19) Temp_single = Temp_single - 32768 Param_int_bmp180(7) = Temp_single 'MD Temp_single = I2c_byte(22) * 256 Temp_single = Temp_single + I2c_byte(21) Temp_single = Temp_single - 32768 Param_int_bmp180(8) = Temp_single End Sub Sub Read_params_bmp180() Dim I2c_int As Integer '-32,768 to +32,767 Dim I2c_int_1 As Byte At I2c_int + 0 Overlay 'Last 8-bits of Integer Dim I2c_int_2 As Byte At I2c_int + 1 Overlay 'First 8-bits of Integer Dim I2c_wrd As Word '0 to +65525 Dim I2c_wrd_1 As Byte At I2c_wrd + 0 Overlay 'Last 8-bits of Word Dim I2c_wrd_2 As Byte At I2c_wrd + 1 Overlay 'First 8-bits of Word Dim Int_counter As Byte Dim Wrd_counter As Byte Dim Bmp180_counter As Byte Int_counter = 1 Wrd_counter = 1 I2cstart I2cwbyte &HEE 'Command address BMP180 I2cwbyte &HAA 'Start address to read from I2cstart I2cwbyte &HEF 'Retreive address BMP180 'Read all data For Bmp180_counter = 1 To 11 'AC1 .. MD If Bmp180_counter < 4 Or Bmp180_counter > 6 Then I2crbyte I2c_int_2 , Ack If Bmp180_counter < 11 Then I2crbyte I2c_int_2 , Ack Else I2crbyte I2c_int_1 , Nack End If Param_int_bmp180(int_counter) = I2c_int Incr Int_counter Else I2crbyte I2c_wrd_2 , Ack I2crbyte I2c_wrd_1 , Ack Param_wrd_bmp180(wrd_counter) = I2c_wrd Incr Wrd_counter End If Next I2cstop End Sub Sub Read_press_bmp180() Dim Bmp180_timeout As Byte , Bmp180_status As Byte Dim Raw_press_a As Byte At Raw_press + 0 Overlay Dim Raw_press_b As Byte At Raw_press + 1 Overlay Dim Raw_press_c As Byte At Raw_press + 2 Overlay 'Start the pressue measurement I2cstart I2cwbyte &HEE I2cwbyte &HF4 I2cwbyte &B11_110100 ' set to ultra high resolution: 8 time over sampling I2cstop Bmp180_timeout = 100 ' time out after about 100ms Do Waitms 1 I2cstart I2cwbyte &HEE 'Adres BMP180 : hxEE (commando) I2cwbyte &HF4 'ctr_meas I2cstart I2cwbyte &HEF 'Adres BMP hxEF (data lezen) I2crbyte Bmp180_status , Nack Decr Bmp180_timeout 'Verlagen van time_out getal Loop Until Bmp180_status.5 = 0 Or Bmp180_timeout = 0 ' wait for completion If Bmp180_timeout = 0 Then Raw_press = -1 Else 'now read the pressure data I2cstart I2cwbyte &HEE 'Command / address BMP180 I2cwbyte &HF6 I2cstart I2cwbyte &HEF 'Read / address BMP180 I2crbyte Raw_press_c , Ack I2crbyte Raw_press_b , Ack I2crbyte Raw_press_a , Nack I2cstop Shift Raw_press , Right , 5 , Signed End If End Sub Sub Read_temp_bmp180() Dim Raw_temp_a As Byte At Raw_temp + 0 Overlay Dim Raw_temp_b As Byte At Raw_temp + 1 Overlay 'read the temp I2cstart I2cwbyte &HEE 'Adres BMP180 hxEE I2cwbyte &HF4 'ctrl_meas I2cwbyte &H2E 'Get Temp I2cstop Waitms 5 I2cstart I2cwbyte &HEE 'Addresseer commando BMP180 &HEE I2cwbyte &HF6 'Output msb I2cstart I2cwbyte &HEF '$HEF adres read I2crbyte Raw_temp_b , Ack I2crbyte Raw_temp_a , Nack I2cstop End Sub Sub Calc_tp() Dim W(6) As Single 'TEMPERATURE '# X1 = (UT - AC6) * Ac5 / 2^15 W(1) = Raw_temp - Param_wrd_bmp180(3) 'UT - AC6 W(1) = W(1) * Param_wrd_bmp180(2) ' (UT - AC6) * AC5 W(1) = W(1) / 32768 ' (UT - AC6) * AC5 / 2^ 15 '# X2 = MC * 2^11 / (X1 + MD) W(2) = Param_int_bmp180(7) * 2048 'MC * 2^11 W(3) = W(1) + Param_int_bmp180(8) ' (X1 + MD) W(2) = W(2) / W(3) 'MC * 2^11 / (X1 + MD) '# B5 = X1 + X2 W(3) = W(1) + W(2) 'X1 + X2 '# T = (B5 + 8) / 2^4 W(4) = W(3) + 8 'B5 + 8 W(4) = W(4) / 16 ' (B5 + 8) / 2^4 Act_temp = W(4) 'PRESSURE '# B6 = B5 - 4000 W(1) = W(3) - 4000 'B5 - 4000 '# X1 = (B2 * (B6 * B6 / 2^12)) / 2^11 W(2) = W(1) * W(1) 'B6 * B6 W(2) = W(2) / 4096 'B6 * B6 / 2^12 W(2) = Param_int_bmp180(5) * W(2) 'B2 * (B6 * B6 / 2^12) W(2) = W(2) / 2048 'B2 * (B6 * B6 / 2^12) / 2^11 '# X2 = AC2 * B6 / 2^11 W(3) = Param_int_bmp180(2) * W(1) 'AC2 * B6 W(3) = W(3) / 2048 'AC2 * B6 / 2^11 '# X3 = X1 + X2 W(4) = W(2) + W(3) 'X3 = X1 + X2 '# B3 = (((AC1 * 4 + X3) +2 / 4 W(5) = Param_int_bmp180(1) * 4 'AC1 * 4 W(5) = W(5) + W(4) 'AC1 * 4 + X3 W(5) = W(5) + 2 ' (AC1 * 4 + X3) + 2 W(5) = W(5) / 4 ' ((AC1 * 4 + X3) + 2) / 4 '# X1 = AC3 * B6 / 2^13 W(2) = Param_int_bmp180(3) * W(1) 'AC3 * B6 W(2) = W(2) / 8192 'AC3 * B6 / 2^13 '# X2 = (B1 * (B6 * B6 / 2^12)) / 2^16 W(3) = W(1) * W(1) 'B6 * B6 W(3) = W(3) / 4096 'B6 * B8/ 2^12 W(3) = Param_int_bmp180(4) * W(3) 'B1 * (B6 * B8/ 2^12) W(3) = W(3) / 65536 'B1 * (B6 * B8/ 2^12) / 2^16 '# X3 = ((X1 + X2) + 2) / 2^2 W(4) = W(1) + W(3) 'X1 + X2 W(4) = W(4) + 2 ' (X1 + X2) + 2 W(4) = W(4) / 4 ' ((X1 + X2) + 2) / 4 '# B4 = AC4 * (X3 + 32768) / 2^15 W(6) = W(4) + 32768 'X3 + 32768 W(6) = Param_wrd_bmp180(1) * W(6) 'AC4 * (X3 + 32768) W(6) = W(6) / 32768 'AC4 * (X3 + 32768) / 2^15 '# If ((UP - B3) * 50000) < 0 then ' p = (B7 * 2) / B4 ' Else ' p = 2 * (B7 / B4) ' End If W(3) = Raw_press - W(5) 'UP - B3 W(3) = W(3) * 50000 'UP - B3 * 5000 If W(3) < 0 Then W(3) = W(3) * 2 'B7 * 2 W(3) = W(3) / W(6) 'B7 * 2 / B4 Else W(3) = W(3) / W(6) 'B7 / B4 W(3) = 2 * W(3) '2 * (B7 / B4) End If '# X1 = (p / 2^8) * (p * 2^8) W(1) = W(3) / 256 'p / 2^8 W(1) = W(1) * W(1) ' (p / 2^8) * (p / 2^8) '# X1=(X1 * 3038) / 2^16 W(1) = W(1) * 3038 'X1 * 3038 W(1) = W(1) / 65536 ' (X1 * 3038) / 2^16 '# X2 = (-7357 * p) / 2^16 W(2) = -7357 * W(3) '-7357 * p W(2) = W(2) / 65536 ' (-7357 * p) / 2^16 '# p = p + (X1 + X2 + 3791) / 2^4 W(4) = W(1) + W(2) 'X1 + X2 W(4) = W(4) + 3791 'X1 + X2 + 3791 W(4) = W(4) / 16 ' (X1 + X2 + 3791) / 2^4 W(4) = W(3) + W(4) 'p + (X1 + X2 + 3791) / 2^4 '# Convert P to kPa W(4) = W(4) / 1000 Act_press = W(4) End Sub Sub Time_update() Dim Time_byte As Byte , Time_str As String * 8 Seconds = Seconds + Secs Secs = 0 If Seconds > 59 Then Incr Minutes Seconds = Seconds - 60 End If If Minutes > 59 Then Incr Hours Minutes = Minutes - 60 End If If Hours > 23 Then Hours = 0 End If 'Tijd / datum naar display 'Tijd If Hours < 10 Then Time_str = "0" Time_str = Time_str + Str(hours) Time_byte = Seconds Mod 2 'Waar knippert het If Time_byte = 0 Then Time_str = Time_str + ":" Else Time_str = Time_str + " " End If If Minutes < 10 Then Time_str = Time_str + "0" Time_str = Time_str + Str(minutes) Setfont Font12x16dig Lcdat 4 , 12 , Time_str End Sub '=============================================================================== 1_sec: Timer1 = 36716 Incr Secs Return $include "font6x8.font" $include "font12x16dig.font"