Hallo,
der HP03 ist ein interessanter Sensor, der Druck und Temperatur messen kann. Er ist zudem leicht beschaffbar und relativ preiswert. Da ich mich kürzlich damit beschäftigt habe, möchte ich Euch meinen Code zur Verfügung stellen.
Ein paar Infos zum Sensor und zum Programm.
Der Sensor kommuniziert über I2C mit dem µC und besitzt einige Besonderheiten. Interessanterweise befinden sich zwei unterschiedliche I2C Bausteine auf dem Modul, zum einen der Sensor selbst und zum anderen ein EEPROM, das einige Betriebsparameter gespeichert hat. Deshalb hat der Baustein insgesamt 4 Adressen, die angesprochen werden wollen. Neben den gewohnten SDA- und SCL- und natürlich GND- und Vcc- (3.3 V!) gibt es noch MLCK- und XLCR-Anschlüsse. Pin XLCR muss vor dem Auslesen der ADC-Daten (Druck und Temperatur) auf high gesetzt werden und vor dem Auslesen der EEPROM-Daten auf low. Währen des ADC-Zugriffs muss zudem ein Signal mit einer Frequenz von 32 kHz an MCLK anliegen. Das lässt sich bequem über einen Timer erledigen.
Die Kontaktierung des Sensors ist etwas fummelig und erfordert etwas Erfahrung mit Lötarbeiten. Davon abgesehen ein feiner Baustein, der in Verbindung mit einem Funkmodul zum Bau einer Wetterstation geradezu prädestiniert ist. Als Höhenmesser taugt er natürlich auch.
der HP03 ist ein interessanter Sensor, der Druck und Temperatur messen kann. Er ist zudem leicht beschaffbar und relativ preiswert. Da ich mich kürzlich damit beschäftigt habe, möchte ich Euch meinen Code zur Verfügung stellen.
Ein paar Infos zum Sensor und zum Programm.
Der Sensor kommuniziert über I2C mit dem µC und besitzt einige Besonderheiten. Interessanterweise befinden sich zwei unterschiedliche I2C Bausteine auf dem Modul, zum einen der Sensor selbst und zum anderen ein EEPROM, das einige Betriebsparameter gespeichert hat. Deshalb hat der Baustein insgesamt 4 Adressen, die angesprochen werden wollen. Neben den gewohnten SDA- und SCL- und natürlich GND- und Vcc- (3.3 V!) gibt es noch MLCK- und XLCR-Anschlüsse. Pin XLCR muss vor dem Auslesen der ADC-Daten (Druck und Temperatur) auf high gesetzt werden und vor dem Auslesen der EEPROM-Daten auf low. Währen des ADC-Zugriffs muss zudem ein Signal mit einer Frequenz von 32 kHz an MCLK anliegen. Das lässt sich bequem über einen Timer erledigen.
Die Kontaktierung des Sensors ist etwas fummelig und erfordert etwas Erfahrung mit Lötarbeiten. Davon abgesehen ein feiner Baustein, der in Verbindung mit einem Funkmodul zum Bau einer Wetterstation geradezu prädestiniert ist. Als Höhenmesser taugt er natürlich auch.
Code:
'##HP03 p,T Sensor##
'
' >3.3V Vcc
' >GND
' >MCLK > PB3
' >XCLR > PC2
' >SDA > PC1
' >SCLK > PC0
$regfile = "m328pdef.dat"
$crystal = 16000000
$baud = 115200
$hwstack = 64
$swstack = 64
$framesize = 64
$lib "i2c_twi.lbx" 'I2C
Config Sda = Portc.1
Config Scl = Portc.0
Config Twi = 100000
Config Portb.3 = Output 'MCLK
Config Portc.2 = Output 'XCLR
Mclk Alias Portb.3
Xclr Alias Portc.2
Config Timer0 = Timer , Prescale = 1 'Timer0 for MCLK signal
On Timer0 Timer_isr
Enable Interrupts
Const Hp03eeprom_w = &HA0 'I2C write address HP03 EEPROM
Const Hp03eeprom_r = &HA1 'I2C read address HP03 EEPROM
Const Hp03adc_w = &HEE 'I2C write address HP03 ADC
Const Hp03adc_r = &HEF 'I2C read address HP03 ADC
Const Hp03_adc_p = &HF0 'I2C address: ADC value for P
Const Hp03_adc_t = &HE8 'I2C address: ADC value for T
Dim D1 As Word
Dim D2 As Word
Dim Temperature As Single
Dim Pressure As Single
Dim Hi As Byte
Dim Lo As Byte
'##################################### sensor coefficients
Dim C1 As Word
Dim C2 As Word
Dim C3 As Word
Dim C4 As Word
Dim C5 As Word
Dim C6 As Word
Dim C7 As Word
Dim C1hi As Byte
Dim C1lo As Byte
Dim C2hi As Byte
Dim C2lo As Byte
Dim C3hi As Byte
Dim C3lo As Byte
Dim C4hi As Byte
Dim C4lo As Byte
Dim C5hi As Byte
Dim C5lo As Byte
Dim C6hi As Byte
Dim C6lo As Byte
Dim C7hi As Byte
Dim C7lo As Byte
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim I As Byte
'#####################################
Declare Sub Read_coeff
Declare Function Read_raw_pt(byval Pt_adress As Byte) As Word
Declare Function Calctemp(byval T_adc As Word) As Single
Declare Function Calcdut(byval T_adc As Word) As Single
Declare Function Calcpress(byval T_adc As Word , P_adc As Word) As Single
'#####################################
Call Read_coeff
'Print "C1: " ; C1
'Print "C2: " ; C2
'Print "C3: " ; C3
'Print "C4: " ; C4
'Print "C5: " ; C5
'Print "C6: " ; C6
'Print "C7: " ; C7
'Print "A: " ; A
'Print "B: " ; B
'Print "C: " ; C
'Print "D: " ; D
'##################################### main loop
Do
D1 = Read_raw_pt(hp03_adc_p)
D2 = Read_raw_pt(hp03_adc_t)
Pressure = Calcpress(d2 , D1)
Temperature = Calctemp(d2)
'Print "D1: " ; D1
'Print "D2: " ; D2
Print "T: " ; Temperature ; " deg"
Print "P: " ; Pressure ; " hpa"
Wait 1
Loop
End
'##################################### MCLK
Timer_isr:
Timer0 = 12 '12
Toggle Mclk
Return
'##################################### read sensor coefficients
Sub Read_coeff
I2cstart
I2cwbyte Hp03eeprom_w
I2cwbyte &H10
I2cstart
I2cwbyte Hp03eeprom_r
I2crbyte C1hi , Ack
I2crbyte C1lo , Ack
I2crbyte C2hi , Ack
I2crbyte C2lo , Ack
I2crbyte C3hi , Ack
I2crbyte C3lo , Ack
I2crbyte C4hi , Ack
I2crbyte C4lo , Ack
I2crbyte C5hi , Ack
I2crbyte C5lo , Ack
I2crbyte C6hi , Ack
I2crbyte C6lo , Ack
I2crbyte C7hi , Ack
I2crbyte C7lo , Ack
I2crbyte A , Ack
I2crbyte B , Ack
I2crbyte C , Ack
I2crbyte D , Nack
I2cstop
C1 = Makeint(c1lo , C1hi)
C2 = Makeint(c2lo , C2hi)
C3 = Makeint(c3lo , C3hi)
C4 = Makeint(c4lo , C4hi)
C5 = Makeint(c5lo , C5hi)
C6 = Makeint(c6lo , C6hi)
C7 = Makeint(c7lo , C7hi)
End Sub
'##################################### read raw sensor P and T values
Function Read_raw_pt(byval Pt_adress As Byte) As Word
Enable Timer0
Waitms 5
Xclr = 1
I2cstart
I2cwbyte Hp03adc_w
I2cwbyte &HFF
I2cwbyte Pt_adress
I2cstop
Waitms 50
I2cstart
I2cwbyte Hp03adc_w
I2cwbyte &HFD
I2cstart
I2cwbyte Hp03adc_r
I2crbyte Hi , Ack
I2crbyte Lo , Nack
I2cstop
Xclr = 0
Disable Timer0
Read_raw_pt = Makeint(lo , Hi)
End Function
'##################################### calc temperature
Function Calctemp(byval T_adc As Word) As Single
Local Dut As Single
Local T As Single
Local Dn As Integer
Dut = Calcdut(t_adc)
T = Dut * C6
T = T / 65536
T = T + 250
Dn = 2 ^ D
Dut = Dut / Dn
T = T - Dut
T = T / 10
Calctemp = T
End Function
'##################################### calc pressure
Function Calcpress(byval T_adc As Word , P_adc As Word) As Single
Local Dut As Single
Local Dut2 As Single
Local Offset As Single
Local Sens As Single
Local X As Single
Local P As Single
Dut = Calcdut(t_adc)
Dut2 = Dut / 16384
Offset = C4 - 1024
Offset = Offset * Dut2
Offset = C2 + Offset
Offset = Offset * 4
Dut2 = Dut / 1024
Sens = C3 * Dut2
Sens = C1 + Sens
X = P_adc - 7168
X = X / 16384
X = Sens * X
X = X - Offset
P = X * 10
P = P / 32
P = P + C7
P = P / 10
Calcpress = P
End Function
'##################################### calc dUT
Function Calcdut(byval T_adc As Word) As Single
Local D2mc5 As Single
Local D2mc52 As Single
Local Dut As Single
Local Cn As Integer
D2mc5 = T_adc - C5
D2mc52 = D2mc5 / 128
Dut = D2mc52 * D2mc52
If T_adc >= C5 Then
Dut = Dut * A
Else
Dut = Dut * B
End If
Cn = 2 ^ C
Dut = Dut / Cn
Dut = D2mc5 - Dut
Calcdut = Dut
End Function
'#####################################