RetroBSD

2.11BSD operating system for microcontrollers
It is currently Tue Apr 07, 2020 8:08 am

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Barometer - BMP085 (i2c)
PostPosted: Sat Sep 26, 2015 8:15 pm 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Attached the Barometer for retrobsd.
A barometer is a scientific instrument used in meteorology to measure atmospheric pressure (from Wikipedia).
Based on BMP085 chip, uses the bitbanged I2C (with delays).
It shows absolute pressure only. We need floating point to get something better :)
Temperature in 0.1 degC.

Code:
# cc -o bmp085 BMP085rd.c
# ./bmp085
T= 239 x0.1C
p(abs)= 99423 Pa
# ./bmp085
T= 239 x0.1C
p(abs)= 99436 Pa
# ./bmp085
T= 239 x0.1C
p(abs)= 99425 Pa
# ./bmp085
T= 239 x0.1C
p(abs)= 99424 Pa
# date
Sat Sep 26 22:19:24 MET 2015
# ./bmp085
T= 239 x0.1C
p(abs)= 99433 Pa
#


Attachments:
BMP085_barometer.zip [2.76 KiB]
Downloaded 421 times

_________________
Pukao Hats Cleaning Services Ltd.
Top
 Profile  
 
PostPosted: Sat Sep 26, 2015 9:51 pm 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
I believe simple fixed-point arithmetic could help.


Top
 Profile  
 
PostPosted: Sat Sep 26, 2015 10:01 pm 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
For example:
Code:
float readAltitude(float pressure, float sealevelPressure) {
  float altitude;
  altitude = 44330.0 * (1.0 - pow(pressure /sealevelPressure, 0.19029495));
return altitude;
}

float readp0(float myAltitude, float pressure) {
  float p0;
  p0 = pressure / pow((1.0 - ( myAltitude / 44330.0 )), 5.255);
return p0;
}

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sat Sep 26, 2015 10:37 pm 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Code:
float readp0(float myAltitude, float abspressure) {
  float p0;
  p0 = abspressure / pow((1.0 - ( myAltitude / 44330.0 )), 5.255);
return p0;
}

That could be simplified for my altitude 235m:
Code:
//p0 = abs_pressure*1.0283;

   p0 = (abspressure * 10283) / 10000;
   printf("p0= %d Pa\r\n", p0);


Code:
# cc -o bmp085 BMP085rd.c
# ./bmp085
T= 239 x0.1C
p(abs)= 99472 Pa
p0= 102287 Pa
#

1023hPa is the pressure I can see at nearby meteostation's web (airfield).
When I touch the sensor for a few seconds:
Code:
# ./bmp085
T= 289 x0.1C
p(abs)= 99478 Pa
p0= 102293 Pa
# ./bmp085
T= 247 x0.1C
p(abs)= 99480 Pa
p0= 102295 Pa
#

So it seems it works :)

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sat Sep 26, 2015 11:29 pm 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Another option for Smaller C right now would be to take the 32-bit binary representation of your float constants and construct calls to floating-point arithmetic functions using ints. This is ugly, but should work.

Code:
#if 0
float pow(float, float); // double = float

float readAltitude(float pressure, float sealevelPressure) {
  return 44330.0f * (1.0f - pow(pressure / sealevelPressure, 0.19029495f));
}

float readp0(float myAltitude, float pressure) {
  return pressure / pow((1.0f - (myAltitude / 44330.0f)), 5.255f);
}

#else

// 32-bit soft float
int pow(int, int);
int __divsf3(int, int);
int __subsf3(int, int);
int __mulsf3(int, int);
// etc

int readAltitude(int pressure, int sealevelPressure) {
  return __mulsf3(0x472D2A00, __subsf3(0x3F800000, pow(__divsf3(pressure, sealevelPressure), 0x3E42DCAE)));
}

int readp0(int myAltitude, int pressure) {
  return __divsf3(pressure, pow(__subsf3(0x3F800000, __divsf3(myAltitude, 0x472D2A00)), 0x40A828F6));
}
#endif


The two should be equivalent in terms of machine code.

P.S. I have not tried the above.


Top
 Profile  
 
PostPosted: Sat Sep 26, 2015 11:52 pm 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
How is the pow call in the lib (libm)?
pow or _pow or __pow or __powf??

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:02 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Pito wrote:
How is the pow call in the lib (libm)?
pow or _pow or __pow or __powf??


