BMP180 Temperature Sensor mikroC

General discussion on mikroC PRO for PIC.
Author
Message
nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

BMP180 Temperature Sensor mikroC

#1 Post by nigelmercier » 12 Sep 2016 12:29

I've got a Bosch BMP180 sensor mounted on the ubiquitous GY-68 PCB.

I have a board with a PIC16F1847 left over from a previous project; unfortunately the I2C pins are in use, so software I2C will be required.

I've looked on LibStock for suitable code for BMP085 and BMP180 in mikroC:
Weather Prediction System with BMP085 Pressure Sensor and AVR is for mikroC PRO for AVR
BMP085 Library is for mikroC PRO for PIC, but see below.
Bosch BMP085 and Bosch BMP180 Pressure and temperature measurement is for mikroC PRO for ARM
10DOF Click Library is for mikroC PRO for ARM & FT90x

The code BMP085 Library for mikroC PRO for PIC has problems:
The project file contains references to a non-existent drive: Path2=C:\Users\Tiago\Google Drive\MikroC\Exemplos\BMP085\pressure_sensor_bmp085\
It will not compile properly if I add the #included file to the project: lots of Redefinition ... errors.
I'm also a bit concerned about using code I can't follow! :)

I also had a look at the Bosch code. If I go to the BMP180 page then the driver link directs me to the code for the later model BMP280 on GitHub. However, it is possible to find the BMP180 on GitHub.

So what are my best options for using this module with mikroC PRO for PIC?

User avatar
nadir.celebic
mikroElektronika team
Posts: 465
Joined: 15 Jun 2016 13:19

Re: BMP180 Temperature Sensor mikroC

#2 Post by nadir.celebic » 13 Sep 2016 16:34

Hi,

Unfortunately, we don't have at this moment example for PIC.

BMP180 and BMP085, both sensors are very similar.
But I tried to compile this project: http://libstock.mikroe.com/projects/vie ... 85-library and it works.
Also you can try this project in mikroBasic from LibStock: http://libstock.mikroe.com/projects/vie ... easurement

Regards,
Nadir

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#3 Post by nigelmercier » 14 Sep 2016 11:07

Thanks Nadir,

Yes, I've got it to compile by making a few changes.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#4 Post by nigelmercier » 15 Sep 2016 11:08

This is my first time using I2C (and indeed sbit) and I'm a bit confused. I've grabbed the example from the Software_I2C library, added the Software I2C defines from the above code and put them in an #included file named I2C.h
[UPDATE TO ABOVE]

OK, most of the errors have been fixed, I think my PORTC definitions were the problem, there is no PORTC! Perhaps the examples would be better to use PORTA?

Now OK using PORTA...

Code: Select all

// Software I2C connections required for software I2C library
sbit Soft_I2C_Scl           at RA0_bit;     // PORT A B0=I2CSCL
sbit Soft_I2C_Sda           at RA1_bit;     // PORT A B1=I2CSDA
sbit Soft_I2C_Scl_Direction at TRISA0_bit;
sbit Soft_I2C_Sda_Direction at TRISA1_bit;
...
Last edited by nigelmercier on 15 Sep 2016 14:47, edited 1 time in total.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#5 Post by nigelmercier » 15 Sep 2016 14:21

In the file BMP180.c there are the following that need to be accessed from the main module:

Code: Select all

typedef struct
{
  float Temperature;
  float Pressure;
  float Altitude;
}BMP ; 

...

void BMP_Read( char oss, BMP *Bar )
{ ... }

void BMP_Init()
{ ... }
So in my main file I #include a header file BMP180.h as follows:

Code: Select all

// Function Prototypes

void BMP_Init() ;
void BMP_Read( char oss, BMP *Bar ) ; // THIS IS LINE 4
typedef struct { float Temperature; float Pressure; float Altitude; } BMP ;
I'm getting these Build errors:

Code: Select all

4   371   Specifier needed                               bmp180.h
4   300   Syntax Error: ')' expected,  but '*' found     bmp180.h
Last edited by nigelmercier on 22 Sep 2016 11:04, edited 1 time in total.

User avatar
nadir.celebic
mikroElektronika team
Posts: 465
Joined: 15 Jun 2016 13:19

Re: BMP180 Temperature Sensor mikroC

#6 Post by nadir.celebic » 16 Sep 2016 16:37

Hi,

You can contact the author of this project for more details.

Also please check help file Software I2C Library: http://download.mikroe.com/documents/co ... ibrary.htm

Regards,
Nadir

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#7 Post by nigelmercier » 17 Sep 2016 12:19

