ads1115 analog-to-digital 4-channel added
[i2c-telemetry.git] / bmp085.c
1 /*
2  Sample code for the BMP085
3  */
4 #include <stdio.h>
5 #include <stdint.h>
6 #include <fcntl.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <linux/i2c-dev.h>
10 #include <linux/i2c.h>
11 #include <sys/ioctl.h>
12 #include "smbus.h"
13
14 #define BMP085_I2C_ADDRESS 0x77
15
16 const unsigned char BMP085_OVERSAMPLING_SETTING = 3;
17
18 // Calibration values - These are stored in the BMP085
19 short int ac1;
20 short int ac2;
21 short int ac3;
22 unsigned short int ac4;
23 unsigned short int ac5;
24 unsigned short int ac6;
25 short int b1;
26 short int b2;
27 short int mb;
28 short int mc;
29 short int md;
30
31 int b5;
32
33 unsigned int temperature, pressure;
34
35
36 // Open a connection to the bmp085
37 // Returns a file id
38 int bmp085_i2c_Begin()
39 {
40         int fd;
41         char *fileName = "/dev/i2c-0";
42
43         // Open port for reading and writing
44         if ((fd = open(fileName, O_RDWR)) < 0)
45                 exit(1);
46
47         // Set the port options and set the address of the device
48         if (ioctl(fd, I2C_SLAVE, BMP085_I2C_ADDRESS) < 0) {
49                 close(fd);
50                 exit(1);
51         }
52
53         return fd;
54 }
55
56 // Read two words from the BMP085 and supply it as a 16 bit integer
57 __s32 bmp085_i2c_Read_Int(int fd, __u8 address)
58 {
59         __s32 res = i2c_smbus_read_word_data(fd, address);
60         if (res < 0) {
61                 close(fd);
62                 exit(1);
63         }
64
65         // Convert result to 16 bits and swap bytes
66         res = ((res<<8) & 0xFF00) | ((res>>8) & 0xFF);
67
68         return res;
69 }
70
71 //Write a byte to the BMP085
72 void bmp085_i2c_Write_Byte(int fd, __u8 address, __u8 value)
73 {
74         if (i2c_smbus_write_byte_data(fd, address, value) < 0) {
75                 close(fd);
76                 exit(1);
77         }
78 }
79
80 // Read a block of data BMP085
81 void bmp085_i2c_Read_Block(int fd, __u8 address, __u8 length, __u8 *values)
82 {
83         if(i2c_smbus_read_i2c_block_data(fd, address,length,values)<0) {
84                 close(fd);
85                 exit(1);
86         }
87 }
88
89
90 void bmp085_Calibration()
91 {
92         int fd = bmp085_i2c_Begin();
93         ac1 = bmp085_i2c_Read_Int(fd,0xAA);
94         ac2 = bmp085_i2c_Read_Int(fd,0xAC);
95         ac3 = bmp085_i2c_Read_Int(fd,0xAE);
96         ac4 = bmp085_i2c_Read_Int(fd,0xB0);
97         ac5 = bmp085_i2c_Read_Int(fd,0xB2);
98         ac6 = bmp085_i2c_Read_Int(fd,0xB4);
99         b1 = bmp085_i2c_Read_Int(fd,0xB6);
100         b2 = bmp085_i2c_Read_Int(fd,0xB8);
101         mb = bmp085_i2c_Read_Int(fd,0xBA);
102         mc = bmp085_i2c_Read_Int(fd,0xBC);
103         md = bmp085_i2c_Read_Int(fd,0xBE);
104         close(fd);
105 }
106
107 // Read the uncompensated temperature value
108 unsigned int bmp085_ReadUT()
109 {
110         unsigned int ut = 0;
111         int fd = bmp085_i2c_Begin();
112
113         // Write 0x2E into Register 0xF4
114         // This requests a temperature reading
115         bmp085_i2c_Write_Byte(fd,0xF4,0x2E);
116
117         // Wait at least 4.5ms
118         usleep(5000);
119
120         // Read the two byte result from address 0xF6
121         ut = bmp085_i2c_Read_Int(fd,0xF6);
122
123         // Close the i2c file
124         close (fd);
125
126         return ut;
127 }
128
129 // Read the uncompensated pressure value
130 unsigned int bmp085_ReadUP()
131 {
132         unsigned int up = 0;
133         int fd = bmp085_i2c_Begin();
134
135         // Write 0x34+(BMP085_OVERSAMPLING_SETTING<<6) into register 0xF4
136         // Request a pressure reading w/ oversampling setting
137         bmp085_i2c_Write_Byte(fd,0xF4,0x34 + (BMP085_OVERSAMPLING_SETTING<<6));
138
139         // Wait for conversion, delay time dependent on oversampling setting
140         usleep((2 + (3<<BMP085_OVERSAMPLING_SETTING)) * 1000);
141
142         // Read the three byte result from 0xF6
143         // 0xF6 = MSB, 0xF7 = LSB and 0xF8 = XLSB
144         __u8 values[3];
145         bmp085_i2c_Read_Block(fd, 0xF6, 3, values);
146
147         up = (((unsigned int) values[0] << 16) | ((unsigned int) values[1] << 8) | (unsigned int) values[2]) >> (8-BMP085_OVERSAMPLING_SETTING);
148
149         return up;
150 }
151
152 // Calculate pressure given uncalibrated pressure
153 // Value returned will be in units of XXXXX
154 unsigned int bmp085_GetPressure(unsigned int up)
155 {
156         int x1, x2, x3, b3, b6, p;
157         unsigned int b4, b7;
158
159         b6 = b5 - 4000;
160         // Calculate B3
161         x1 = (b2 * (b6 * b6)>>12)>>11;
162         x2 = (ac2 * b6)>>11;
163         x3 = x1 + x2;
164         b3 = (((((int)ac1)*4 + x3)<<BMP085_OVERSAMPLING_SETTING) + 2)>>2;
165
166         // Calculate B4
167         x1 = (ac3 * b6)>>13;
168         x2 = (b1 * ((b6 * b6)>>12))>>16;
169         x3 = ((x1 + x2) + 2)>>2;
170         b4 = (ac4 * (unsigned int)(x3 + 32768))>>15;
171
172         b7 = ((unsigned int)(up - b3) * (50000>>BMP085_OVERSAMPLING_SETTING));
173         if (b7 < 0x80000000)
174                 p = (b7<<1)/b4;
175         else
176                 p = (b7/b4)<<1;
177
178         x1 = (p>>8) * (p>>8);
179         x1 = (x1 * 3038)>>16;
180         x2 = (-7357 * p)>>16;
181         p += (x1 + x2 + 3791)>>4;
182
183         return p;
184 }
185
186 // Calculate temperature given uncalibrated temperature
187 // Value returned will be in units of 0.1 deg C
188 unsigned int bmp085_GetTemperature(unsigned int ut)
189 {
190         int x1, x2;
191
192         x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15;
193         x2 = ((int)mc << 11)/(x1 + md);
194         b5 = x1 + x2;
195
196         unsigned int result = ((b5 + 8)>>4);  
197
198         return result;
199 }
200
201 int main(int argc, char **argv)
202 {
203         bmp085_Calibration();
204         temperature = bmp085_GetTemperature(bmp085_ReadUT());
205         pressure = bmp085_GetPressure(bmp085_ReadUP());
206
207         printf("Temperature (C)\t\t%0.1f\n", ((double)temperature)/10);
208         printf("Pressure (mBar)\t%0.2f\n", ((double)pressure)/100);
209         // printf("Pressure (mmHg)\t%0.2f\n", ((double)pressure)/100*0.75006375541921);
210         // printf("Pressure (mmHg)\t\t%0.2f\n", ((double)pressure)/100*0.750061683);
211         return 0;
212 }