[BMP180] Bascom vs C

Ik heb hier een BMP180-sensormodule. Het is een sensor van Bosch, waarmee temperatuur en luchtdruk gemeten kan worden. Via een Atmega32 probeer ik er gegevens uit los te peuteren, via I2C.

https://www.uploadarchief.net/files/download/bmp180.jpg

Via internet heb ik de nodige info opgehaald. Zo ook om er gegevens uit te kunnen trekken. Via Bascom-code is het me gelukt om de Raw-Temp (UT) en RAW-Pressure (UP) uit te trekken.
De verkregen waarden wijkt, voor wat betreft de luchtdruk erg af. In de datasheet staat een uitleg over hoe de berekeningen uitgevoerd dienen te worden, middels formules.
Voor de berekeningen heb ik de parameter-waarden uit de datasheet gebruikt. De uiteindelijk berekende waarden voor de temperatuur en de luchtdruk wijken abnormaal af.
In Nederland schommelt de temperatuur tussen -10 en +35 oC. De luchtdruk tussen de 950 en 1015. Maar de berekende waarden wijken echt enorm af, en vallen ver buiten de aangegeven waarden. Als ik de meter zou mogen geloven zou het vandaag of erg fris zijn of kokend heet. En dan heb ik het nog niet eens over de luchtdruk.

Voor mij vormde dit een reden om de gecalibreerde parameters uit de BMP180 te halen, middels I2C. Je voelt het al aankomen, deze schijnen ook behoorlijk af te wijken, van de datasheet. Inmiddels zit ik te denken of "ik" wellicht iets fout doe.
Vandaar dat ik probeer om het op CO te posten, in de hoop dat ik er alsnog uit kom.

Om te starten, zal ik hier een overzicht geven van de gegevens uit de datasheet, en dat wat ik hier in de praktijk uit de BMP180 krijg.

code:


Param	Byte1	Byte2	Waarde		Datasheet
AC1	34	209	int 20770	408
AC2	251	193	int 16891	-72
AC3	199	194	int 17095	-14383
AC4	127	217	wrd 55679	32741
AC5	100	20	wrd 5220	32757
AC6	75	38	wrd 9803	23153
B1	25	115	int -3303	6190
B2	0	39	int -22784	4
MB	138	0	int -32630	-32768
MC	209	246	int 30417	-8711
MD	9	138 	int 2569	2868

Ik haal in 1 keer alle parameters uit de BMP180. Vervolgens sorteer ik ze en vertaal het terug naar een waarde.

Opm : Wat ik heb begrepen, is dat :
In C, "Short" de waarde -32,768 tot +32,767 kan hebben. In Bascom komt dat overeen met een Integer.
In C, "Unsigned short" de waarde 0 tot 65535 kan hebben. In Bascom komt dat overeen met een Word.

Goed, laat ik een voorbeeld geven hoe ik bijv. een parameter bereken.

AC1 (short / integer)
(Byte2 * 256) + Byte1 = (209 * 256) + 34 = 53538. Vervolgens trek ik er 32768 van af, zodat AC1 de waarde 20770 krijgt.

AC4 (unsigned short / word)
(Byte2 * 256) + Byte1 = (217 * 256) + 127 = 55769.

Nu ja, als de gecalibreerde waarden zouden kloppen, dan zou het verder niet uit moeten maken. Maar ik vindt ze behoorlijk afwijken, met een enkele uitzondering.

Pas ik de formules toe, zoals in de datasheet aangegeven, dan zijn de resultaten bedroevend. Ze wijken echt fors af. Maar het kan ook natuurlijk zijn dat ik de formules niet goed hanteer. Dat komt mede omdat ik bepaalde dingen niet goed begrijp. Ik daarom de waarden uit de datasheet gebruikt samen met de calibratie-waarden. Zo heb ik een aardige indruk gekregen wat er allemaal gebeurd (alles in een excel sheet gepropt, om het te kunnen volgen).
Toch zijn er een aantal zaken waar ik geen vat op heb.

Opm : Hieronder zijn de RAW_temp (UT) en RAW_pressure (UC) uit de BMP180.
Voor UT krijg ik Byte1 = 210 en Byte2 = 107
Voor UC krijg ik Byte1 = 71, Byte2 = 35 en Byte3 = 5

De hieronderstaande formules zijn overgenomen uit de datasheet :

code:


Temperatuur :
X1 = (UT - AC6) * AC5 / 2^15
X2 = MC * 2^11 / (X1 + MD)
B5 = X1 + X2
T = (B5 + 8) / 2^4