nadir.celebic wrote:You can contact the author of this project for more details...
Hi Nadir,

[UPDATE] Errors fixed, but code not producing correct result. See posts below from Sat Sep 24, 2016

I've reduced the errors now, so I've reposted under new relevant subject Specifier needed?
Last edited by nigelmercier on 25 Sep 2016 11:33, edited 4 times in total.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#8 Post by nigelmercier » 22 Sep 2016 10:56

I've got this working, but not happy with the results from this code. Using the BMP085 Library for mikroC PRO for PIC the values returned are very odd. The returned temperature always takes the form x.9999... and the returned pressure varies by up to 1mB over a few seconds.

Is it that hard to get a version of the 10DOF Click Library for mikroC for PIC?

Failing that, as anyone got the Bosch BMP180 on GitHub to work with mikroC for PIC?

User avatar
nadir.celebic
mikroElektronika team
Posts: 465
Joined: 15 Jun 2016 13:19

Re: BMP180 Temperature Sensor mikroC

#9 Post by nadir.celebic » 23 Sep 2016 16:10

Hi,

Can you please zip and send your whole modified project?

Regards,
Nadir

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#10 Post by nigelmercier » 24 Sep 2016 16:25

nadir.celebic wrote:Can you please zip and send your whole modified project?
Hi Nadir,

