Forum: Mikrocontroller und Digitale Elektronik Probleme mit BMP085 und ANT+ über UART


von No Y. (noy)


Lesenswert?

Hallo Forum,

ich bin momentan dabei auf meinem DE2 Board mit dem NIOS einen BMP085 
auszulesen und anschließend diese Daten über das ANT Breakout Board
https://www.sparkfun.com/products/retired/8565 von Sparkfun an meinem PC 
zu senden und dort dann mit dem ANT USB Stick 
https://www.sparkfun.com/products/retired/8840 von Sparkfun die Daten in 
Matlab zu verarbeiten.

Nun habe ich allerdings 2 Probleme:

1. Laut Wikipedia müsste ich auf einer Höhe von 290-350m ÜNN liegen.
Nach dem auswerten und umrechnen der Daten des BMP085, bin ich hier aber 
nur auf ca 200-220m (schwankt ziemlich). Stimmt etwas an meinem Code 
nicht oder ist der Sensor so ungenau?

2. Wenn ich die Daten über UART an den Sender schicke, scheint noch 
alles zu passen, zumindest nach meinem LA über den ich das UART 
überwache. Es wird genau das gesendet, was ich im Code angebe. Daraufhin 
bekomme ich vom Breakout Board : 0xA4,0x03,0x40,0x00,0x01,0x03,0xE5 
zurück. Leider finde ich nirgends eine Angabe was 0x01 und 0x03 heißt. 
Müssten Message ID und Message Code sein. Sagt mir nur nichts.

Das Problem ist nun, dass ich leider in Matlab nur Müll empfange. Von 
daher wüsste ich gern ob etwas in meinem Code falsch ist oder ob ich in 
Matlab einen Fehler habe.
1
/*
2
 *  Created on: 31.07.2013
3
 */
4
5
#include <stdio.h>
6
#include <string.h>
7
#include <math.h>
8
#include "system.h"
9
#include "i2c_opencores.h"
10
#include "unistd.h"
11
#include "altera_avalon_pio_regs.h"
12
#include "altera_avalon_uart_regs.h"
13
                    // ESC[#;#H Moves the cursor to line #, column #