Luchtdruk :
B6 = B5 - 4000
X1 = (B2 * (B6 * B6 / 2^12)) / 2^11
X2 = AC2 * B6 / 2^11
X3 = X1 + X2
B3 = (((AC1 * 4 + X3) << oss) + 2) / 4
X1 = AC3 * B6 / 2^13
X2 = (B1 * (B6 * B6 / 2^12)) / 2^15
X3 = ((X1 + X2) + 2) / 2^2
B4 = AC4 * (unsigned long)(X3 + 32768) / 2^15
B7 = ((unsigned long)UP - B3) * (50000 >> oss)
if (B7 < 0x800000000) {p = (B7 * 2) / B4}
else {p = (B7 / B4) * 2}
X1 = (p / 2^8) * (p / 2^8)
X1 = (X1 * 3038) / 2^16
X2 = (-7357 * p) / 2^16
p = (p + (X1 + X2 + 3791)) / 2^4

Ik heb het bovenstaande zitten napluizen, en heb vervolgens haakjes toegevoegd, zodat je kunt zien hoe ik aan mijn berekeningen kom :

code:


Temperatuur :
X1 = (UT - AC6) * AC5 / 32768
X2 = MC * 2048 / (X1 + MD)
B5 = X1 + X2
T = (B5 + 8) / 16

Luchtdruk :
B6 = B5 - 4000
X1 = ((B2 * (B6 * B6)) / 4096) / 2048
X2 = (AC2 * B6) / 2048
X3 = X1 + X2
B3 = ((((AC1 * 4) + X3) << oss) + 2) / 4
X1 = (AC3 * B6) / 8192
X2 = ((B1 * (B6 * B6)) / 4096) /  32768
X3 = ((X1 + X2) + 2) / 4
B4 = (AC4 * (X3 + 32768)) / 32768
B7 =  Zorg ervoor dat UP positief is (- teken weghalen)
      en dan (UP - B3) * 50000

Indien B4 < 0 dan :
      p = (B7 * 2) / B4
anders :
      p = (B7 / B4) * 2

X1 = (p / 256) * (p / 256)
X1 = (X1 * 3038) / 65536
X2 = (-7357 * p) / 65536
p = (p + (X1 + X2 + 3791)) / 16

Wat met "<< oss" en ">> oss" in de datasheet wordt bedoeld, is me onduidelijk. Evengoed, of beter : evenslecht, heb ik het niet helemaal duidelijk voor me wat bij "AC4 * (unsigned long)UP - B3) * (50000 >> oss) gebeurt.

Goed, een hele lap text, incl. wat formules. Ik kan me heel goed voorstellen dat vele lezers hierdoor al meteen wegduiken. Ik had het inderdaad ook stapsgewijs middels reacties kunnen plaatsen. Ik vind het echter eerlijker om meteen te laten zien wat ik al heb ondernomen en waar ik ergens gestruikeld moet zijn.

Ik hoop dat er reacties komen met aanvullende info, zodat ik de BMP180 uiteindelijk aan de praat krijg.

Van elk bezoek aan CO leer ik weer meer...

Hallo,

Zou je de echte bascom code willen toevoegen, dan valt er wat te controleren. Als datgene waar code bij staat echt zo in de bascom IDE is gezet dan gaat het niet werken.

Het makke van Bascom is dat je maar 1 bewerking per regel mag doen.
T = (B5 + 8) / 16 , mag dus niet, je moet dit opsplitsen.

bascom code:

T= B5 + 8
T= T / 16

en daar moet je ook nog bij oppassen dat de variable van hetzelfde type zijn.

In een terzijde presteren deze sensoren volgens mij erg goed; ik kan niet echt programmeren, maar met de Arduino libraries logde ik afgelopen maand deze metingen uit een BME280:

Het verschil met het dichtstbijzijnde knmi station, de rode puntjes, is klein. En dat station staat niet om de hoek.

oss is de oversampling setting en kan een waarde hebben van 0 tot 3, afhankelijk van je instelling. >> en << zijn schuif operaties in C. >> 1 is 1 bit opschuiven naar rechts en is hetzelfde als delen door 2. << 1 is opschuiven naar links, en dus vermenigvuldigen met 2.

De vermenigvuldig/deel factor verandert met de waarde van oss.
oss = 0 : factor = 1.
oss = 1 : factor = 2.
oss = 2 : factor = 4.
oss = 3 : factor = 8.

AC1 (short / integer)
(Byte2 * 256) + Byte1 = (209 * 256) + 34 = 53538. Vervolgens trek ik er 32768 van af, zodat AC1 de waarde 20770 krijgt.

Dit gaat ook niet helemaal goed:
(Byte2 * 256) + Byte1 = (209 * 256) + 34 = 53538.
Resultaat is een signed int, dus max 32767. Het getal is groter dan 32767 en dus negatief. De feitelijk waarde krijg je door er 65536 (2^16) van af te trekken. Dus AC1 = 53538 - 65536 = -11998.

Ik zou zeggen dat de calibratie waarden fout zijn. Misschien moet je opnieuw calibreren, of de waarden uit de datasheet terugschrijven.