Should be just pow. And you might need to tell cc to link in the math library, add "-lm" without the quotes at the end of the cc command.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:09 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Code:
cc -o bmp085 BMP085rd.c -lm
ld: /lib/libm.a: cannot open
# cd lib
# ls
crt0.o         libcurses.a    libtermlib.a   retroImage
libc.a         libreadline.a  libwiznet.a

If you have it handy post it plz..

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:29 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Looks like libm.a is compiled, but not installed/copied. Serge should fix something in the scripts.
No guarantee that mine works.


Last edited by alexfru on Sun Sep 27, 2015 2:09 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:35 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Code:
# cc -o bmp BMP085rd.c -lm
ld: /lib/libm.a: bad magic
#

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:57 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Sorry, that was a regular library used when cross-compiling on the host. Looks like there's no Makefile for the target version of libm.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 2:04 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Try this libm.a.

Code:
// fp.c
#include <stdio.h>

// 32-bit soft float
int pow(int, int);
int __divsf3(int, int);
int __subsf3(int, int);
int __mulsf3(int, int);
int __addsf3(int, int);

#define F1_0 0x3F800000

int main(void)
{
  int two = __addsf3(F1_0, F1_0);
  int four = __mulsf3(two, two);
  int sixteen = pow(two, four);
  printf("two:%f four:%f sixteen:%f\n", two, four, sixteen);
  return 0;
}


Quote:
# cc fp.c -o fp -lm
# ./fp
two:2.000000 four:4.000000 sixteen:15.999999


Last edited by alexfru on Mon Sep 28, 2015 6:13 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 6:50 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Code:
# cc -o bmp085  BMP085rd.c -lm
ld: /lib/libm.a: out of date (warning)
# ./bmp085
T= 235 x0.1C
p(abs)= 99686 Pa
p0= 102507 Pa
p0= 102499.382813 Pa
#

But with :)
Code:
#define F1_0 0x3F800000
#define F44330_0    0x472D2A00
#define F5_255       0x40A828F6
#define F235_0       0x436B0000
#define F99676_0    0x47C2AE00

// 32-bit soft float
int pow(int, int);
int __divsf3(int, int);
int __subsf3(int, int);
int __mulsf3(int, int);
int __addsf3(int, int);

int readp0(int myAltitude, int pressure) {
return __divsf3(pressure, pow(__subsf3(F1_0, __divsf3(myAltitude, F44330_0)), F5_255));
   }

int main ()
{

   int ut, up, temperature, abspressure, p0;   
   
   // init the pins driver !!
   if (pinsinit() < 0) return -1;
   // init i2c driver
   I2CInit();
   
   BMP085_Calibration();
   
   ut = BMP085_ReadUT();
   up = BMP085_ReadUP();
   
   //printf("ut= %d \r\n", ut);
   //printf("up= %d \r\n", up);

   temperature = BMP085_GetTemperature(ut);
   abspressure = BMP085_GetPressure(up, ut);
   
   printf("T= %d x0.1C\r\n", temperature);
   printf("p(abs)= %d Pa\r\n", abspressure);
   
   p0 = (abspressure * 10283) / 10000;
   printf("p0= %d Pa\r\n", p0);   

   p0 = readp0(F235_0, F99676_0);
   printf("p0= %f Pa\r\n", p0);

So we still need to convert int into float somehow :evil:
Maybe there is a conversion routine in the libm or elswere we can utilize via a call..
BTW the difference in size is plus 2.8kB when the above float calls are used.

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 8:14 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
The dirtiest of hacks I've ever done (freely based on the Babbage engine's No.2 adder subengine):

Code:
..
int readp0(int myAltitude, int pressure) {
return __divsf3(pressure, pow(__subsf3(F1_0, __divsf3(myAltitude, F44330_0)), F5_255));
   }
   
unsigned int uint2float(unsigned int x) {
   unsigned int i, res;
   res = 0;
   if (x == 0 ) return 0;
   for(i=0; i<x; i++ )  res = __addsf3(res, F1_0);
   return res;
}
..   
   p0 = (abspressure * 10283) / 10000;
   printf("p0= %d Pa\r\n", p0);   

   p0 = readp0(uint2float(235), uint2float(abspressure));
   printf("p0= %f Pa\r\n", p0);
   

Code:
# ./bmp085
T= 237 x0.1C
p(abs)= 99749 Pa
p0= 102571 Pa
p0= 102574.445313 Pa
# ./bmp085
T= 237 x0.1C
p(abs)= 99734 Pa
p0= 102556 Pa
p0= 102559.023438 Pa
# ./bmp085
T= 237 x0.1C
p(abs)= 99743 Pa
p0= 102565 Pa
p0= 102568.281250 Pa
#