14
#define ESC_TOP_LEFT "[1;0H"
15
#define ESC_BOTTOM_LEFT "[2;0H"
16
#define LCD_CLR "[2J"             // ESC[2J Clear screen and home cursor
17
#define LCD_CLR_LINE "[K"         // ESC[K Clear to end of line
18
#define ESC  0x1b             // Integer ASCII value of the ESC character
19
20
#define I2C_SPEED 400000
21
22
#define BMP085_OVERSAMPLING 3
23
#define BMP085_ADDRESS 0x77
24
#define BMP085_CMD_ADDRESS 0xF4
25
#define BMP085_PARAM_ADDRESS 0xAA
26
#define BMP085_START_TEMP 0x2E
27
#define BMP085_MEASURED_DATA 0xF6
28
#define BMP085_PRESSURE_MEASURE_PRECISION (0x34+(BMP085_OVERSAMPLING<<6))
29
30
31
#define P0 1013.25            //Pressure [hPA] @ NN
32
33
short AC1 = 0, AC2 = 0, AC3 = 0, B1 = 0, B2 = 0, MB = 0, MC = 0, MD = 0;
34
unsigned short AC4 = 0, AC5 = 0, AC6 = 0;
35
long B5 = 0;
36
37
FILE *lcd;
38
FILE *uart;
39
40
void get_Param(void);
41
float get_Temp(void);
42
float get_Height(void);
43
float get_Height_average_10(void);
44
void Display_Data(float Height_UNN, float Temperature);
45
46
void ANT_config(void);
47
void ANT_reset(void);
48
void ANT_assignch(void);
49
void ANT_setchid(void);
50
void ANT_opench(void);
51
void ANT_send_Test(void);
52
void ANT_SEND(float Height_UNN,float Temperature);
53
54
55
int main()
56
{
57
float Temperature = 0, Height_UNN = 0;
58
char k = 4;
59
60
61
I2C_init(I2C_BASE,ALT_CPU_FREQ,I2C_SPEED);
62
63
get_Param();
64
ANT_config();
65
66
while(1)
67
{
68
  k++;
69
  if (k >= 5)
70
  {
71
    Temperature = get_Temp();
72
    k = 0;
73
  }
74
  Height_UNN = get_Height_average_10();
75
  Display_Data(Height_UNN,Temperature);
76
  ANT_SEND(Height_UNN,Temperature);
77
  usleep(1000000);
78
}
79
80
fclose (lcd);
81
return 0;
82
}
83
84
void Display_Data(float Height_UNN, float Temperature)
85
{
86
  lcd = fopen ("/dev/LCD","w");
87
  if(lcd)
88
  {
89
  fprintf(lcd,"%c%s",ESC,LCD_CLR);
90
  //fprintf(lcd,"Temp = %.1f C Height = %.1f m", 1.1, 2.2);
91
  fprintf(lcd,"Temp = %.1f C\nHeight = %.1f m", Temperature, Height_UNN);
92
  fclose(lcd);
93
  }
94
}
95
96
void get_Param(void)
97
{
98
  unsigned char data[22] = {0};
99
  char i = 0;
100
  char AOK = 1;
101
  FILE *fp;
102
  AOK = I2C_start(I2C_BASE,BMP085_ADDRESS,0); //set chip address and set to write
103
104
  fp = fopen("/dev/LCD","w");
105
  if (AOK == 0)
106
  fprintf(fp,"Adress OK");
107
  fclose(fp);
108
109
  I2C_write(I2C_BASE,BMP085_PARAM_ADDRESS,0);
110
  I2C_start(I2C_BASE,BMP085_ADDRESS,1); //set chip address in read mode
111
112
  for (i = 0;i < 21;i++)
113
  {
114
    data[(0 + (i))] =  I2C_read(I2C_BASE,0);  // memory array
115
  }
116
  data[(0 + (i))] =  I2C_read(I2C_BASE,1);  // last memory read
117
118
  AC1 = (data[0] << 8) | data[1];
119
  AC2 = (data[2] << 8) | data[3];
120
  AC3 = (data[4] << 8) | data[5];
121
  AC4 = (data[6] << 8) | data[7];
122
  AC5 = (data[8] << 8) | data[9];
123
  AC6 = (data[10] << 8) | data[11];
124
  B1 = (data[12] << 8) | data[13];
125
  B2 = (data[14] << 8) | data[15];
126
  MB = (data[16] << 8) | data[17];
127
  MC = (data[18] << 8) | data[19];
128
  MD = (data[20] << 8) | data[21];
129
}
130
131
float get_Temp(void)
132
{
133
    float Temperature = 0;
134
    long  X1 = 0 ,X2 = 0, Temp_Comp = 0;
135
    unsigned long Temp_Raw = 0;
136
137
    I2C_start(I2C_BASE,BMP085_ADDRESS,0);
138
    I2C_write(I2C_BASE,BMP085_CMD_ADDRESS,0);
139
    I2C_write(I2C_BASE,BMP085_START_TEMP,1);
140
    while(!(IORD_ALTERA_AVALON_PIO_DATA(GPIO_IN_BASE) & 0x80));
141
    I2C_start(I2C_BASE,BMP085_ADDRESS,0);
142
    I2C_write(I2C_BASE,BMP085_MEASURED_DATA,0);
143
    I2C_start(I2C_BASE,BMP085_ADDRESS,1);
144
145
    Temp_Raw = (I2C_read(I2C_BASE,0) << 8);
146
    Temp_Raw = (Temp_Raw | I2C_read(I2C_BASE,1));
147
148
    X1 = ((((long)Temp_Raw - (long)AC6) * (long)AC5) >> 15);
149
    X2 = (((long)MC << 11) / (X1 + (long)MD));
150
    B5 = (X1 + X2);
151
    Temp_Comp = ((B5 + 8) >> 4);
152
    Temperature =((float)Temp_Comp * 0.1);
153
154
    return Temperature;
155
}
156
157
float get_Height(void)
158
{
159
    long X1 = 0, X2 = 0, X3 = 0, B3 = 0, B6 = 0, Press_Comp = 0;
160
    unsigned long B4 = 0, B7 = 0, Press_Raw = 0;
161
    float UNN = 0;
162
163
    I2C_start(I2C_BASE,BMP085_ADDRESS,0);
164
    I2C_write(I2C_BASE,BMP085_CMD_ADDRESS,0);
165
    I2C_write(I2C_BASE,BMP085_PRESSURE_MEASURE_PRECISION,1);
166
    while(!(IORD_ALTERA_AVALON_PIO_DATA(GPIO_IN_BASE) & 0x80));
167
    I2C_start(I2C_BASE,BMP085_ADDRESS,0);
168
    I2C_write(I2C_BASE,BMP085_MEASURED_DATA,0);
169
    I2C_start(I2C_BASE,BMP085_ADDRESS,1);
170
171
    Press_Raw = (I2C_read(I2C_BASE,0) << 16);
172
    Press_Raw = (Press_Raw | (I2C_read(I2C_BASE,0) << 8));
173
    Press_Raw = (Press_Raw | (I2C_read(I2C_BASE,1)));
174
    Press_Raw = (Press_Raw >> (8 - BMP085_OVERSAMPLING));
175
176
    B6 = (B5 - 4000);
177
    X1 = ((B6 * B6) >> 12);
178
    X1 *=  B2;
179
    X1 >>= 11;
180
    X2 = (AC2 * B6);
181
    X2 >>= 11;
182
    X3 = (X1 + X2);
183
    B3 = ((((((long)AC1 << 2) + X3) << BMP085_OVERSAMPLING) + 2) >> 2);
184
    X1 = ((AC3 * B6) >> 13);
185
    X2 = ((B1 * ((B6 * B6) >> 12)) >> 16);
186
    X3 = (((X1 + X2) + 2) >> 2);
187
    B4 = ((AC4 * (unsigned long)(X3 + 32768)) >> 15);
188
    B7 = (((unsigned long)(Press_Raw - B3)) * (50000 >> BMP085_OVERSAMPLING));
189
    Press_Comp = 0;
190
    if (B7 < 0x80000000)
191
    {
192
      Press_Comp = (B7 << 1) / B4;
193
    }
194
    else
195
    {
196
      Press_Comp = (B7 / B4) << 1;
197
    }
198
    X1 = (Press_Comp >> 8);
199
    X1 *= X1;
200
    X1 = ((X1 * 3038) >> 16);
201
    X2 = (((-7357) * Press_Comp) >> 16);
202
    Press_Comp += (((X1 + X2 + 3791) >> 4));
203
    UNN = (44330.0 * (1.0 - (pow(((((float)Press_Comp / 100.0)) / P0),(1.0 / 5.255)))));
204
205
    return UNN;
206
207
}
208
209
float get_Height_average_10(void)
210
{
211
  char z = 0;
212
  float Height_UNN_average_10 = 0, Height_UNN = 0;
213
214
  for(z = 0; z <= 24 ; z++)
215
  {
216
  Height_UNN += get_Height();
217
  }
218
  Height_UNN_average_10 = (Height_UNN / 25.0);
219
220
  return Height_UNN_average_10;
221
222
}
223
224
void ANT_config (void)
225
{
226
  ANT_reset();
227
  usleep(1000000);
228
  ANT_assignch();
229
  usleep(1000000);
230
  ANT_setchid();
231
  usleep(1000000);
232
  ANT_opench();
233
  usleep(1000000);
234
  //ANT_send_Test();
235
}
236
237
// Resets module
238
void ANT_reset (void)
239
{
240
  unsigned char i;
241
  unsigned char setup[4];
242
243
  setup[0] = 0xa4; // SYNC Byte
244
  setup[1] = 0x01; // LENGTH Byte
245
  setup[2] = 0x4a; // ID Byte
246
  setup[3] = 0x00; // Data Byte N (N=LENGTH)
247
  setup[4] = 0xef; // Checksum
248
  uart = fopen("/dev/UART", "r+");
249
  if(uart)
250
  {
251
    for(i = 0 ; i < 5 ; i++)
252
        {
253
        putc(setup[i],uart);
254
        }
255
    }
256
  fclose(uart);
257
}
258
259
// Assigns CH=0, CH Type=10(TX), Net#=0
260
void ANT_assignch (void)
261
{
262
  unsigned char i;
263
  unsigned char setup[6];
264
265
  setup[0] = 0xa4;
266
  setup[1] = 0x03;
267
  setup[2] = 0x42;
268
  setup[3] = 0x00;
269
  setup[4] = 0x10;
270
  setup[5] = 0x00;
271
  setup[6] = 0xf5;
272
  uart = fopen("/dev/UART", "r+");
273
  if(uart)
274
  {
275
    for(i = 0 ; i < 7 ; i++)
276
        {
277
        putc(setup[i],uart);
278
        }
279
    }
280
  fclose(uart);
281
}
282
283
// Assigns Device#=3100, Device Type ID=01, Trans Type=01
284
void ANT_setchid (void)
285
{
286
  unsigned char i;
287
  unsigned char setup[8];
288
289
  setup[0] = 0xa4;
290
  setup[1] = 0x05;
291
  setup[2] = 0x51;
292
  setup[3] = 0x00;
293
  setup[4] = 0x31;
294
  setup[5] = 0x00;
295
  setup[6] = 0x01;
296
  setup[7] = 0x05;
297
  setup[8] = 0xc5;
298
  uart = fopen("/dev/UART", "r+");
299
  if(uart)
300
  {
301
    for(i = 0 ; i < 9 ; i++)
302
         {
303
        putc(setup[i],uart);
304
         }
305
    }
306
  fclose(uart);
307
}
308
309
// Opens CH 0
310
void ANT_opench (void)
311
{
312
  unsigned char i;
313
  unsigned char setup[4];
314
315
  setup[0] = 0xa4;
316
  setup[1] = 0x01;
317
  setup[2] = 0x4b;
318
  setup[3] = 0x00;
319
  setup[4] = 0xee;
320
  uart = fopen("/dev/UART", "r+");
321
  if(uart)
322
  {
323
    for(i = 0 ; i < 5 ; i++)
324
         {
325
        putc(setup[i],uart);
326
         }
327
    }
328
  fclose(uart);
329
}
330
331
void ANT_SEND(float Height_UNN,float Temperature)
332
{
333
  unsigned char i;
334
  unsigned char  txBuffer[32];
335
  unsigned char  txBufferSize=0;
336
  unsigned char BUFFER[32]={0};
337
338
sprintf(BUFFER,"%.1f%.1f",Temperature,Height_UNN);
339
txBufferSize  = strlen(BUFFER) + 4;  // message plus sync, size and checksum
340
txBuffer[0]  = 0xa4;  // sync byte
341
txBuffer[1]  = (unsigned char) strlen(BUFFER) - 1;  // message size - command size (1)
342
txBuffer[2] = 0x4e;
343
for(i=0; i<strlen(BUFFER); i++)
344
    txBuffer[3+i] = BUFFER[i];
345
346
// calculate the checksum
347
for(i=0; i<txBufferSize - 1; ++i)
348
txBuffer[txBufferSize - 1] = txBuffer[txBufferSize - 1] ^ txBuffer[i];
349
350
351
352
uart = fopen("/dev/UART", "r+");
353
  if(uart)
354
  {
355
    for(i = 0 ; i < txBufferSize ; i++)
356
         {
357
        putc(txBuffer[i],uart);
358
         }
359
    }
360
  fclose(uart);
361
}
362
// Sends Data=AAAAAAAAAAAAAAAA
363
void ANT_send_Test (void)
364
{
365
  unsigned char i;
366
  unsigned char setup[12];
367
368
  setup[0] = 0xa4;
369
  setup[1] = 0x09;
370
  setup[2] = 0x4e;
371
  setup[3] = 0x00;
372
  setup[4] = 0xaa;
373
  setup[5] = 0xaa;
374
  setup[6] = 0xaa;
375
  setup[7] = 0xaa;
376
  setup[8] = 0xaa;
377
  setup[9] = 0xaa;
378
  setup[10] = 0xaa;
379
  setup[11] = 0xaa;
380
  setup[12] = 0xe3;
381
382
  uart = fopen("/dev/UART", "r+");
383
  if(uart)
384
  {
385
    for(i = 0 ; i < 13 ; i++)
386
         {
387
        putc(setup[i],uart);
388
         }
389
    }
390
  fclose(uart);
391
}