Bedankt voor de vele interessante reacties.
Op verzoek heb ik de broncode in Bascom bijgesloten. Ik heb de broncode wel flink wat opgeschoond tot het essentieele. (Ik had het nodige zitten schrijven aan probeersels, en het is wel handig om het weer overzichtelijk te krijgen.

Een korte toelichting van wat er in de "subs" uitgevoerd wordt :

Er zijn 2 versies om de calibratiecodes uit de BMP180 te krijgen :
- Sub Read_params()
- Sub Read_params_bmp180()

In beide gevallen worden de calibratiegegevens uiteindelijk opgeslagen in integers (Param_int_bmp180(x)) en words (Param_wrd_bmp180(x)). Met deze waarden worden later berekeningen uitgevoerd via de formules in de datasheet.

Uitlezen van de metingen (Raw_temp and Raw_press) vindt plaats in :
- Sub Read_temp_bmp180()
- Sub Read_press_bmp180()

Vervolgens vindt de berekening naar de temperatuur (act_temp) en luchtdruk (act_press) plaats in :
- Sub Calc_tp()

In de achtergrond loopt ook een klokje mee op het scherm. Dat verloopt via timer1, samen met de sub Time_update().

Alle gemeten bytes (0xAA t/m 0xBF), worden weergegeven op het display (Nokia 5110). Netzogoed kunnen de uitgerekende calibratie-waarden (int en wrd) op het scherm vertoond worden. Dat had ik in eerste instantie dan ook. Door de vreemde waarden heb ik -ter controle- de uitgelezen byte-waarden op het scherm gezet.

-=[ UPDATE ]=-
Ik heb de originele broncode een beetje aangepast.

Van elk bezoek aan CO leer ik weer meer...

Even voor de goede orde: De voorbeeld getallen van calibratie-waardes in het datasheet zijn alleen voorbeelden om te laten zien hoe de berekeningen gedaan moeten worden. Je MOET de waardes uit JOU sensor gebruiken.

Ohja, ook nog handig is dat je ipv de waardes uit JOU sensor te lezen je de "reken het uit" functie aanroept met de getallen uit het datasheet. Dan moet daar ook het resultaat uit het datasheet uitrollen....

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

@Rew:
Adafruit heeft ook een library (in C, volgens mij). Ik begreep er niet alles uit, maar ik kreeg er de indruk van dat ze de calibratiewaarden uit de datasheet gebruikten.

En ja, het leek mij ook handiger om de calibratie-waarden uit de eigen sensor te pakken, zeker omdat ik van die afwijkingen zie. Maar ja, als ik bij het uitlezen en converteren al grove fouten maak....
Kortom, het is verstandig om hier wat hulp te vragen. Dat van die "oss" is me nu duidelijker geworden. Ik moet het alleen nog zien uit te werken in code.
Verder moet ik nog even achterhalen hoe ik het beste de waarden kan uitlezen en opslaan.

Van elk bezoek aan CO leer ik weer meer...

Ik heb ook met deze formules geworsteld. In JAL, dat alleen met integers overweg kan. Daar zijn aardig wat uurtjes in gaan zitten.
Het uiteindelijke resultaat zat er steeds een of twee millibar naast. Dat moest beter kunnen. Uiteindelijk heb ik een tabel gemaakt met de berekende waarden en de KNMI gegevens. Het voelde eerlijk gezegd wel als een nederlaag, je werkt eigenlijk om het probleem heen. Maar na dagen puzzelen was ik er wel klaar mee.
Het werkt prima. Al heb je maar een paar meetpunten, de tussenliggende waarden kun je wel interpoleren.

Inmiddels heb ik een paar extra uurtjes erop zitten, maar ik krijg het maar niet betrouwbaar aan de praat. Ik heb de tip van deKees ook toegepast, wat betreft het terugrekenen. Ik heb me geconcentreerd op de temperatuurmeting. Waar het 23.4 oC is, geeft de sensor een waarde terug (na berekening) van 188.
De gemeten en berekende waarden voor de luchtdruk wijken nog steeds enorm af.

Voor mij een reden om uiteindelijk in de pen te klimmen en een mailtje naar Bosch Sensortec te sturen. Ik ga wachten op een reactie met een toelichting / hulp. In de tussentijd ga ik stoeien met een SHT30 (krijg ik momenteel helemaal niet aan de praat).

Van elk bezoek aan CO leer ik weer meer...
bprosman

Golden Member

Die SHT's zijn I2C, ooit een interface gemaakt voor de SHT11 (in Keil C) en die kon ik zo van de voorbeeldcode op de website van de fabrikant overnemen.

De jongere generatie loopt veel te vaak zijn PIC achterna.

code:

if (B7 < 0x800000000) {p = (B7 * 2) / B4}
else {p = (B7 / B4) * 2}

is niet hetzelfde als

code:


Indien B4 < 0 dan :
      p = (B7 * 2) / B4
anders :
      p = (B7 / B4) * 2

In C betekent '<< n' schuif de waarde in deze variabele n bits naar links.

code:

X3 = ((X1 + X2) + 2 / 2^2
B4 = AC4 * (unsigned long))(X3 + 32768) / 2^15

Hier kloppen de haakjes niet; X3 heeft een haakje openen teveel, terwijl B4 een haakje sluiten teveel heeft. Ik weet niet hoe bascom hiermee omgaat, in C zou je een compile fout moeten krijgen.

[Bericht gewijzigd door roadrunner84 op 10 april 2018 11:45:59 (34%)]

Meep! Meep!

Deze sensoren geven bij velen niet de goede temperatuur aan, dat geldt voor alle BMP sensoren.

De reden is dat er in een loop continu de temperatuur en de luchtdruk wordt opgevraagd, liefst zo snel als mogelijk. Door deze conversie warmt de chip op en geeft behoorlijk teveel aan; in ieder geval de temperatuur. Een graad of 6 teveel moet je aan denken.

Vertraag een en ander zodat maar 1x per seconde ofzo een conversie wordt gedaan en je ziet dat ze dan behoorlijk precies de temperatuur aangeven.

Ik gebruik ze met Domoticz om 1x per minuut de temperatuur te loggen en ik converteer dus ook maar 1x per minuut; dan zijn ze fantastisch...

@roadrunner :
Je hebt volkomen gelijk, wat betreft de haakjes. Ik heb de text in mijn posting inmiddels aangepast.
Wees gerust, in de broncode (bascom-file) is het wel goed uitgewerkt. Daar staat vermeld met welke formule gewerkt wordt, ook hoe de deelstapjes verlopen.

@djoveld :
Dat wat je nu opmerkt lijkt heel erg overeen te komen met wat ik hier in de praktijk zie gebeuren. Metingen waren standaard te hoog. Het was hier gisteren 28.3 oC, de BMP180 gaf (na berekeningen) aan dat het 42.6 oC was. Dat is ruim 14 graden te hoog. Met de luchtdruk was het nog driester gesteld. De BMP180 gaf waarden tussen de 1080 en 1120. Dat is erg hoog. Desondanks kan ik me wel vinden in je verklaring. Ik ga het eens proberen met 1x samplen per minuut. Kijken wat het oplevert.

En in de tussentijd wachten op een reactie van Bosch. Man, waarom konden ze niet een eenvoudiger sensor maken, waar rechtstreeks de meetwaarden uit floepen via I2C ?
Ik vind het uitlezen met deze sensoren best omslachtig en er kunnen diverse foutjes in de berekeningen sluipen.

@bprosman :
Vertel...
Ik heb het idee dat er redelijk wat broncode te vinden is voor allerlei sensoren in C. Echter, omzetten naar Bascom is een ander verhaal.

-=[ EDIT ]=-
@Arco (hieronder) :
Ja ja, ik weet het. Maar deze (SHT30-DIS) heb ik ook om mee te experimenteren.

Van elk bezoek aan CO leer ik weer meer...

De SHT sensors zijn geen luchtdruksensors, maar luchtvochtigheid...

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com
bprosman

Golden Member

De SHT sensors zijn geen luchtdruksensors, maar luchtvochtigheid...

Klopt, maar TS had het over de SHT30 en de aansturing (I2C) is het zelfde.

De jongere generatie loopt veel te vaak zijn PIC achterna.

Als ik de datasheet na lees dan blijkt uit de voorbeeld code dat er getallen voorkomen die enkel in een long variabele passen. Als ik een stuk c vertaal naar bascom dan probeer ik dat in eerste instantie altijd letterlijk te doen en daarna wat bij te schaven. Waarom gebruik jij in je berekeningen een word variabele en niet een dword? Ik zit op mijn telefoontje dit te lezen en kan zo niet de boel narekenen. Echter ik vind het raar om aan de voorbeeld calibratie waardes te twijfelen. Waarom zouden ze daar enorm van de werkelijkheid gaan zitten. Wellicht kan je met een word variabele wegkomen door wat truukjes toe te passen en wellicht benader ik het te simpel maar wou het toch nog even melden.

Op 10 april 2018 18:14:05 schreef bol00052:
Waarom zouden ze daar enorm van de werkelijkheid gaan zitten.

Dat luchtdruk meten is een gevoelig gebeuren. Je wilt een hoogteverschil van zeg 1m kunnen meten (*), dus dat is iets van 1/10000e van de totale druk. Maak je zeg een thermometer, dan is "absoluut" gezien een resolutie van 1 graad iets van 1/300e, dat is veel beter te mikken op een chip.

Kortom, ze hebben bij productie een enorme variatie aan sensoren, en door bij allemaal de calibratiewaardes mee te geven met de chip, kan je daar heel aardig de druk uit achterhalen. Het is niet zo dat ze in het datasheet een raar voorbeeld nemen, maar gewoon een aardig gemiddelde van hoe de sensoren uit de fabriek kwamen op het moment van schrijven van dat datsheet. Als ze iets aan het proces veranderd hebben, maar ook gewoon natuurlijke variatie kan behoorlijk andere getallen als calibratiewaardes geven.

(*) Eigenlijk 10cm, maar goed.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Er is een complete BMP180 voorbeeld incl. library te downloaden van de Bascom site https://www.mcselec.com/index2.php?option=com_forum&Itemid=59&…
Wel even inloggen om te kunnen zien/downloaden.

Piet_Knutselaar

Golden Member

Ooit onderstaande code voor picbasic (Proton) gemaakt.

pic basic code:


'****************************************************************
'*  Name    : BMP085-BMP180.bas                                 *
'*  Author  : www.Knutselaar.eu                                 *
'*  Date    : 4/Apr/2014                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
Device 18F25K20
Xtal = 20

Config_Start     
      FOSC = HS                   ;external oscillator
      FCMEN = OFF             ;Fail-Safe Clock Monitor disabled
      IESO = OFF                  ;internal external switchover mode
      PWRT = On                   ;power-up timer
      BOREN = On                  ;brown-out reset
      BORV = 27                   ;brown-out reset value (2,7V)
      WDTEN = OFF             ;watchdog timer
      WDTPS = 128             ;1:128 WDT prescalar
      PBADEN = OFF            ;analog port B<4:0> 
      STVREN = On             ;stack overflow reset
      LVP = OFF                   ;low voltage programming
      XINST = OFF             ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
      Debug = OFF             ;no debug
Config_End 

All_Digital TRUE

     Symbol SCL    =  PORTC.3   ' I2C clock pin 
     Symbol SDA    =  PORTC.4   ' I2C data pin
  
     Dim i2c_Reg     As Byte    'I2C register adres
     Dim x           As Byte    'gemiddelde teller
     
     Dim wAC1 As Word      'I2c uitlezing
     Dim wAC2 As Word      'I2c uitlezing
     Dim wAC3 As Word      'I2c uitlezing
     Dim wAC4 As Word      'I2c uitlezing
     Dim wAC5 As Word      'I2c uitlezing
     Dim wAC6 As Word      'I2c uitlezing
     Dim wB1 As Word       'I2c uitlezing
     Dim wB2 As Word       'I2c uitlezing
     Dim wMB As Word       'I2c uitlezing
     Dim wMC As Word       'I2c uitlezing
     Dim wMD As Word       'I2c uitlezing

     Symbol OSS = 3        'resolutie setting
     Dim OSS1    As Byte   'resolutie variabele
     Dim OSSdel  As Byte   'resolutie delay
     Dim AC1     As Dword  'Calibratie data  
     Dim AC2     As Dword  'Calibratie data    
     Dim AC3     As Dword  'Calibratie data    
     Dim AC4     As Dword  'Calibratie data     
     Dim AC5     As Dword  'Calibratie data    
     Dim AC6     As Dword  'Calibratie data     
     Dim B1      As Dword  'Calibratie data     
     Dim B2      As Dword  'Calibratie data     
     Dim MB      As Dword  'Calibratie data     
     Dim MC      As Dword  'Calibratie data     
     Dim MD      As Dword  'Calibratie data    
  
     Dim X1      As SDword  'Calibratie variabele
     Dim X2      As SDword  'Calibratie variabele
     Dim B5      As SDword  'Calibratie variabele
     Dim B6      As SDword  'Calibratie variabele   
     Dim X3      As SDword  'Calibratie variabele    
     Dim B3      As SDword  'Calibratie variabele    
     Dim B4      As Dword   'Calibratie variabele
     Dim B7      As Dword   'Calibratie variabele
     
     Dim UT      As Word    'ongecompenseerde temperatuur
     Dim UP      As Dword   'ongecompenseerde pressure
  
     Dim float1  As Float   'reken variable
     Dim float2  As Float   'reken variable
     
     Dim Alt     As SWord   'hoogte in meters x 10 
     Dim AltAv   As SDword  'gemiddelde hoogte x 10
     Dim T       As SWord   'graden celcius x 10
     Dim Pr      As Dword   'luchtdruk in Pa

     Cls
     Clear
     Print At 1 , 1 , " Knutselaar.eu "
     DelayMS 1000

     GoSub read_BMP_eeprom  'uitlezen eeprom data (calibratie data)

 main:

     For x = 1 To 20            'gemiddelde uit 20 metingen
         GoSub get_BMP_temp     'niet gecompenseerde temperatuur uitlezen
         GoSub calc_BMP_temp    'gecompenseerde temperatuur
         GoSub get_BMP_pressure 'niet gecompenseerde druk uitlezen
         GoSub calc_BMP_press   'gecompenseerde druk
         GoSub calc_BMP_Alt     'hoogte t.o.v. gemiddeld zee niveau 
         AltAv = AltAv + Alt    '(niet gecompenseerd voor luchtdruk verschillen)
     Next x
     AltAv = AltAv/20

     Print At 1 , 1 , SDec AltAv/10,".",Dec1 AltAv," m ",SDec2 T/10,".",Dec1 T , 223, "C    " 
     Print At 2 , 1 , Dec Pr/100,".",Dec1 Pr/10," Pa   "
     
     AltAv = 0
     Toggle LATA.5

GoTo main

'------Start subroutines -------------------------------------------
 read_BMP_eeprom:


     i2c_Reg =$AA  'Start adres van de BMP085 Calibratie data
     I2CIn SDA,SCL,$EF,i2c_Reg, [wAC1,wAC2,wAC3,wAC4,wAC5,wAC6,wB1,wB2,wMB,wMC,wMD]  'Read 11 words out of sensor MSB then LSB

     AC1 = (wAC1.HighByte<<8) + wAC1.LowByte  
     AC2 = (wAC2.HighByte<<8) + wAC2.LowByte
     AC2 = AC2-65536
     AC3 = (wAC3.HighByte<<8) + wAC3.LowByte  
     AC3 = AC3-65536
     AC4 = (wAC4.HighByte<<8) + wAC4.LowByte         
     AC5 = (wAC5.HighByte<<8) + wAC5.LowByte
     AC6 = (wAC6.HighByte<<8) + wAC6.LowByte
     B1 = (wB1.HighByte<<8) + wB1.LowByte
     B2 = (wB2.HighByte<<8) + wB2.LowByte
     MB = (wMB.HighByte<<8) + wMB.LowByte
     MB = MB - 65536
     MC = (wMC.HighByte<<8) + wMC.LowByte
     MC = MC - 65536
     MD = (wMD.HighByte<<8) + wMD.LowByte
Return
  
 get_BMP_temp:

     UT = 0
     i2c_Reg = $F4                     'control register adres
     I2COut SDA,SCL,$EE,i2c_Reg,[$2E]  'schrijf $2E voor temperature conversie
     DelayMS 10                        'Delay 10ms na write
     i2c_Reg = $F6                     '$F6 is het resultaat register MSB
     I2CIn SDA,SCL,$EF,i2c_Reg,[UT]    'Lees temperatuur MSB, LSB.
Return
  
 get_BMP_pressure:

     i2c_Reg = $F4                     'control register adres
     OSS1 = $34+(OSS << 6)
     I2COut SDA,SCL,$EE,i2c_Reg,[OSS1] 'Write $34+(oss << 6) voor pressure conversie
     If OSS = 3 Then 
         OSSdel = 30 
     Else 
         OSSdel = 10
     End If                               
     DelayMS OSSdel                    'Delay 30mS voor HiRes resultaat (oss=3))
     i2c_Reg = $F6                     '$F6 is het resultaat register MSB
     I2CIn SDA,SCL,$EF,i2c_Reg,[UP]    'Lees pressure MSB, LSB, XLSB, $F9 ($F9 is niet nodig).
     UP = UP >> (16 - OSS)             'verwijder $F9 van resultaat (>>8), en schuif resultaat terug naar 16 tot 19 Bits (OSS waarde afhankelijk)
Return  
  
 calc_BMP_temp:                        'temperatuur berekenen met
     X1 = (UT - AC6)                   'calibratie gegevens, formules
     X1 = (X1 *AC5)/32768              'uit de BMP035 datasheet.
     X2 = (MC * 2048)
     X2 = X2/(X1 + MD)
     B5 = X1 + X2
     T = (B5 + 8)/16                   'temperatuur in °C*10 
Return
  
 calc_BMP_press:                       'pressure berekenen met
     B6 = B5 - 4000                    'calibratie gegevens, formules
                                       'uit de BMP035 data sheet.
     X1 = (B6*B6)/4096 
     X1 = (B2 * X1)/2048
     
     X2 = (AC2 * B6)/2048
     X3 = X1 + X2
     
     B3 = (AC1 * 4)+ X3
     B3 = (B3 << OSS) + 2
     B3 = B3/4 
     
     X1 = (AC3 * B6)/8192
      
     X2 = (B6 * B6)/4096 
     X2 = (B1 * X2)/65536
     
     X3 = (X1 + X2) 
     X3 = (X3 + 2)/4
     
     X3 = X3 + $8000
     B4 = (AC4*X3)/$8000
     
     B7 = UP - B3 
     B7 = B7*(50000 >> OSS)
     
     If B7 < $80000000 Then 
         Pr = (B7 * 2) / B4
         Else
         Pr = (B7 / B4) * 2
     EndIf 
        
     X1 = Pr /$100
     X1 = X1 * X1 
     
     X1 = (X1 * 3038)/$10000
     
     X2 = -7357 * Pr
     X2 = X2/$10000
     
     X3 = X1 + X2 + 3791
     Pr = Pr + (X3/$10)         'druk in Pa        
Return
  
 calc_BMP_Alt:

     float1 = Pr/100      
     float1 = float1/1013.25
     float2 = 0.1902949571  
     float1 = Pow float1,float2
     float2 = 1 - float1
     Alt = 443300 * float2     'hoogte in meters x 10      
Return

End 

@Arco & bprosman:
Zodra ik het met de BMP180 goed aan de praat heb, ga ik met de SHT30 beginnen. Mocht ik daar niet uitkomen, zal ik het hier posten, of via een nieuw topic.

@bol00052:
Zo ben ik er ook mee bezig geweest. Kijken wat onder C een bepaalde variabele is, vervolgens onder Bascom terugzoeken waarmee het overeen komt. Voor berekeningen geldt hetzelfde.

@rew:
Ja, interessant weetje. Ik had het logischer gevonden dat de calibratie-waarden desondanks toch aardig bij elkaar in de buurt zitten. De praktijk laat iets anders zien. Als je dan ook nog zit te rommelen met de keuze voor de variabelen (Integer, Word, ...) dan wordt het een ware zoektocht om de bron (van alle ergernis) te ontdekken. Ik zat al met een Excel spreadsheetje op de achtergrond alle waarden te herberekenen. Als bepaalde waarden dan ook nog eens afwijken (inlezen / herberekenen calibratiewaarden, onjuiste keuze voor variabelen, gelimiteerde rekenmogelijkheden, afrondingsfouten, afwijkingen door het ontwerp), begint voorzichtig het plezier weg te ebben...
Gelukkig is er dan CO, waar mensen graag kennis en ervaring delen :)