:x
PS: Excel shows 102568.26 with the last p0 calc..

Code:
# ./bmp085
T= 236 x0.1C
p(abs)= 99770 Pa
p0= 102593 Pa
p0= 102596.039063 Pa
#

The nearby airfield reports 1026hPa.

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 9:33 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
Pito wrote:
So we still need to convert int into float somehow :evil:
Maybe there is a conversion routine in the libm or elswere we can utilize via a call..


Code:
int __fixsfsi(int);
int __floatsisf(int);

#define F1_0 0x3F800000
...
  printf("one:%d one:%f\n", __fixsfsi(F1_0), __floatsisf(1));


Quote:
one:1 one:1.000000


However, our libm lacks conversion between unsigned int and float. I've mentioned this before.

Pito wrote:
BTW the difference in size is plus 2.8kB when the above float calls are used.


When Serge adds libm.a in one of the next auto builds, it should be somewhat smaller. The compiler he's using is better than the one I'm using. I guess, the warning should also go away (my repository is a couple of commits older than the current).


Top
 Profile  
 
PostPosted: Sun Sep 27, 2015 12:18 pm 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
Code:
#define F1_0       0x3F800000
#define F44330_0    0x472D2A00
#define F5_255       0x40A828F6

// 32-bit soft float - direct calls to libm
int pow(int, int);
int __divsf3(int, int);
int __subsf3(int, int);
int __mulsf3(int, int);
int __addsf3(int, int);
int __fixsfsi(int);
int __floatsisf(int);

#define POW pow
#define DIV __divsf3
#define SUB __subsf3
#define MUL __mulsf3
#define ADD __addsf3
#define I2F __floatsisf
#define F2I __fixsfsi

int readp0(int myAltitude, int pressure) {
return DIV(pressure, POW( SUB(F1_0, DIV(myAltitude, F44330_0)), F5_255));
   }
.. 
   p0 = (abspressure * 10283) / 10000;
   printf("p0= %d Pa\r\n", p0);   
   
   myaltitude = 235; //meters above sea

   // p0 - the station pressure adjusted to sea level, reported by weather services
   p0 = readp0(I2F(myaltitude), I2F(abspressure));
   printf("p0= %f Pa\r\n", p0);
..

Code:
# cc -o bmp085  BMP085rd.c -lm
ld: /lib/libm.a: out of date (warning)
# ./bmp085
T= 236 x0.1C
p(abs)= 99792 Pa
p0= 102616 Pa
p0= 102618.664063 Pa
# ./bmp085
T= 236 x0.1C
p(abs)= 99786 Pa
p0= 102609 Pa
p0= 102612.492188 Pa
#

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Mon Sep 28, 2015 6:10 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
With v384 (libm installed) it seems it works fine:
Code:
# cc -o bmp BMP085rd.c -lm
# ./bmp
T= 230 x0.1C
p(abs)= 100103 Pa
p0= 102935 Pa
p0= 102938.476563 Pa
#

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Mon Sep 28, 2015 6:42 pm 
Committer
User avatar

Joined: Wed Oct 10, 2012 11:01 pm
Posts: 1081
Location: Sunnyvale, CA
Looks nice.
Which module do you use, Pito?
Something like this, GY-80?
I can find it for $9 on AliExpress.
Image

As I can see from the datasheet, the accuracy of BMP085 is no better than 0.1%, or ±100 Pa. So it makes little sense to compute and print more that 5 digits.
Code:
p0= 102930 ± 100 Pa


Top
 Profile  
 
PostPosted: Tue Sep 29, 2015 5:37 am 
Contributor
User avatar

Joined: Thu Nov 08, 2012 7:04 am
Posts: 2401
Location: Rapa Nui
I am using that module on the above picture..
You can improve precision with pure floating point calcs. Btw, I did 30cm altitude resolution long time back (averaging, smoothing..)

_________________
Pukao Hats Cleaning Services Ltd.


Top
 Profile  
 
PostPosted: Tue Sep 29, 2015 5:59 am 
Committer
User avatar

Joined: Wed Oct 10, 2012 11:01 pm
Posts: 1081
Location: Sunnyvale, CA
OK, I'll order this module to be able to run your examples.

The precision of the measured value is defined by the BMP085 chip. It gives relative error from ±0.1% to ±0.3%. See the datasheet.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
cron




Powered by phpBB® Forum Software © phpBB Group

BSD Daemon used with permission