Bascom Druck- und Temperatursensor HP03 und BASCOM

avrkarl

Neues Mitglied
04. Mai 2011
28
0
0
Sprachen
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.

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

'#####################################
 
Hi,

ich bin grad für ne kleine Bestellung bei Pollin am stöbern und da kommt mir das natürlich sehr gelegen ;)
Da werd ich mir zu dem restlichen Fummelzeugs mal gleich einen mitbestellen. Ist wenigstens etwas höher integriertes dabei ;)

Besten Dank :cool:

Gruß
Dino
 
Edit sagt: "Bitte löschen..."

Wobei ich aber sagen muss, ein nettes Teil, werde ich mir auch mal zulegen :)

@Dino: du hast ne PN!
 
Habe noch die barometrische Höhenformel mit eingebaut, so dass der Druck auf NN ausgegeben wird (also dass, was die Wetterdienste so angeben). Erstaunlicherweise stimmt alles sehr gut überein. Wäre interessiert, ob es bei Euch auch hinkommt. Die Höhe Eures Messpunkts müsst ihr bei "Const Hnn" in m angeben. Das sollte schon auf etwa 10m genau sein, da der Druck stark von der Höhe abhängig ist.

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

Const Hnn = 330                                             'meter abvove sea level, h ueber NN



Dim D1 As Word
Dim D2 As Word

Dim Temperature As Single
Dim Pressure As Single
Dim Pressure_baro As Single

Dim Temperatures As String * 5
Dim Pressure_baros As String * 6

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

'#####################################

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
Declare Function Calcpbaro(byval Temperature As Single , Pressure As Single) 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
   Pressure = Calcpress(d2 , D1)
   Temperature = Calctemp(d2)
   Pressure_baro = Calcpbaro(temperature , Pressure)        'pressure at NN; Barometric formula

   Temperatures = Fusing(temperature , "#.#")
   Pressure_baros = Fusing(pressure_baro , "#.#")


   'Print "D1: " ; D1
   'Print "D2: " ; D2
   Print "T: " ; Temperatures ; " deg"
   'Print "P: " ; Pressure ; " hpa"
   Print "P: " ; Pressure_baros ; " 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

'#####################################   Barometric formula: p(h1)=p(h0)(1-(0.0065*delta(h)/T(h0))^5.225 ; 0.65K / 100m

Function Calcpbaro(byval Temperature As Single , Pressure As Single) As Single

Local Tfac As Single
Local Pfac As Single
Local T As Single
Local Pbaro As Single

Tfac = 0.0065 * Hnn

T = Temperature + 273.15
T = T + Tfac

Pfac = Tfac / T
Pfac = 1 - Pfac
Pfac = Pfac ^ 5.255
Pfac = 1 / Pfac
Pbaro = Pfac * Pressure

Calcpbaro = Pbaro

End Function

PS. Nach einer fast schlaflosen Nacht und einigen grauen Haaren mehr, funktionieren die Funkmodule RFM01/RFM02 grob. Also wird es wohl doch auf eine Wetterstation hinauslaufen. Mehr dazu vielleicht viel viel später....;-)
 
Hallo,
ich habe das Programm mal ausprobiert.
Der angezeigte Druck stimmt etwa mit Angaben von Wetterdaten im Internet überein.
Nur die Temperatur liegt ca. 10 Grad über der Zimmertemperatur.
z.Z. 1015 hpa und 33 Grad
Trage ich die Werte aus dem Datenblatt ein, statt wirklich zu messen, stimmen auch hier die angezeigten Werte.
Das Programm arbeitet also korrekt. (Dank an den Entwickler.)
Wird das Teil selbst so warm ? Habt ihr da Erfahrungen ?


Danke Dietmar
 
Hallo
habe den Code auch ausprobiert einmal mit LCD und einmal seriell, ich bekomme weder in Hterm noch auf dem LCD eine Anzeige. Woran könnte das denn liegen?
Wäre total schön wenn einer Antworten würde......Danke im vorraus
Gruss Thomas
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)