@2N3055:
Ah, juist, inloggen is het belangrijke woord (pas dan krijg je de broncode te zien).
Ik had dat topic inderdaad ook gevonden, maar zag geen broncode voor download beschikbaar. Ik vond het dan ook raar dat er vervolgens wel voor werd bedankt. Vandaar dat ik dacht dat het wellicht elders op de site te downloaden was (maar ik kon het niet vinden). Inloggen dus...

@Piet_Knutselaar:
Dat is een erg interessante broncode die je hier deelt. Het komt aardig overeen met Bascom.

Verder, wil ik toch nog even -tussendoor- iedereen bedanken voor de reacties. Er staan interessante hints en tips tussen. Ik ga met bovenstaande broncodes stoeien. Volgens mij kom ik een heel eind.

Van elk bezoek aan CO leer ik weer meer...

Na lang stoeien, heb ik het eindelijk voor elkaar gekregen. Het bleek dat er wat kleine foutjes ingeslopen waren, plus dat ik de broncode niet goed had omgezet (met name met de "oss").
Ik kan nu wel zeggen dat ik absoluut geen liefhebber ben van deze sensor, maar erg blij ben dat het aan de praat is : op naar de SHT30.

Ik vermoed dat diverse CO'ers, ook ooit tegen deze sensor aan gaan lopen, samen met Bascom. Vandaar dat ik de vitale code, de berekening naar temperatuur en luchtdruk, hier ook post als naslagwerk voor anderen.

