Many changes from 2018
[owSlave2.git] / common / I2C / BMP280.c
1 #define F_CPU 8000000UL\r
2 #include <avr/io.h>\r
3 #include <avr/interrupt.h>\r
4 #include <util/delay.h>\r
5 #include <avr/wdt.h>\r
6 #include <avr/sleep.h>\r
7 #include "TWI_Master.h"\r
8 \r
9 uint16_t dig_T1;\r
10 int16_t dig_T2;\r
11 int16_t dig_T3;\r
12 uint16_t dig_P1;\r
13 int16_t dig_P2;\r
14 int16_t dig_P3;\r
15 int16_t dig_P4;\r
16 int16_t dig_P5;\r
17 int16_t dig_P6;\r
18 int16_t dig_P7;\r
19 int16_t dig_P8;\r
20 int16_t dig_P9;\r
21 \r
22 \r
23 \r
24 \r
25 short bmp280ReadShort(unsigned char address)\r
26 {\r
27         char msb, lsb;\r
28         short data;\r
29         I2c_StartCondition();\r
30         I2c_WriteByte(0xEC);\r
31         I2c_WriteByte(address);\r
32         I2c_StopCondition();\r
33         I2c_StartCondition();\r
34         I2c_WriteByte(0xED);\r
35         lsb=I2c_ReadByte(ACK);\r
36         msb=I2c_ReadByte(NO_ACK);\r
37         I2c_StopCondition();\r
38         \r
39 \r
40         \r
41         data = msb << 8;\r
42         data |= lsb;\r
43         \r
44         return data;\r
45 }\r
46 \r
47 void bmp280Init(void) {\r
48         I2c_StartCondition();\r
49         I2c_WriteByte(0xEC);\r
50         I2c_WriteByte(0xF4);\r
51         I2c_WriteByte(0b01010111); //2x Temp over 16x Press over   Normal mode\r
52         I2c_WriteByte(0b11100000);  //4s time / no IIfilter\r
53         I2c_StopCondition();\r
54         dig_T1=bmp280ReadShort(0x88);\r
55         dig_T2=bmp280ReadShort(0x8A);\r
56         dig_T3=bmp280ReadShort(0x8C);\r
57         dig_P1=bmp280ReadShort(0x8E);\r
58         dig_P2=bmp280ReadShort(0x90);\r
59         dig_P3=bmp280ReadShort(0x92);\r
60         dig_P4=bmp280ReadShort(0x94);\r
61         dig_P5=bmp280ReadShort(0x96);\r
62         dig_P6=bmp280ReadShort(0x98);\r
63         dig_P7=bmp280ReadShort(0x9A);\r
64         dig_P8=bmp280ReadShort(0x9C);\r
65         dig_P9=bmp280ReadShort(0x9E);\r
66         \r
67         \r
68         \r
69 }\r
70 int32_t bmp280ReadTemp(void) {\r
71         uint8_t msb, lsb,xlsb;\r
72         volatile int32_t data;\r
73         I2c_StartCondition();\r
74         I2c_WriteByte(0xEC);\r
75         I2c_WriteByte(0xFA);\r
76         I2c_StopCondition();\r
77         I2c_StartCondition();\r
78         I2c_WriteByte(0xED);\r
79         msb=I2c_ReadByte(ACK);\r
80         lsb=I2c_ReadByte(ACK);\r
81         xlsb=I2c_ReadByte(NO_ACK);\r
82         I2c_StopCondition();\r
83                 \r
84         data = (int32_t)msb << 12;\r
85         data |= (int16_t)lsb<<4;\r
86         data|=xlsb>>4;\r
87                 \r
88                 return data;\r
89 \r
90         \r
91 }\r
92 int32_t bmp280ReadPressure(uint8_t oss) {\r
93                 uint8_t msb, lsb,xlsb;\r
94                 volatile int32_t data;\r
95                 I2c_StartCondition();\r
96                 I2c_WriteByte(0xEC);\r
97                 I2c_WriteByte(0xF7);\r
98                 I2c_StopCondition();\r
99                 I2c_StartCondition();\r
100                 I2c_WriteByte(0xED);\r
101                 msb=I2c_ReadByte(ACK);\r
102                 lsb=I2c_ReadByte(ACK);\r
103                 xlsb=I2c_ReadByte(NO_ACK);\r
104                 I2c_StopCondition();\r
105                 \r
106                 data = (int32_t)msb << 12;\r
107                 data |= (int16_t)lsb<<4;\r
108                 data|=xlsb>>4;\r
109                 \r
110                 return data;\r
111 \r
112 \r
113 }\r
114 \r
115 int32_t bmp280ReadPressure_simple() {\r
116                 uint8_t msb, lsb,xlsb;\r
117                 volatile int32_t data;\r
118                 I2c_StartCondition();\r
119                 I2c_WriteByte(0xEC);\r
120                 I2c_WriteByte(0xF7);\r
121                 I2c_StopCondition();\r
122                 I2c_StartCondition();\r
123                 I2c_WriteByte(0xED);\r
124                 msb=I2c_ReadByte(ACK);\r
125                 lsb=I2c_ReadByte(ACK);\r
126                 xlsb=I2c_ReadByte(NO_ACK);\r
127                 I2c_StopCondition();\r
128                 \r
129                 data = (int32_t)msb << 12;\r
130                 data |= (int16_t)lsb<<4;\r
131                 data|=xlsb>>4;\r
132                 \r
133                 return data;\r
134 \r
135 \r
136 }\r
137 #define BMP280_S32_t int32_t\r
138 // Returns temperature in DegC, double precision. Output value of \9351.23\94 equals 51.23 DegC.\r
139 // t_fine carries fine temperature as global value\r
140 BMP280_S32_t t_fine;\r
141 double bmp280_compensate_T_double(BMP280_S32_t adc_T)\r
142 {\r
143         double var1, var2, T;\r
144         var1 = (((double)adc_T)/16384.0 - ((double)dig_T1)/1024.0) * ((double)dig_T2);\r
145         var2 = ((((double)adc_T)/131072.0 - ((double)dig_T1)/8192.0) *\r
146         (((double)adc_T)/131072.0 - ((double) dig_T1)/8192.0)) * ((double)dig_T3);\r
147         t_fine = (BMP280_S32_t)(var1 + var2);\r
148         T = (var1 + var2) / 5120.0;\r
149         return T;\r
150 }\r
151 // Returns pressure in Pa as double. Output value of \9396386.2\94 equals 96386.2 Pa = 963.862 hPa\r
152 double bmp280_compensate_P_double(BMP280_S32_t adc_P)\r
153 {\r
154         double var1, var2, p;\r
155         var1 = ((double)t_fine/2.0) - 64000.0;\r
156         var2 = var1 * var1 * ((double)dig_P6) / 32768.0;\r
157         var2 = var2 + var1 * ((double)dig_P5) * 2.0;\r
158         var2 = (var2/4.0)+(((double)dig_P4) * 65536.0);\r
159         var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;\r
160         var1 = (1.0 + var1 / 32768.0)*((double)dig_P1);\r
161         if (var1 == 0.0)\r
162         {\r
163                 return 0; // avoid exception caused by division by zero\r
164         }\r
165         p = 1048576.0 - (double)adc_P;\r
166         p = (p - (var2 / 4096.0)) * 6250.0 / var1;\r
167         var1 = ((double)dig_P9) * p * p / 2147483648.0;\r
168         var2 = p * ((double)dig_P8) / 32768.0;\r
169         p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;\r
170         return p;\r
171 }\r
172 \r
173 void bmp280ConvertInt_df(int32_t * temperature,uint32_t *pressure,uint8_t oss) {\r
174                 //bmp280Init();\r
175                 double var1, var2, T;\r
176                 int32_t adc_T=bmp280ReadTemp();\r
177                 var1 = (((double)adc_T)/16384.0 - ((double)dig_T1)/1024.0) * ((double)dig_T2);\r
178                 var2 = ((((double)adc_T)/131072.0 - ((double)dig_T1)/8192.0) *\r
179                 (((double)adc_T)/131072.0 - ((double) dig_T1)/8192.0)) * ((double)dig_T3);\r
180                 t_fine = (BMP280_S32_t)(var1 + var2);\r
181                 T = (var1 + var2) / 5120.0;\r
182 \r
183                 int32_t adc_P= bmp280ReadPressure(oss);\r
184                 double  p;\r
185                 var1 = ((double)t_fine/2.0) - 64000.0;\r
186                 var2 = var1 * var1 * ((double)dig_P6) / 32768.0;\r
187                 var2 = var2 + var1 * ((double)dig_P5) * 2.0;\r
188                 var2 = (var2/4.0)+(((double)dig_P4) * 65536.0);\r
189                 var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;\r
190                 var1 = (1.0 + var1 / 32768.0)*((double)dig_P1);\r
191                 if (var1 == 0.0)\r
192                 {\r
193                         return ; // avoid exception caused by division by zero\r
194                 }\r
195                 p = 1048576.0 - (double)adc_P;\r
196                 p = (p - (var2 / 4096.0)) * 6250.0 / var1;\r
197                 var1 = ((double)dig_P9) * p * p / 2147483648.0;\r
198                 var2 = p * ((double)dig_P8) / 32768.0;\r
199                 p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;\r
200                 *temperature=(int32_t) (T*100.0);\r
201                 *pressure=(uint32_t) p;\r
202                 return;\r
203 }\r
204 \r
205 \r
206 \r
207 void bmp280ConvertInt(int32_t * temperature,uint32_t *pressure,uint8_t oss) {\r
208         int32_t var1,var2,T,t_fine;\r
209         int32_t adc_T=bmp280ReadTemp();\r
210         var1 = ((((adc_T>>3) - ((int32_t)dig_T1<<1))) * ((int32_t)dig_T2)) >> 11;\r
211         var2 = ((((((adc_T>>4) - ((int32_t)dig_T1)) * ((adc_T>>4) - (int32_t)dig_T1))) >> 12) *((int32_t)dig_T3)) >> 14;\r
212         t_fine = var1 + var2;\r
213         T = (t_fine * 5 + 128) >> 8;\r
214         *temperature=T;\r
215         int32_t adc_P= bmp280ReadPressure(oss);\r
216         int32_t p;\r
217         var1 = (((int32_t)t_fine)>>1) - (int32_t)64000;\r
218         var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)dig_P6);\r
219         var2 = var2 + ((var1*((int32_t)dig_P5))<<1);\r
220         var2 = (var2>>2)+(((int32_t)dig_P4)<<16);\r
221         var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)dig_P2) * var1)>>1))>>18;\r
222         var1 =((((32768+var1))*((int32_t)dig_P1))>>15);\r
223         if (var1 == 0) {\r
224                 return ; // avoid exception caused by division by zero\r
225         }\r
226         p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;\r
227         if (p < 0x80000000){\r
228                 p = (p << 1) / ((uint32_t)var1);\r
229                 }else{\r
230                 p = (p / (uint32_t)var1) * 2;\r
231         }\r
232         var1 = (((int32_t)dig_P9) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12;\r
233         var2 = (((int32_t)(p>>2)) * ((int32_t)dig_P8))>>13;\r
234         p = (uint32_t)((int32_t)p + ((var1 + var2 + dig_P7) >> 4));\r
235 \r
236         *pressure=(uint32_t)(p);\r
237 \r
238 }\r
239 \r
240 void bmp280Convert(double * temperature, double * pressure,uint8_t oss) {\r
241 \r
242         uint32_t p;\r
243         int32_t T;\r
244         bmp280ConvertInt(&T,&p,oss);\r
245         *temperature=T/100.0;\r
246         *pressure=p/100.0;\r
247 }\r
248                 \r
249 void bmp280ConvertIntP(int32_t temp256,uint32_t *pressure) {\r
250         int32_t var1,var2,t_fine;\r
251         //T = (t_fine * 5 + 128) >> 8;\r
252         t_fine=((temp256)-128)/5;\r
253         int32_t adc_P= bmp280ReadPressure_simple();\r
254         uint32_t p;\r
255         var1 = (((int32_t)t_fine)>>1) - (int32_t)64000;\r
256         var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)dig_P6);\r
257         var2 = var2 + ((var1*((int32_t)dig_P5))<<1);\r
258         var2 = (var2>>2)+(((int32_t)dig_P4)<<16);\r
259         var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)dig_P2) * var1)>>1))>>18;\r
260         var1 =((((32768+var1))*((int32_t)dig_P1))>>15);\r
261         if (var1 == 0) {\r
262                 return ; // avoid exception caused by division by zero\r
263         }\r
264         p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;\r
265         if (p < 0x80000000){\r
266                 p = (p << 1) / ((uint32_t)var1);\r
267                 }else{\r
268                 p = (p / (uint32_t)var1) * 2;\r
269         }\r
270         var1 = (((int32_t)dig_P9) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12;\r
271         var2 = (((int32_t)(p>>2)) * ((int32_t)dig_P8))>>13;\r
272         p = (uint32_t)((int32_t)p + ((var1 + var2 + dig_P7) >> 4));\r
273         *pressure=p;\r
274 \r
275 }               \r
276                 \r
277 void bmp280ConvertIntP1(uint32_t *pressure) {\r
278         int32_t var1,var2,t_fine;\r
279         \r
280         \r
281         int32_t adc_T=bmp280ReadTemp();\r
282         var1 = ((((adc_T>>3) - ((int32_t)dig_T1<<1))) * ((int32_t)dig_T2)) >> 11;\r
283         var2 = ((((((adc_T>>4) - ((int32_t)dig_T1)) * ((adc_T>>4) - (int32_t)dig_T1))) >> 12) *((int32_t)dig_T3)) >> 14;\r
284         t_fine = var1 + var2;\r
285         //T = (t_fine * 5 + 128) >> 8;\r
286         int32_t adc_P= bmp280ReadPressure_simple();\r
287         uint32_t p;\r
288         var1 = (((int32_t)t_fine)>>1) - (int32_t)64000;\r
289         var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)dig_P6);\r
290         var2 = var2 + ((var1*((int32_t)dig_P5))<<1);\r
291         var2 = (var2>>2)+(((int32_t)dig_P4)<<16);\r
292         var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)dig_P2) * var1)>>1))>>18;\r
293         var1 =((((32768+var1))*((int32_t)dig_P1))>>15);\r
294         if (var1 == 0) {\r
295                 return ; // avoid exception caused by division by zero\r
296         }\r
297         p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;\r
298         if (p < 0x80000000){\r
299                 p = (p << 1) / ((uint32_t)var1);\r
300                 }else{\r
301                 p = (p / (uint32_t)var1) * 2;\r
302         }\r
303         var1 = (((int32_t)dig_P9) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12;\r
304         var2 = (((int32_t)(p>>2)) * ((int32_t)dig_P8))>>13;\r
305         p = (uint32_t)((int32_t)p + ((var1 + var2 + dig_P7) >> 4));\r
306         *pressure=p;\r
307 \r
308 }\r