[UPDATE #2] I may have fixed it, see next post.

OK, I've used the data from the example in the Bosch data sheet (attached) to force the values to be the same as the example. According to the SparkFun BMP180_Breakout Arduino Library this should be a good way to check the math, it effectively removes the BMP180 and I2C from the problem ...
[UPDATE #1] Now working with Bosch example data, but reading too high on actual pressure :(

Project attached but the main area of concern is the file that reads and converts the I2C data from the BMP180, BMP180.c (with the associated BMP180.h file and I2C.h definitions).

BMP180.c [Updated 11:07 25 September 2016]

Code: Select all

/* Adapted from LibStock http://libstock.mikroe.com/projects/view/889
   Bosch BMP Pressure Sensor Original Author: Tiago Henrique
   Blog: http://microcontrolandos.blogspot.com.br
   
   Modified by Nigel Mercier:
     Uses variable names to match datasheet and better legibility
     Unnecessary structures removed
     Calibration data load modified to linear
     Repetitive code moved to internal functions
     Files required: "BMP180.c"  "BMP180.h"  "I2C.h"
*/

#include <built_in.h>
#include "I2C.h"
// Note: #include "BMP180.h" in main module

#define CAL_DATA_ADDR         0xAA    // start address of calibration data
#define BMP_CONTROL           0xF4    // see Figure 6 in datasheet, ctrl_meas F4h (oss, sco, meas)
#define BMP_OUT_MSB           0xF6    // see Figure 6 in datasheet, out_msb
#define BMP_READTEMPCMD       0x2E
#define BMP_READPRESSURECMD   0x34

// Calibration data in E2PROM (named as in datasheet but with c suffix on B1 & B2 or redifined)
int AC1, AC2, AC3 ;
unsigned int AC4, AC5, AC6 ;
int B1c, B2c, MB, MC, MD ;           // c suffix added to B1 & B2

// Global variables for display in main function
int TrueT ;          // temperature in 0.1 degrees (named T in datasheet) so 20deg = 200
long TrueP ;         // pressure in Pa (named P in datasheet) so 1013 hPa = 101300
// Global for debug purposes
int UT ;                    // uncompensated value of temperature
long UP ;                   // uncompensated value of pressure

// Internal functions
void delayOss (char oss)
{ // delay depending on oversampling oss 0 to 3, approximates to 2x^2 + x + 5
  char i, do1mS ;
  do1mS = 2*oss*oss + oss + 5 ; // (0, 1, 2, or 3 gives 5, 8, 15, or 26)
  for (i = 0 ; i < do1mS ; i++)
    Delay_ms(1) ;
}

int BMP_I2C_Rd16b (char ackm)
{ // return MSB<<8 + LSB, send ACKM if parameter ackm is 1, NACKM if ackm 0
  return ( (BMP_I2C_Rd(1) << 8) + BMP_I2C_Rd(ackm) ) ;
}

void BMP_I2C_SetU( char reg )
{ // setup for read of UT or UP, do delay on return
  BMP_I2C_Start();
  BMP_I2C_Wr( I2C_ADDR_WR );
  BMP_I2C_Wr( BMP_CONTROL );          // 0xF4
  BMP_I2C_Wr( reg );                  // write 0x2E or 0x34 into reg 0xF4
  BMP_I2C_Stop();
}

void BMP_I2C_SetReg( char reg )
{ // setup for read of calibration data 0xAA, or UT/UP data 0xF6
  BMP_I2C_Start();                // start condition
  BMP_I2C_Wr( I2C_ADDR_WR );      // module address write command 0xEE
  BMP_I2C_Wr( reg );              // select read register (calibration data 0xAA, UT/UP data 0xF6)
  BMP_I2C_Start();                // restart condition
  BMP_I2C_Wr( I2C_ADDR_RD );      // module address read command 0xEF
}

// Global functions
void BMP_Read( char oss )
{// read uncompensated values UT & UP, convert to true, save in global variables: TrueT & TrueP
  long B3, B5, B6, X1, X2, X3, pp ;
  unsigned long B4, B7;
  
  // read uncompensated value UT
  BMP_I2C_SetU( BMP_READTEMPCMD ) ;                  // write 0x2E into reg 0xF4: setup for UT
  Delay_ms( 5 ) ;                                    // delay 4.5mS minimum
  BMP_I2C_SetReg ( BMP_OUT_MSB ) ;                   // select read register start 0xF6
  UT = BMP_I2C_Rd16b(0) ;                            // read 16 bits into UT, send NACKM
  BMP_I2C_Stop() ;                                   // stop
  
  // DEBUG Example from Bosch datasheet
  // UT = 27898 ;
  
  // read uncompensated value UP
  BMP_I2C_SetU( BMP_READPRESSURECMD | (oss << 6) ) ; // write 0x34 into reg 0xF4: setup for UP
  delayOss( oss ) ;                                  // delay depends on oss
  BMP_I2C_SetReg( BMP_OUT_MSB ) ;                    // select read register start 0xF6
  UP = BMP_I2C_Rd16b(1) ;                            // read MSB + LSB into UP, send ACKM
  UP = UP<<8 | BMP_I2C_Rd(0) ;                       // read XLSB into UP, send NACKM
  UP = UP>>(8-oss) ;                                 // adjust for oss
  BMP_I2C_Stop() ;                                   // stop
  
  // DEBUG Example from Bosch datasheet
  // UP = 23843;
   
  //Calculate True Temperature
  X1 = (( (long)UT - (long)AC6)*(long)AC5) >> 15 ;
  X2 = ( (long)MC << 11)/(X1 + MD) ;
  B5 = X1 + X2 ;                       // long B5 used in calculation of True Pressure
  TrueT = ( (B5 + 8) >> 4 ) ;          // TrueT is temperature in 0.1 degrees

  //Calculate True Pressure [SOMETHING WRONG IN THIS BIT!]
  // Calculate B6
  B6 = B5 - 4000 ;
  // Calculate B3
  X1 = ((long)B2c * (long)(B6*B6)>>12) >>11 ;
  X2 = ((long)AC2 * (long)B6) >>11 ;
  X3 = X1 + X2 ;
  B3 = ((( (long)AC1*4 + X3) <<oss) + 2) >>2 ; [UPDATED, now working with Bosch data]
  // Calculate B4
  X1 = (AC3 * B6) >>13 ;
  X2 = (B1c * ((B6 * B6)>>12)) >>16 ;
  X3 = ((X1 + X2) + 2 ) >>2 ;
  B4 = (AC4 * (unsigned long)(X3 + 32768)) >>15 ;

  B7 = ((unsigned long)(UP - B3) * (unsigned long)(50000 >>oss)) ;
  if( B7 < 0x80000000 )
  { pp = ((B7 <<1) / B4) ; }
  else
  { pp = ((B7 / B4) <<1) ; }

  X1 = (pp >>8)*(pp >>8) ;
  X1 = (X1 * 3038) >>16;                   // LibStock original says * 1519, Bosch datasheet says 3038 (twice!)
  X2 = (-7357 * pp) >>16;
  TrueP = pp + ((X1 + X2 + 3791) >>4) ;   // pressure in Pa 101300
}

void BMP_Init()
{
  BMP_I2C_SetReg ( CAL_DATA_ADDR ) ; // select read register at start of calibration data 0xAA
  // load up calibration data
  AC1 = (int)BMP_I2C_Rd16b(1) ;
  AC2 = (int)BMP_I2C_Rd16b(1) ;
  AC3 = (int)BMP_I2C_Rd16b(1) ;
  AC4 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC5 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC6 = (unsigned int)BMP_I2C_Rd16b(1) ;
  B1c  = (int)BMP_I2C_Rd16b(1) ;
  B2c  = (int)BMP_I2C_Rd16b(1) ;
  MB  = (int)BMP_I2C_Rd16b(1) ;
  MC  = (int)BMP_I2C_Rd16b(1) ;
  MD  = (int)BMP_I2C_Rd16b(0) ; // send NACKM before stop
  BMP_I2C_Stop();
  
  // DEBUG Example from Bosch datasheet
  // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
  // B1c = 6190; B2c = 4; MB = -32768; MC = -8711; MD = 2868;
}
BMP180.h

Code: Select all

// Function Prototypes
void BMP_Init() ;
void BMP_Read( char oss );

// Global variables
extern int TrueT ;          // temperature in 0.1 degrees
extern long TrueP ;         // pressure in Pa

extern int UT ;       // (global for DEBUG) uncompensated value of temperature
extern long UP ;      // (global for DEBUG) uncompensated value of pressure
I2C.h

Code: Select all

// Software I2C connections required for software I2C library

sbit Soft_I2C_Scl           at RA0_bit;     // PORT A B0=I2CSCL
sbit Soft_I2C_Sda           at RA1_bit;     // PORT A B1=I2CSDA
sbit Soft_I2C_Scl_Direction at TRISA0_bit;
sbit Soft_I2C_Sda_Direction at TRISA1_bit;

// use software I2C port
#define BMP_I2C_Rd         Soft_I2C_Read
#define BMP_I2C_Start      Soft_I2C_Start
#define BMP_I2C_Stop       Soft_I2C_Stop
#define BMP_I2C_Wr         Soft_I2C_Write

#define BMP_Scl            Soft_I2C_Scl
#define BMP_Sda            Soft_I2C_Sda
#define BMP_Scl_Direction  Soft_I2C_Scl_Direction
#define BMP_Sda_Direction  Soft_I2C_Sda_Direction

#define I2C_ADDR_WR    0xEE       // I2C address of BMP180 module for write operations
#define I2C_ADDR_RD    0xEF       // I2C address of BMP180 module for read operations
The rest of the modules are for control and display. At present I am getting a reading of 246 for true temperature (24.6 degrees, so about right) but I've got 87914 for true pressure (879.14hPa) which is very low.
Attachments
Barograph MK2.zip
(705.29 KiB) Downloaded 306 times
BST-BMP180-DS000-09 Flowchart.pdf
(175.41 KiB) Downloaded 347 times
Last edited by nigelmercier on 25 Sep 2016 12:38, edited 14 times in total.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#11 Post by nigelmercier » 25 Sep 2016 10:36

I may have fixed it.
My original code for final calculation of TrueP ...

Code: Select all

  TrueP = pp + ((X1 + X2 + 3791) >>4) ;   // pressure in Pa 101300
New code that gives more sensible result ...

Code: Select all

  TrueP = pp + (X1 + X2 + 3791) >>4 ;     // pressure in Pa 101300

User avatar
nadir.celebic
mikroElektronika team
Posts: 465
Joined: 15 Jun 2016 13:19

Re: BMP180 Temperature Sensor mikroC

#12 Post by nadir.celebic » 26 Sep 2016 16:18

Hi,

Did you solve the problem?

Regards,
Nadir

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#13 Post by nigelmercier » 26 Sep 2016 16:39

nadir.celebic wrote:Did you solve the problem?
I need to double check against a calibrated source, but the readings now seem correct.

It does mean that the code on LibStock is faulty, when I've finished adjusting I'll zip some files up and upload them.

nigelmercier
Posts: 316
Joined: 23 Oct 2008 09:36

Re: BMP180 Temperature Sensor mikroC

#14 Post by nigelmercier » 27 Sep 2016 11:18

Hi Nadir,

There is one thing still bugging me. The Bosch datasheet says that the true pressure is returned in Pa, so standard air pressure of 1013hPa should be a long integer of value 101300. I'm getting 10130.

User avatar
nadir.celebic
mikroElektronika team
Posts: 465
Joined: 15 Jun 2016 13:19

Re: BMP180 Temperature Sensor mikroC

#15 Post by nadir.celebic » 27 Sep 2016 16:35

Hi,

There is a chance that the example project from LibStock has errors,
because it is not official MikroElektronika example project,
and therefore we can't provide detailed help for the code itself.

But your problem is in the calculation.
You can set Pa, hPa or mbar.
1 mbar = 1 hPa = 100 Pa

Regards,
Nadir

Post Reply

Return to “mikroC PRO for PIC General”