Een beknopte toelichting :
L(6) as long : Zijn variabelen, voor het rekenen.
Param_int_bmp180(8) : Integer (AC1, AC2, AC3, B1, B2, MB, MC, MD)
Param_wrd_bmp180(3) : Word (AC4, AC5, AC6)

Raw_temp : Long (= UT)
Raw_press : Long (= UP)
Act_Temp : Long (= T, gedeeld door 10 : x.x oC)
Act_Press : Long (=p gedeeld door 100 : hPa)

Uart_on : Bit (bedoeld ter controle, data over serieele poort)

Oh ja, en "oss" is ingesteld op 1. Dat zie je terug bij het "Shiften".

Ik vermoed dat het veel ellende en napluiswerk zal besparen. Ik heb er ruim 2 weken over gedaan, dus doe er je voordeel mee.

Van elk bezoek aan CO leer ik weer meer...

Goed, zoals ik al had gemeld, ben ik nu met de SHT30 aan de slag.
Ik loop wederom tegen een probleempje aan.

De SHT30-DIS-B reageerde totaal niet. In de datasheet staat op pagina 8 en 9 vermeld dat met de ADDR-pin het uiteindelijke I2C-adres kan worden ingesteld :

- Naar Gnd : 0x44
- naar Vcc : 0x45