Vielen Dank für die Hilfe!


Achja für Matlab nehme ich diesen Code:
https://docs.google.com/file/d/0B_ftilQUm9aTS3poNDVUUjRNOVk/edit?pli=1

Und lese dann mit fread die Daten in eine Variable.

von Karl H. (kbuchegg)


Lesenswert?

> 1. Laut Wikipedia müsste ich auf einer Höhe von 290-350m ÜNN
> liegen. Nach dem auswerten und umrechnen der Daten des BMP085,
> bin ich hier aber nur auf ca 200-220m (schwankt ziemlich).
> Stimmt etwas an meinem Code nicht oder ist der Sensor so ungenau?

Was erwartest du?
Der Luftdruck ändert sich nun mal mit jedem Hoch- und Tiefdruckgebiet, 
welches über deinen Standort drüberzieht.
Woher soll denn der Sensor wissen, ob das Wetter schlecht wird oder du 
mit ihm in die Höhe steigst?

von No Y. (noy)


Lesenswert?

Naja das sich der Druck je nach Wetter ändert hab ich mir schon gedacht, 
nur dass es sich dann so stark auf die Höhe auswirkt hab ich nicht 
erwartet. Eigentlich wollte ich den Sensor später mal für meinen Flying 
F3 verwenden, aber so wird das wohl nichts.




Meine Kommunikation zum Breakout Board müsste ja nach dem LA zu urteilen 
stimmen.

Wie kann ich denn am einfachsten überprüfen ob die vom Stick empfangenen 
Daten stimmen?

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

No y. schrieb:
> nur dass es sich dann so stark auf die Höhe auswirkt hab ich nicht
> erwartet.
>
vereinfachte Näherung: 1hPa pro 8 Meter Höhenunterschied

(http://de.wikipedia.org/wiki/Luftdruck#Abnahme_mit_der_H.C3.B6he)

Grüße Uwe

von No Y. (noy)


Lesenswert?

Kennt sich hier keiner mit ANT aus und kann mit helfen?

Wäre schön wenn ich das Problem gelöst bekomme. Leider kenn ich mich 
nicht mit Python aus...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.