Goed, in eerste instantie heb ik het naar Gnd (0x44) getrokken en code geschreven. Een soft reset, sampling-rate (1 mps) en zo nog wat dingen tijdens de start-up en later in een loop de meetwaarden eruit halen. De resultaten kwamen niet overeen met wat ik verwachtte. Ik vond het helemaal apart, toen bleek dat als ik de sensor met de hand verwarmde, de uitgelezen waarden niet veranderen. Voor mij een reden om uit voorzorg het adres te veranderen naar 0x45 (ADDR-pin aan Vcc).
Het probleem bleef echter.

Nu, na een paar dagen stoeien, kon ik nog steeds niet achterhalen waar het probleem nu lag. Het was de reden om een stukje code te schrijven, waarmee gescand wordt op welke adressen "iets" zit.
Tot mijn verbazing bleek de sensor niet op 0x44 of 0x45 te zitten, maar op 0x88 of 0x8A, als ik met de ADDR-pin ging stoeien.

Mijn eerste gedachte : Oh, zal wel defect zijn. Weggegooid en vervolgens een nieuwe op de print gesoldeerd. Voor de zekerheid ADDR-pin aan Vcc, zodat het op adres 0x45 zou zitten. Niet dus,.. De scan liet wederom zien dat de SHT30 op 0x8A zit.

Ik begin nu te twijfelen of ik nu een paar slechte SHT30 sensoren heb besteld / ontvangen, of dat er iets anders aan de hand is.

Wat me wel opviel is dat het betreffende adres een soort "shift" naar links heeft :

0x44 = 01000100
0x45 = 01000101

0x88 = 10001000
0x8A = 10001010

Kortom, doe ik iets fout, of ...

Broncode om te scannen naar I2C-devices :

code:


'Bascom-code : Checking occupied I2C addresses
$regfile = "M32def.dat"         'ATMega32
$crystal = 7372800              'ClockRate
$hwstack = 32
$swstack = 16
$framesize = 24
$baud = 9600                    'BaudRate (COM)
$lib "i2c_twi.lbx"              'I2C-library

'Variables
 Dim B As Byte                  'A counter
 Dim Text as String * 4         'String for max. 4 characters

'Pin-settings
 Ddrd.2 = 0                     'Pin D2 = input
'Alias
 Btn_pushed Alias Pind.2        'Name for a pin to read-out


 I2cinit                        'Initiate I2C bus
 Config Twi = 100000            'Used clock frequency when using $lib "i2c_twi.lbx"

 'Main
 '===============
 Do
    If Btn_pushed = 1 Then      'Button has been pushed ?
       Print "Start scan .."    'Message (UART / COM)
       For B = 2 To 254 Step 2  'All I2C Addresses, per 2 steps
           I2cstart             'Send Start
           I2cwbyte B           'Send Address
           If Err = 0 Then      'Ack received ?
              Text = Hex(b)     'Store found Hex-address
              Print Text        'Message Hex-address (UART / COM)
           End If
           I2cstop              'Free bus
       Next                     'And go to next I2C address
       Print "Done."            'Message (UART / COM)
    Else
      'Do Nothing
    End If
 Loop
End

P.S. Indien een moderator liever heeft dat dit vervolg in een ander topic wordt gestart,.. Geen probleem.

Van elk bezoek aan CO leer ik weer meer...

Bij I2C is het eigenlijke adres maar 7 bits lang, de 8ste bit wordt gebruikt om aan te geven of er moet gelezen worden, of geschreven. Hier kan dus wel verwarring ontstaan. Kan de sensor op het gevonden adres wel uitgelezen worden ?

Op 17 april 2018 04:36:31 schreef oxurane:
Tot mijn verbazing bleek de sensor niet op 0x44 of 0x45 te zitten, maar op 0x88 of 0x8A, als ik met de ADDR-pin ging stoeien.

Adressen op I2C zijn zeven-bits. Als je een I2C ding wil aanspreken, dan stuur je z'n adres in de BOVENSTE 7 bits met als onderste bitje een 0 - write of 1 -read.

Als het 7-bit adres 0x44 is, dan moet je dus 0x88 of 0x89 sturen afhankelijk van of je read of write wilt.

Als men spreekt over "het adres" kan je het hebben over die 0x44, maar ook over die 0x88. De helft van de wereld doet het zus de andere helft zo. Dus als je datasheet zegt dat het adres 0x44 is, en in de software moet je 0x88 opgeven, dan wil de software kennelijk "adres * 2" hebben.

Ze hadden 40 jaar geleden ook kunnen kiezen voor het hoogste bitje dat als adres wordt aangemerkt. Dan had je dus 0x44 voor read en 0xc4 voor write moeten sturen (of omgekeerd). Maar die keuze is dus niet gemaakt.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/