NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Sensors, Actuators, and Robotics » I2C sensor software help(BMP085 absolute pressure sensor)

April 07, 2012
by dvdsnyd
dvdsnyd's Avatar

Hi all,

I have been attempting to interface a 3.3 volt BMP085 breakout board from Sparkfun. It is an absolute pressure sensor. I have a simple voltage level shift circuit on the I2C bus as outlined in this thread by pcbolt.

I have been researching the Fleury I2C library as well have read up on interfacing and reading from a Wii Nunchuck. However, I am still having difficulty in getting this sensor to work. It has calibration coefficients written to EEPROM held in the sensor. So I must read these values first. Once I get those read, I can use basically the same format to read the temperature and pressure out. I will post the part of the datasheet that explains what the sensor needs from the master as well as what I have so far. Here goes. First the Datasheet.

BMP085

Here is the code that I am attempting to use read just the msb value. I have not tried to combine the two 8 bit msb and lsb together. The program compiles. I get a few warnings relating to returning the msb/lsb and casting it from a pointer. I think I am on the right path. But I need help getting the msb and lsb read and combined properly.

/*
BMP085 Pressure Sensor Test
main.c
Developed for ATMega168 with 14745600 crystal
David Snyder
Last Modified: 04/07/2012
*/

//Define Statements

#define F_CPU 14745600

#define BMP085_addr 0xEE            // Device Address for BMP085 Pressure Sensor
// Include Files

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

// Nerdkit Header Files
#include "../Libraries/libnerdkits/lcd.h"
#include "../Libraries/libnerdkits/delay.h"
#include "../Libraries/libnerdkits/uart.h"

// Peter Fleury I2C master header
#include "../Libraries/i2cmaster/i2cmaster.h"

/* Pin Definitions

PC4 = SDA   I2C Data line
PC5 = SCL   I2C clock line
PB1 = Green LED
PB2 = Red LED

*/

uint16_t BMP085_ReadCal(unsigned char address)

{
    //uint16_t data;

    //short data;
    uint8_t i , lsb[7] , msb[7];

    i2c_start(BMP085_addr + I2C_WRITE);

    i2c_write(address);

    i2c_rep_start(BMP085_addr + I2C_READ);

    for (i = 0; i < 7; i++)
    {
        msb[i] = i2c_readAck();

    }
        for (i = 0; i < 7; i++)
    {
        lsb[i] = i2c_readNak();

    }

    i2c_stop();

    return msb;
}

int main(void)
{

    //unsigned char ret;
    PORTC = (1<<PC4) | (1<<PC5);        // Set internal pull up resisotrs for I2C bus
    DDRB |= (1<<PB1);                   // Enable Pin B1 for Output
    DDRB |= (1<<PB2);                   // Enable Pin B2 for Output
    uint16_t AC1;

    // Start up the LCD
    // lcd_init() and lcd_home() are methods written by nerdkits to easily write to the lcd
    lcd_init();
    // Set lcd up for stream that lets us write to the lcd the same way you would a file
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0 , _FDEV_SETUP_WRITE);
    lcd_home();

    i2c_init();                         // Initialize I2C Library

    while(1){

    AC1 = BMP085_ReadCal(0xAA);

    lcd_home();
    lcd_write_string(PSTR("Calibration "));
    lcd_write_int16(AC1);
    /*
    ret =  i2c_start(BMP085_addr + I2C_WRITE);
    if ( ret ) {
        PORTB |= (1<< PB2);
        i2c_stop();
    }else{
        PORTB |= (1<<PB1);
        i2c_stop;

    }
    delay_ms(10000);
    */
    }

}

Like I said, it compiles and I get a result...but if I change the register address to a different calibration coefficient it does not seem to change the value. Which leads me to believe I am not quite reading the EEPROM correctly. Here is a link to the BMP085 Datasheet

Thanks a lot Any help is so greatly appreciated.

David

April 07, 2012
by Ralphxyz
Ralphxyz's Avatar

Look at Rick's great I2C RTC post.

Ralph

April 07, 2012
by dvdsnyd
dvdsnyd's Avatar

Ralph, I did not see that post in my searching. It may be what I need to get this working. Thanks. One question. What does the asterisk do in this line?

*data = i2c_readNak();

Thanks,

David

April 07, 2012
by dvdsnyd
dvdsnyd's Avatar

Also, Is it possible to read signed values?

April 07, 2012
by dvdsnyd
dvdsnyd's Avatar

All,

It seems that I am communicating with the sensor...however I am not getting what I would think I would. Since I have to read the EEPROM first I figured I would print the msb and lsb to the serial port and see what I got. this is for the second coefficient -00000004 msb 00000098 lsb

which when the commands are performed

data = msb << 8;
data |= lsb;

yeilds -000926 AC2

This does not make any sense to me...for one, I was expecting msb and lsb to be all 1's and 0's I don't understand how it can yield the result of -926. What am I missing?

I will post the full code for any one to review.

I know it is messy but if anyone can help me here I would be so grateful. Thanks a lot

David

/*
BMP085 Pressure Sensor Test
main.c
Developed for ATMega168 with 14745600 crystal
David Snyder
Last Modified: 04/07/2012
*/

//Define Statements

#define F_CPU 14745600

#define BMP085_addr 0xEE            // Device Address for BMP085 Pressure Sensor
// Include Files

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

// Nerdkit Header Files
#include "../Libraries/libnerdkits/lcd.h"
#include "../Libraries/libnerdkits/delay.h"
#include "../Libraries/libnerdkits/uart.h"

// Peter Fleury I2C master header
#include "../Libraries/i2cmaster/i2cmaster.h"

/* Pin Definitions

PC4 = SDA   I2C Data line
PC5 = SCL   I2C clock line
PB1 = Green LED
PB2 = Red LED

*/

// Global Variables
long UT;

short AC1;
short AC2;
short AC3;
unsigned short AC4;
unsigned short AC5;
unsigned short AC6;
short B1;
short B2;
short MB;
short MC;
short MD;

// Program Specific Functions

short BMP085_ReadShort(unsigned char address)

{   
    short data;
    char msb, lsb;

    i2c_start(BMP085_addr + I2C_WRITE);

    i2c_write(address);

    i2c_rep_start(BMP085_addr + I2C_READ);
    msb = i2c_readAck();
    lsb = i2c_readNak();
    printf_P(PSTR("%.8i msb \r\n"), msb);
    printf_P(PSTR("%.8i lsb \r\n"), lsb);
    i2c_stop();
    data = msb << 8;
    data |= lsb;

    return data;
}

long BMP085_ReadTemp(void)
{

    i2c_start(BMP085_addr + I2C_WRITE);

    i2c_write(0XF4);

    i2c_write(0X2E);

    i2c_stop();

    delay_ms(10);

    return(long) BMP085_ReadShort(0XF6);

}

void BMP085_GetCalCoefs(void)
{
    AC1 = BMP085_ReadShort(0XAA);
    AC2 = BMP085_ReadShort(0XAC);
    AC3 = BMP085_ReadShort(0XAE);
    AC4 = BMP085_ReadShort(0XB0);
    AC5 = BMP085_ReadShort(0XB2);
    AC6 = BMP085_ReadShort(0XB4);
    B1  = BMP085_ReadShort(0XB6);
    B2  = BMP085_ReadShort(0XB8);
    MB  = BMP085_ReadShort(0XBA);
    MC  = BMP085_ReadShort(0XBC);
    MD  = BMP085_ReadShort(0XBE);

    // Send constants through serial port
    printf_P(PSTR("%.6d AC1 \r\n"), AC1);
    printf_P(PSTR("%.6d AC2 \r\n"), AC2);
    printf_P(PSTR("%.6d AC3 \r\n"), AC3);
    printf_P(PSTR("%.6d AC4 \r\n"), AC4);
    printf_P(PSTR("%.6d AC5 \r\n"), AC5);
    printf_P(PSTR("%.6d AC6 \r\n"), AC6);
    printf_P(PSTR("%.6d B1  \r\n"), B1 );
    printf_P(PSTR("%.6d B2  \r\n"), B2 );
    printf_P(PSTR("%.6d MB  \r\n"), MB );
    printf_P(PSTR("%.6d MC  \r\n"), MC );
    printf_P(PSTR("%.6d MD  \r\n"), MD );
    printf_P(PSTR("------------------------\n\n"));

}

int main(void)
{   // Variable Type Definitions

    //long temperature = 0;
    //long pressure = 0;

    //unsigned char ret;
    PORTC = (1<<PC4) | (1<<PC5);        // Set internal pull up resisotrs for I2C bus
    DDRB |= (1<<PB1);                   // Enable Pin B1 for Output
    DDRB |= (1<<PB2);                   // Enable Pin B2 for Output

    // start up the serial port
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    // Start up the LCD
    // lcd_init() and lcd_home() are methods written by nerdkits to easily write to the lcd
    lcd_init();
    // Set lcd up for stream that lets us write to the lcd the same way you would a file
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0 , _FDEV_SETUP_WRITE);
    lcd_home();

    i2c_init();                         // Initialize I2C Library

    BMP085_GetCalCoefs();

    while(1){

    UT = BMP085_ReadTemp();
    printf_P(PSTR("%.6d UT \r\n"), UT);

    UT = BMP085_ReadTemp();
    printf_P(PSTR("%.6d UT \r\n"), UT);

    lcd_home();
    lcd_write_string(PSTR("UT "));
    lcd_write_int16(UT);
    lcd_line_two();
    lcd_write_int16(AC2);
    lcd_line_three();
    lcd_write_int16(AC3);
    lcd_line_four();
    lcd_write_int16(AC4);

    delay_ms(100000);

    /*
    ret =  i2c_start(BMP085_addr + I2C_WRITE);
    if ( ret ) {
        PORTB |= (1<< PB2);
        i2c_stop();
    }else{
        PORTB |= (1<<PB1);
        i2c_stop;

    }
    delay_ms(10000);
    */
    }

}
April 09, 2012
by dvdsnyd
dvdsnyd's Avatar

Hi again, Still struggling to get this working...trying to make progress. Any help is appreciated. I know there is a lot of knowledge about I2C here in the forum community.

I have been able to read the EEPROM...I think These are my 11 calibration coefficients. Some of them are very close if not exact to another post I have seen. others are VERY far off.

-0000115 AC1
-000926 AC2
-014474 AC3
-031680 AC4
024892 AC5
022313 AC6
005498 B1
000045 B2
-032768 MB
-000067 MC
-000128 MD

One thing that has me concerned is AC4. It is supposed to be an UNSIGNED value. I read a negative value. This raises a reg flag to me. Is it possible to check to make sure you are indeed correctly communicating with the device? Another reason I am wondering if I am getting the right data, is when I read temperature and convert it(Proven conversion function with datasheet) I get about 104 degrees F in a 74 degree F room.

Anyone have any ideas at all??

Thanks so much

David

April 09, 2012
by esoderberg
esoderberg's Avatar

David,

Do you have external pull-ups on both the 3.3v and 5v sides of your Logic Level Shifter? I've tried I2C comms before using the internal pull-ups (as from your code it looks like you might be trying) and it worked just well enough to make me think I had it working, but I always had intermittent problems until going with the recommended external pull-ups between 2.2k and 4.7K ohm.

Eric

April 10, 2012
by dvdsnyd
dvdsnyd's Avatar

Eric,

Thanks so much for responding! I have been slowly working on getting this sensor integrated with the NK for a bit now. I tried adding some 4.7 K ohm pull-up resistors on the ATMega 168 side of the SCL and SDA lines. It did not seem to make any change to the data coming out. It almost seems a bit more reliable though. I have had it on start up read very small(order of magnitude) negative numbers i.e -20 - (-100) On both uncompensated Pressure and uncompensated Temperature(UP, UT).

Right now I am just reading UT and UP, Once you have those, Some nasty integer calculations involving the 11 calibration coefficients gets the true temperature and true pressure.

I have coded the temperature conversion and I know it is right. But it gives me a true temperature reading too high for a room temperature room-see above post. I am also still getting a negative uncompensated pressure, which does not make any sense.

My SDA and SCL lines are not very long. I would say total between 8-12 inches. I have tried different delays and delays in different spots in the read functions. I had to desolder and resolder the header pins on the breakout board.

I have based my code heavily on this ATmega328 example

The above code uses a different I2C library. But it is written in C. Thanks again. If I can attempt to better explain something please don't hesitate. I really want to see this through.

Thanks again,

David

April 10, 2012
by esoderberg
esoderberg's Avatar

David,

Perhaps you could try i2c_start_wait vice i2c_rep_start.

Eric

April 11, 2012
by dvdsnyd
dvdsnyd's Avatar

Eric, Thanks for the suggestion once again.

No change. One thing I have noticed is sometimes when I start up the project I will get values of -20 for uncompensated temperature. I can touch the pressure sensor and it will go to -1000, then I can also get it to display in the 30000 range which I believe is where it is suppose to be. I have looked at my connections everything seems good. I have moved the breakout board around on the breadboard and it doesn't seem to be the breadboard. Here is a quick printout from putty...

-0000000000000017 UT  <<<<<<<<<<<<<<<<<<<< Start up
-0000000000025559 UP
-0000000000000017 UT
-0000000000025556 UP
-0000000000000017 UT
-0000000000025560 UP
-0000000000000019 UT
-0000000000025560 UP
-0000000000000018 UT
-0000000000025558 UP
-0000000000000019 UT
-0000000000025557 UP
-0000000000000018 UT
-0000000000025558 UP
-0000000000000020 UT
-0000000000025561 UP
-0000000000000021 UT
-0000000000025559 UP
-0000000000000019 UT
-0000000000025561 UP
-0000000000000020 UT
-0000000000025559 UP
-0000000000000019 UT
-0000000000025557 UP
-0000000000000019 UT
-0000000000025560 UP
-0000000000000017 UT
-0000000000025559 UP
-0000000000000019 UT   <<<<<<<<<<<<<<<<<<<<< fiddled with sensor
-0000000000025560 UP
0000000000030977 UT
-0000000000025570 UP
0000000000031000 UT
-0000000000025584 UP
0000000000031011 UT
-0000000000025592 UP
0000000000031014 UT
-0000000000025593 UP
0000000000031013 UT
-0000000000025592 UP
0000000000031010 UT
-0000000000025591 UP
0000000000031007 UT
-0000000000025588 UP
0000000000031003 UT
-0000000000025586 UP
0000000000031001 UT
-0000000000025585 UP
0000000000030997 UT
-0000000000025583 UP
0000000000030995 UT
-0000000000025584 UP
0000000000030992 UT
-0000000000025581 UP
0000000000030990 UT
-0000000000025580 UP
0000000000030985 UT
-0000000000025577 UP
0000000000030985 UT
-0000000000025578 UP
0000000000030984 UT
-0000000000025577 UP

What do you think could cause something like this? Sorry if I am trying to go after too many questions at once. Seems there is a gremlin somewhere...or maybe 2 or 3...Thanks again, so much

David

I really do appreciate any and all help, even if it is something really simple or something I may have tried.

April 11, 2012
by pcbolt
pcbolt's Avatar

David -

I've been helping out on another project here and found the "printf_P()" and "fprintf_P()" functions act a little squirrely sometimes and do not behave as the ANSI C documentation you'll find online says it does. I noticed too that you are using the "%.6d" escape sequence. This does not make sense since the ".6" tells the function to format using 6 decimal places, but you are using integers. Try just using "%d" (shorts) and "%ld" (longs) for now and worry about proper formatting after. (Note: if you want 6 places padded with 0's you "should" use %06d - but even that I have had some problems with using the avr compiler).

April 11, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks pcbolt,

I appreciate the help. Is there another method of getting information onto the computer from the project other than those functions? I will try to implement those changes tomorrow morning after work. One thing to note though, I also have the data printed out the the lcd screen, and it correlates exactly to the data running through the serial line. I am really at a loss here. I have contacted Sparkfun, and they replied yesterday wanting more information, but they have not sent back a response yet. I have heard people having difficulty with this sensor, but nothing like I am experiencing.

I know it is a ton to ask, but could would it be possible to ask someone to look at the datasheet and confirm I am using the I2C library correctly? This is the first time I have tried using it.

I believe I made all the changes to the library files, like changing the processor speed...

Thanks again, Guys-

I do believe that this will get resolved. I am bound and determined. Appreciate the help

David

April 11, 2012
by pcbolt
pcbolt's Avatar

David -

I think I may have been wrong in my last post. The formatting you use is for precision is OK, but when you are printing UNSIGNED variables use %u (for short) and %ul (for long). You might be getting the correct EEPROM values after all.

Using your coefficients, an uncorrected value of UT should be around 27500. Still a bit hot but fairly close. Please re-post the coefficients if the print out is different.

April 11, 2012
by pcbolt
pcbolt's Avatar

David -

The one thing that confuses me in your code is in the lines 66 to 70;

i2c_write(address);
i2c_rep_start(BMP085_addr + I2C_READ);
msb = i2c_readAck();
lsb = i2c_readNak();

The first 3 lines make sense, but how does the slave device know to increment the address to send for the second read? It seems to work for you, just not sure why. I would think it needs to be written;

i2c_write(address);
i2c_rep_start(BMP085_addr + I2C_READ);
msb = i2c_readAck();
i2c_start(BMP085_addr + I2C_WRITE);
i2c_write(address + 1);
i2c_rep_start(BMP085_addr + I2C_READ);
lsb = i2c_readNak();         // maybe just lsb = i2c_readAck();

I'm no expert on this subject so I could easily be missing something.

April 11, 2012
by pcbolt
pcbolt's Avatar

Correction - The 'test' code should be;

i2c_write(address);
i2c_rep_start(BMP085_addr + I2C_READ);
msb = i2c_readAck();
i2c_rep_start(BMP085_addr + I2C_WRITE);
i2c_write(address + 1);
i2c_rep_start(BMP085_addr + I2C_READ);
lsb = i2c_readNak();         // maybe just lsb = i2c_readAck();
April 12, 2012
by esoderberg
esoderberg's Avatar

David,

I'd take pcbolt's suggestion to look at your data types and how you print them out, I've often found this to be the root problem when getting data that doesn't make sense.

NK_printf_gouge

As for the suggestion to manually sequence through the MSB and LSB address, after looking at Fig. 7 in the datasheet I don't think that is necessary; most I2C devices will auto sequence to the next register on consecutive reads as assumed in your code.

April 12, 2012
by pcbolt
pcbolt's Avatar

Eric -

You're right...I didn't catch that when I looked through the datasheet. Good call.

David -

Hope I didn't steer you too far wrong :-)

April 13, 2012
by dvdsnyd
dvdsnyd's Avatar

Hey Guys,

No one is steering me wrong! :-) You guys are helping out a ton!

Thanks a lot for taking a look at my code and the datasheet.

pcbolt-

I haven't tried to implement your test code...yet. I may just to see if it changes anything- remember, I have based a lot of my code off of code that someone from Sparkfun wrote in C for an arudino. They didn't manually sequence the address of the registers, so I didn't. Here is the code that I have based mine on...much of it is very similar, except I am using Jim Fleury's I2C library.

I have been looking at the data types quite a bit today. Couple things ended up coming up yesterday that were beyond my control. So I wasn't able to spend much time on the project.

I changed the section of code where I write the calibration coefficients through serial to the computer to:

// Send constants through serial port
printf_P(PSTR("\r\nCalibration Information\r\n"));
printf_P(PSTR("------------------------\r\n"));
printf_P(PSTR("%d AC1 \r\n"), AC1);
printf_P(PSTR("%d AC2 \r\n"), AC2);
printf_P(PSTR("%d AC3 \r\n"), AC3);
printf_P(PSTR("%u AC4 \r\n"), AC4);
printf_P(PSTR("%u AC5 \r\n"), AC5);
printf_P(PSTR("%u AC6 \r\n"), AC6);
printf_P(PSTR("%d B1  \r\n"), B1 );
printf_P(PSTR("%d B2  \r\n"), B2 );
printf_P(PSTR("%d MB  \r\n"), MB );
printf_P(PSTR("%d MC  \r\n"), MC );
printf_P(PSTR("%d MD  \r\n"), MD );
printf_P(PSTR("------------------------\n\n"));

Here are the results I get:

Calibration Information
------------------------
-115 AC1
-926 AC2
-14474 AC3
33856 AC4
24892 AC5
22313 AC6
5498 B1
45 B2
-32768 MB
-67 MC
-128 MD
------------------------

If you go up a few posts, you can see that it changed AC4. The value the datasheet gives is 32741. Quite a bit closer. However, before we celebrate, the value of -31860 is still printed to the LCD. This is the same value I was getting before. The only thing I changed is how the serial port sends the information. AC4 is declared in my code as an unsigned short- exactly how it is in the serial communication. Could the explanation be as simple as the code block:

lcd_write_int16(AC4);

can't take into account the actual unsigned value? I don't know if it would help to display the msb and lsb values?? They are declared as characters. It just seems to add to the confusion whatever I try to display them has...hex, integer..char.

If I print out the uncompensated temperature and pressure as well. I get this

-32745 UT
65409 UP
-26346 UT
65410 UP
-26345 UT
65409 UP
-26345 UT

Something interesting-

If I just print out UP

32889 UP
39291 UP
39294 UP
39294 UP
39292 UP
39291 UP

Just printing out UT

-32735 UT
30982 UT
30984 UT
30983 UT
30983 UT
30985 UT

Is it possible that there is something still wrong with how I am using the I2C libraries? Or maybe in the delays? I read that the first reading can be thrown out.

With just UT displaying. If I blow on the device or breathe on it try to cool/heat up the air around it I get mixed results.

If I blow on it, The data coming out will change to -120 or so, but it will return to the above readings. It seems that if I blow hard enough or disturb the sensor just a tiny amount, communication just stops.

Sorry this is so long. I just try to be as thorough as possible. It seems there is some progress here, I am wondering now if it is something in my delays/I2C reading now...Again, Thanks so much for helping/looking at this mess! I appreciate all help. It goes a long ways. Wouldn't be this far without the help I have gotten so far. Please keep it up!

Look forward to hearing your thoughts

David

April 13, 2012
by pcbolt
pcbolt's Avatar

David -

"Could the explanation be as simple as the code block?"

Yes! When you look at the code for the "lcd_write_int16()" function the first thing it looks for is if the number is less than zero or not. To do that, all the processor does is look at the Most Significant Bit (MSB) of the number...if it is 1 the number is negative, if it is 0 the number is positive. By having a "signed" number you actually have to sacrifice 1 of the 16 bits (for type short). This means the range of numbers can only go from -32,768 to +32,767 (+/- 2^15). Having an unsigned number means you can use all 16 bits and numbers range from 0 to 65,536. It would be pretty easy to copy the code for "lcd_write_int16()", modify it slightly and make it "lcd_write_uint16()".

When you read AC4 from the EEPROM, you're getting just a bunch of 1's and 0's. How you put it into human readable form is what's important. Using the AC4 value of 33856 as an example, becomes 0x8440 hex or 1000 0100 0100 0000 binary (this is what gets sent over the I2C line), the MSB is 1 so if this were treated as a signed number it would be negative. The "lcd_write_int16()" would then take the number and subtract it from 65,536 to get 31,680 and print a '-' sign in front of it. The binary (or hex) number never changed. If you want to print out "msb" and "lsb" use hex notation.

As far as the symptoms of your experiment go...it looks like you are using the I2C interface just fine. I would focus efforts on trying to make the wiring more stable but it seems like what you describe is a timing issue. I noticed there is a an End Of Conversion pin you might want to test (if possible). It might complicate things though. It seems to me the 10 ms delay you use should work. I assume you use similar code for pressure. I'd be curious to see the "msb"/"lsb" values (in hex) of your raw readings, mainly after you blow on the sensor.

April 13, 2012
by dvdsnyd
dvdsnyd's Avatar

All-,

pcbolt- Thanks for that explanation. It helped me out a lot to understand what was going on. Makes perfect sense now.

So...as it stands I believe I am getting good calibration values. Now, on to figuring out what is going on with getting good data now too. I know I am not getting good data, Converting the uncompensated temp to true temp, gives me an outrageous value...I can tell, just looking at pressure it will do the same thing.

I have tried a few things, like putting delays in various places...taking delays out. I found this as well. It shows a delay quirk. I tried to implement it, but it didn't alleviate all my issues. I think it helped resolve the "timing" issue. I am not positive though. My data seems consistent...just wrong, and a bit finicky too.

A bit of explanation..

A few things I have noticed now. If I gently "HAAAAAA" on the sensor...essentially try to see an increase in temperature. The communication abruptly shuts off, ALWAYS in the same place. I get this through serial- I have the msb and lsb shown in hex format.

0xff99 msb
0x28 lsb
39208 UP
------------------------
0x79 msb
0x38 lsb
31032 UT
------------------------
0xff99 msb
0x1f lsb
39199 UP
------------------------
0x79 msb
0x4a lsb
31050 UT
------------------------
0xff99 msb
0x9 lsb
39177 UP
------------------------
0x79 msb
0x6f lsb
31087 UT
------------------------
0xff98 msb
0xfffb lsb
65531 UP
------------------------
0xffde msb

You can see that pressure doubles and then shuts off. the reading it stops on is always the same and always gives that hex value. It is starting to read temperature. From what I can tell too, the temperature seems to respond by increasing too.

If I go the other way, and hold ice cold glass of water over the sensor-not touching I get this result:

------------------------
0xff99 msb
0x30 lsb
39216 UP
------------------------
0x79 msb
0xb lsb
30987 UT
------------------------
0xff99 msb
0x33 lsb
39219 UP
------------------------
0x79 msb
0x7 lsb
30983 UT
------------------------
0xff99 msb
0x37 lsb
39223 UP
------------------------
0x79 msb
0x4 lsb
30980 UT
------------------------
0xff99 msb
0x36 lsb
39222 UP
------------------------
0x79 msb
0x1 lsb
30977 UT
------------------------
0xff99 msb
0x37 lsb
39223 UP
------------------------
0x78 msb
0xfffd lsb
-3 UT
------------------------
0xff99 msb
0x35 lsb
39221 UP
------------------------
0x78 msb
0xfffd lsb
-3 UT
------------------------
0xff99 msb
0x38 lsb
39224 UP
------------------------
0x78 msb
0xfff9 lsb
-7 UT
------------------------
0xff99 msb
0x3b lsb
39227 UP
------------------------
0x78 msb
0xfff6 lsb
-10 UT
------------------------
0xff99 msb
0x3a lsb
39226 UP
------------------------
0x78 msb
0xfff4 lsb
-12 UT
------------------------

It will continue to run though. Also, it will display the negative temperature for quite some time. Eventually going back to the normal readings before. But it can take upwards of a few minutes.
-A quick note- I get the exact same result for temperature whether I am reading both UP and UT or just UT.

I know this isn't recommended. I read that it can be done if you have 1 3.3 V device on the I2C bus...I don't really believe it would be good for the longevity of the device...but I bypassed the logic level shift to see if anything changed. It did not do anything to the values whatsoever. It may have been a bit more stable, less wire/breadboard to deal with.

I have thought about trying to power everything at 3.3 volts. Can I program everything at 5 volts, then throw the 3.3 volt regulator in place of the 5 volt and walla? Or is it more involved?

I had to solder and desolder and then resolder some headers onto the board...could I have damaged sensor in some way?

That seems about all I can think of at the moment. Thanks again, for the help.

Look forward to your comments/suggestions

David

I will post the code again:

/*
BMP085 Pressure Sensor Test
main.c
Developed for ATMega168 with 14745600 crystal
David Snyder
Last Modified: 04/12/2012
*/

//Define Statements

#define F_CPU 14745600

#define BMP085_addr 0xEE            // Device Address for BMP085 Pressure Sensor
#define OSS = 0
// Include Files

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

// Nerdkit Header Files
#include "../Libraries/libnerdkits/lcd.h"
#include "../Libraries/libnerdkits/delay.h"
#include "../Libraries/libnerdkits/uart.h"

// Peter Fleury I2C master Library
#include "../Libraries/i2cmaster/i2cmaster.h"

/* Pin Definitions

PC4 = SDA   I2C Data line
PC5 = SCL   I2C clock line
*/

/* Global Variables
 Calibration Coeficient variable declaration
 Found on Page 13 of BMP085 Datasheet
*/

short AC1;
short AC2;
short AC3;
unsigned short AC4;
unsigned short AC5;
unsigned short AC6;
short B1;
short B2;
short MB;
short MC;
short MD;

// Program Specific Functions

long BMP085ConvertTemp(long UTemp)
{
/*Calculate True Temperatue from Uncompensated Temperature
Calculations found on page 14 of BMP085 Datasheet
INPUT: Uncompensated Temperature
OUTPUT: True Temperature
*/
    long Temperature;
    long X1 , X2, B5;

    X1 = ((long)UTemp - AC6) * AC5 >>15;
    X2 = ((long)MC << 11) / (X1 + MD);
    B5 = X1 + X2;
    return Temperature = (B5 + 8) >>4;

}

short BMP085_ReadShort(unsigned char address)
/*Read two sequential 8-bit registers, and return a 16 bit value
  INPUT: First register address to read data from-MSB
  OUTPUT:

*/
//RIGHT: Waiting after sending repeated start (or stop)
//i2c1start(0xEE); //BMP085 address, write mode
//i2c1write(0xF4); //Control register
//i2c1write(0x2E); //Start temp conversion
//i2c1start(0xEE); //BMP085 address, write mode (repeated start)
//for (int i = 0; i < 50000; i++) { asm(“nop”); } //wait for conversion

{   
    short data;
    char msb, lsb;

    i2c_rep_start(BMP085_addr + I2C_WRITE);
    delay_ms(10);
    i2c_write(address);

    i2c_rep_start(BMP085_addr + I2C_READ);

    delay_ms(10);

    printf_P(PSTR("------------------------\r\n"));

    msb = i2c_readAck();
    printf_P(PSTR("%#x msb \r\n"), msb);
    lsb = i2c_readNak();
    printf_P(PSTR("%#x lsb \r\n"), lsb);
    i2c_stop();

    data = msb << 8;
    data |= lsb;

    return data;
}

long BMP085_ReadTemp(void)
/* Read Uncompensated Temperature from BMP085

*/
{
    i2c_start(BMP085_addr + I2C_WRITE);     // BMP085 Address, Write Mode

    i2c_write(0XF4);                        // Control Register

    i2c_write(0X2E);                        // Start Temperature Conversion

    i2c_stop();

    delay_ms(10);
    return (long) BMP085_ReadShort(0XF6);
}

long BMP085_ReadPres(void)
{
    long pressure = 0;

    i2c_start(BMP085_addr + I2C_WRITE);     //BMP085 Address, Write Mode

    i2c_write(0XF4);                        // Control Register

    i2c_write(0X34);                        // Start Pressure Conversion

    i2c_stop();
    delay_ms(10);
    pressure = (long)BMP085_ReadShort(0XF6);
    pressure &= 0X0000FFFF;

    return pressure;

}

void BMP085_GetCalCoefs(void)
/* Read 11 Calibration Coefficients from EEPROM
*/
{
    delay_ms(100);  // Start-up time as stated in table 5 of page 16 of BMP085 Datasheet

    AC1 = BMP085_ReadShort(0XAA);
    AC2 = BMP085_ReadShort(0XAC);
    AC3 = BMP085_ReadShort(0XAE);
    AC4 = BMP085_ReadShort(0XB0);
    AC5 = BMP085_ReadShort(0XB2);
    AC6 = BMP085_ReadShort(0XB4);
    B1  = BMP085_ReadShort(0XB6);
    B2  = BMP085_ReadShort(0XB8);
    MB  = BMP085_ReadShort(0XBA);
    MC  = BMP085_ReadShort(0XBC);
    MD  = BMP085_ReadShort(0XBE);

    // Send constants through serial port
    printf_P(PSTR("\r\nCalibration Information\r\n"));
    printf_P(PSTR("------------------------\r\n"));
    printf_P(PSTR("%d AC1 \r\n"), AC1);
    printf_P(PSTR("%d AC2 \r\n"), AC2);
    printf_P(PSTR("%d AC3 \r\n"), AC3);
    printf_P(PSTR("%u AC4 \r\n"), AC4);
    printf_P(PSTR("%u AC5 \r\n"), AC5);
    printf_P(PSTR("%u AC6 \r\n"), AC6);
    printf_P(PSTR("%d B1  \r\n"), B1 );
    printf_P(PSTR("%d B2  \r\n"), B2 );
    printf_P(PSTR("%d MB  \r\n"), MB );
    printf_P(PSTR("%d MC  \r\n"), MC );
    printf_P(PSTR("%d MD  \r\n"), MD );
    printf_P(PSTR("------------------------\n\n"));

}

int main(void)
{   // Variable Type Definitions

    long Temp = 0;
    long UT = 0;
    long UP = 0;

    PORTC = (1<<PC4) | (1<<PC5);        // Set internal pull up resisotrs for I2C bus
    DDRB |= (1<<PB1);                   // Enable Pin B1 for Output
    DDRB |= (1<<PB2);                   // Enable Pin B2 for Output

    // start up the serial port
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    // Start up the LCD
    lcd_init();
    // Set lcd up for stream that lets us write to the lcd the same way you would a file
    //FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0 , _FDEV_SETUP_WRITE);

    lcd_home();

    i2c_init();                         // Initialize I2C Library

    BMP085_GetCalCoefs();

    while(1)
    {

        UT = BMP085_ReadTemp();
        //UT = BMP085_ReadTemp();
        printf_P(PSTR("%ld UT \r\n"), UT);
        delay_ms(500);

        UP = BMP085_ReadPres();
        //UP = BMP085_ReadPres();
        printf_P(PSTR("%ld UP \r\n"), UP);

        //Temp = BMP085ConvertTemp(UT);
        //printf_P(PSTR("%.6d True Temp \r\n"), Temp);

    }

}
April 13, 2012
by pcbolt
pcbolt's Avatar

David -

There is something wrong with the msb/lsb to data conversion inside BMP085_ReadShort(). I think when you declare msb/lsb as "char" it is defaulting to "signed char" and when you involve "data" (a signed short 16-bit) it does what's known as "sign extending" when it converts from a 8-bit value to a 16-bit value. You can see this happening every time "msb/lsb" becomes greater than 0x7f in your listing it tacks on "0xff" in front of the actual number. Not exactly sure why it's doing this, but it is corrupting your results. Take the very last UT listing for example;

------------------------
0x78 msb
0xfff4 lsb
-12 UT
------------------------

The actual answer you should get is 0x78f4 or 30,964. When you go through your code on lines 108-109 and plug in your values you get

data = msb << 8;    // data = 0x78 << 8 or data = 0x7800
data |= lsb;        // data = 0x7800 | 0xfff4 or data = 0xfff4  WRONG!

Since 0xfff4 = -12 (which is what is getting spit out) it is not computing correctly.

There are two ways to solve this.

Inside "BMP085_ReadShort()" change

char msb, lsb;

To

uint8_t msb, lsb;

Or, use this line

data |= (0x00ff & lsb);        //mask off the leading byte

This may have effected how the EEPROM values were computed as well so you may have to re-print them to see if things changed there. (It looks like MD maybe wrong so the temp equation might be off).

April 14, 2012
by dvdsnyd
dvdsnyd's Avatar

pcbolt!!!!!

It looks like that may have done it. It altered some of the calibration coefficient values. It didn't change the UT value, but when I used the new calibration values, I got the temperature that I was expecting!! I haven't implemented the complex pressure calculations yet, but hope to have it tested by tomorrow. I will keep you all posted!

Thank you SO much for hanging with me so far! I only hope that I can be more help to people on the forums in the coming months, and not such a leech.

Obviously I'm not out of the woods yet, but I think we're getting there!

Thanks again!! Keep you posted

David

April 14, 2012
by pcbolt
pcbolt's Avatar

No problem, David.

I learned quite a bit myself just by chipping in my 2 cents. Looking forward to see your progress.

May 18, 2012
by dvdsnyd
dvdsnyd's Avatar

Hey Guys!

I am back :-)

I have been looking into implementing the ultra high resolution mode of the sensor. This should help with noise reduction. As I can tell reading the datasheet and looking at other code. It is mostly adds 3 more bits of data, totaling 19 bits. You read msb, lsb and an xlsb, then to get the uncompensated pressure:

UP = (MSB<<16 + LSB<<8 + XLSB) >> (8-oss)

Where oss = oversampling setting = 3 This takes 8 internal samples instead of just 1, and should reduce noise.

I have a couple questions with this. If UP is designated an unsigned int, this gives 16 bits of data. Going to a long int gives 32 bits of data, +16 and -16 Correct? I am having difficulty understanding how I can fit 19 bits worth of data in 16 bits. If someone could explain how that works, it would be grand.

The second question is with regards to reading XLSB. When I read MSB and LSB, the sensor automatically increments the register on successive reads. Can I do something similar for XLSB? Instead of having a stop command after reading LSB, continue to read XLSB?

Thanks again for the help! The photo in the very first post has the information for reading the registers, as well as the datasheet.

David

May 18, 2012
by Ralphxyz
Ralphxyz's Avatar

Won't just join MSB, LSB and XLSB into a 32bit number in order to do anything with the results/readings?

Ralph

May 18, 2012
by dvdsnyd
dvdsnyd's Avatar

Ralph,

I am sorry, I don't quite understand what you are saying. Could you please elaborate some?

David

May 18, 2012
by Ralphxyz
Ralphxyz's Avatar

You need to add lsb to a 32 bit number and then left shift 8 bits MSB to the 32 bit number and then left shift XLSB 16 bits.

Or something like that I am not a (programmer).

So then you have a 32 bit number that you can do things with.

Sorry but like I said I am not a programmer, this is recollection from other similar threads where >16bit number was involved.

It's logical to me but I have never done it, sorry.

Ralph

May 18, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks,

That makes more sense. That is what I figured I would have to do..or something similar Thanks again, David

May 18, 2012
by dvdsnyd
dvdsnyd's Avatar

What I am really trying to understand is how to read the XLSB register.

msb = i2c_readAck();
lsb = i2c_readAck();
xlsb = i2c_readNak();
i2c_stop();

I tried the above code. I just added the xlsb bit, but I get 0 for a result, so this isn't how to do it...Any idea how to do it simply?

Thanks David

May 18, 2012
by pcbolt
pcbolt's Avatar

Hi David -

Just curious, are you still using this code to initiate the pressure conversion?

i2c_start(BMP085_addr + I2C_WRITE);     //BMP085 Address, Write Mode
i2c_write(0xF4);                        // Control Register
i2c_write(0x34);                        // Start Pressure Conversion
i2c_stop();

I think you may need to use:

i2c_start(BMP085_addr + I2C_WRITE);     //BMP085 Address, Write Mode
i2c_write(0xF4);                        // Control Register
i2c_write(0xF4);                        // 0x34 + (oss << 6) - see datasheet page 14 
i2c_stop();

Your code for reading sequential registers looks right. And yes you will need a 32-bit variable to contain the final result so the "Read_Short" code will need to be modified.

May 19, 2012
by dvdsnyd
dvdsnyd's Avatar

Hi pcbolt-

Yes, I was still using the first code at the time of testing last night. I started looking at the datasheet and as you pointed out, there is a bit more to do than just simply read the extra register and set the oversampling setting. Originally I had followed some code I found online that had the oversampling setting of 0 hard coded in. I am currently trying to change all of that.

Do you think it will be as simple as just sequentially reading the xlsb register after lsb? I can't quite tell going through the datasheet...but I would think I could read the extra register without doing the oversampling? I attempted to do that last night. Just tried to read the extra xlsb register and got 0, with an oversampling setting of 0. Or, do you think it needs to be in ultra high resolution mode(oversampling setting = 3) To read the xlsb register?

Thanks for pointing this out. I'll keep you all posted on what I can get done on it today Thanks again for all the help.

David

May 19, 2012
by Ralphxyz
Ralphxyz's Avatar

David what is the order of your reads? MSB, LSB then XLSB?

You might try changing the order XLSB, MSB then LSB.

Can you read them one at a time, I mean read one without the others to make sure you are getting a reading from each individual register.

Ralph

May 20, 2012
by dvdsnyd
dvdsnyd's Avatar

Hi all,

I think I have gotten the oversampling to correctly work. The data does not seem as noisy as it was before.

I think I am reading all the registers too. However, XLSB is always read as 0, except when I read through the calibration data. ( I haven't separated it out yet, so it must be reading jibberish...) I just don't understand why it would be 0 if it is suppose to extend the data. Obviously it doesn't extend it out that much...but Now it is personal, I just want to be able to get the data. All of the Arduino sample code reads the three registers pretty similarly to how I do it. But, I can't find anywhere that has readouts of xlsb or anyone experiencing my issue. I might try changing the way I read it, but it sure seems like it should work...I guess the value could be 0...but that seems pointless to me..

Thanks again,

David

May 20, 2012
by Ralphxyz
Ralphxyz's Avatar

So David, how are you going to deal/use the readings in an actual flight/launch?

Are you recording the readings to the EEPROM for recovery later?

If you are storing the readings could you do a launch to see what your readings are?

Or of course you could make up a vacuum chamber to simulate a launch.

Ralph

May 20, 2012
by dvdsnyd
dvdsnyd's Avatar

Ralph,

Thanks for taking an interest in my project. I will do my best to explain what I am attempting to do.

As the rocket sits on the pad, A baseline ground level pressure(altitude) will be established. As the rocket ascends pressure decreases. The microcontroller will poll pressure data until pressure starts to increase again. Which will be apogee9maximum altitude). I will have to do some filtering or something to help hone in on apogee a bit more, as the sensor doesn't read a steady pressure sitting on my desk- varies about 5 feet or so, maybe a bit less/more. But really probably good enough for me.

Once apogee has been established, the corresponding pressure will be converted into altitude above ground level. Then, in code the integer part of the altitude will be separated into it's individual digits. I will then using a beeper, beep out the individual digits of the maximum altitude until the unit is powered off, with a zero being a longer steady "beeeeep" and a 2 being a beep beep so 402 feet would be "beeped" back as (beep beep beep beep)pause(beeeeeep)pause(beep beep)

Fairly low tech. But this is just a first revision. I would like to be able to add accelerometers and gyros and a data logging system, so that more post processing could be done to analyze flight characteristics.

Also, with an accelerometer, you can work backwards to characterize a given rocket motor. Force = mass * acceleration, given the mass of the rocket and acceleration, and summing all of the forces( motor thrust, drag...) you can calculate the thrust of the motor at any given time.theoretically

So far I have the pressure senors working for the most part...I believe. I would like to figure out what is up with getting zeros for xlsb. But I probably have enough resolution for what I need. I think the oversampling is working too, as the data does not seem to be as noisy as single sampling. Also, I have been able to write the routine to beep out the altitude...so I really just need to put it all together

Thanks again, David

May 20, 2012
by dvdsnyd
dvdsnyd's Avatar

Hey guys, I changed the way I read the registers...Here is the code

for(i = 1; i <= 2; i++)
{
    dat[i] = i2c_readAck();

}

dat[3] = i2c_readNak();

i2c_stop();

msb = dat[1];
lsb = dat[2];
xlsb = dat[3];

Still the same thing...So it must just be what it is?...

David

June 19, 2012
by HansRoaming
HansRoaming's Avatar

I'm working on an Altimeter with my Nerdkit (MPX4115 + AD997ANZ) and this article related to noise I found really useful.

http://mbed.org/users/tkreyche/notebook/bmp085-pressure-sensor/

It's for the mbed MCU but it is working c code with a BMP085.

June 20, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks Hans,

I have seen that article before. I will have to go back and read it again and try to implement the filter that he talks about.

Are you building an altimeter for rocketry or some other application?

Thanks again!

David

June 22, 2012
by HansRoaming
HansRoaming's Avatar

It's part of learning how do do active stabilisation on a rocket using fuzzy logic, inspired by a fellow UK rocket fliers rocket.

Here's the schematic for what I'm using.

June 24, 2012
by dvdsnyd
dvdsnyd's Avatar

Hans,

Very impressive! Thanks for the links. I have searched many sites looking for rocket and electronics, and have not come across this one. Very cool.

What is the AD997ANZ. I have heard of the other chip. It is popular for rocket altimeters. I did a Google search on the AD997ANZ and just came across this thread. Is it another pressure sensor?

David

June 25, 2012
by HansRoaming
HansRoaming's Avatar

Ahh that would be a typo for the AD977ANZ, sorry, here's it product page.

The pressure sensor links to some noise reduction circuitry and is connected to an op amp running as a voltage follower. It then plugs into the 16bit ADC (upto 100ksps) which connects to the MCU using two lines for the request conversion and then SPI for the data transfer at approx 7Mhz. At the moment I'm just sampling at 640 samples per second but the sampler bandwidth allows you sleep the MCU and do a sample then transfer to keep the noise low and still do a high number of samples per second.

There is a temp sensor LM35 connected to the MCU and that also sleeps the MCU when using the 10 bit built in ADC.

The MCU connects using I2C to the EEPROM (24AA512) at 400Khz and writes an altitude update every 10th second which is averaged over 64 samples from the altimeter (640 samples per second). To save time I buffer writes into 128 bytes pages and write those out in one go as a page write takes 5ms, byte writes refresh the entire page so also take 5ms. So it is much quicker to just dump 128 bytes out the I2C as fast as one can and then let it refresh in its own time.

June 25, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks, I had a feeling it was an ADC :-D That is really impressive. From what it seems you aren't using any kind of real time clock? How are you able to get accurate time stamps for your data? I am very very new to electronics and am working up to designing a dual deploy data logging altimeter. I just etched the board for my simple apogee beeping altimeter using the BMP085 pressure sensor this last weekend. I am still having issues with the pressure sensor however, It has a high resolution mode that offers 19 bits of pressure data. I can't the xlsb register to read correctly, which holds the last 3 bits of data. It is an I2C protocol. From all the arduino code out on the internet and the help I have received here, it seems that I am doing it correctly. Sparkfun, where I got the breakout board thinks I may be truncating the data stream somehow. This is the code that I am using to read the registers. It is based on Peter Fleury's I2C protocol.

long BMP085_ReadPres(void)
{
    long pressure = 0;

    i2c_start(BMP085_addr + I2C_WRITE);         //BMP085 Address, Write Mode

    i2c_write(0XF4);                            // Control Register

    i2c_write(0X34 + (OSS<<6));             // Start Pressure Conversion

    i2c_stop();
    delay_ms(P_Conv_Time[OSS]);                 // Wait for conversion to end
    pressure = (long)BMP085_ReadShort(0XF6);    // Read pressure data registers
    pressure &= 0X0000FFFF;

    return pressure;

}

short BMP085_ReadShort(unsigned char address)
/*Read two sequential 8-bit registers, and return a 16 bit value
  INPUT: First register address to read data from-MSB
  OUTPUT:

*/

{   
    uint16_t data;
    uint8_t msb, lsb, xlsb;
    uint8_t dat[3];
    uint8_t i;

    i2c_rep_start(BMP085_addr + I2C_WRITE);

    i2c_write(address);

    i2c_rep_start(BMP085_addr + I2C_READ);

    printf_P(PSTR("------------------------\r\n"));

    for(i = 0; i < 2; i++)
    {
        dat[i] = i2c_readAck();

    }

    dat[2] = i2c_readNak();

    i2c_stop();

    msb = dat[0];
    lsb = dat[1];
    xlsb = dat[2];
    //msb = i2c_readAck();
    printf_P(PSTR("%d msb \r\n"), msb);
    //lsb = i2c_readAck();
    printf_P(PSTR("%d lsb \r\n"), lsb);
    //xlsb = i2c_readNak();
    printf_P(PSTR("%d xlsb \r\n"), xlsb);
    //i2c_stop();

    data = msb << 8;
    data |= lsb;

    return data;

I am not doing anything with the xlsb data right now. I am just trying to read it and display it to verify that I am getting some data. As of now all I get is 0. I use the same BMP085_ReadShort() routine to read temperature and the calibration coefficients. For some odd reason when I read the calibration coefficients, it outputs nonzero results for xlsb, but when I read the actual pressure registers I get zero. Any help from anyone would be so appreciated. I have sent an email to Bosch Sensortec as well. We will see if they can offer any insight. I would think I should get something for xlsb even at ground level. Or does anyone think that It would only be at higher altitudes that it would come into play?

Thanks a lot,

David

June 26, 2012
by HansRoaming
HansRoaming's Avatar

I would say your code should throw up something to send to the serial line.

At 19 bits I'm guessing you'll loose a lot to noise though so am not sure if a lower resolution would be ok.

What rockets you looking at flying this in? Model? HPR? Experimental?

For me the timestamps are not important as it was just a learning exercise so something that works and records me going up and down the stairs over 3 stories will be considered epic! :)

June 26, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks Hans,

That is what I am having problems with. I think it should throw something out. All I get is 0. Just doesn't seem to make sense. And it seems I am the only person on this planet experiencing this problem :-p

I don't know how much I would gain going from 16 bits to 19 bits. I may just say the heck with it. I really just need it to be accurate to within 5-10 feet. But the the fact that it isn't working properly bugs the heck out of me.

This first revision will be in small model and mid power rockets. It is my hope to eventually do dual deploy in larger rockets and experimental rockets. My Dad and I have spent the last 5-6 years experimenting with sugar rocket motors. We have designed a J motor that launched a rocket to close to a mile.

For me the timestamps are not important as it was just a learning exercise so something that works and records me going up and down the stairs over 3 stories will be considered epic! :)

I know how that works :-)

Are you planning to implement your altimeter into a rocket? Did you have some sort of vacuum chamber to calibrate your pressure sensor? I don't have a vacuum chamber, so that is why I chose the BMP085, it is per-calibrated.

June 27, 2012
by HansRoaming
HansRoaming's Avatar

It's all learning to eventually get to an active stabilisation system, either fins or gimballed mount.

If I was going to calibrate it then would probably fly alongside the Raven altimeter or something as my rocket buddies love this piece of kit.

Nice result on launching to a mile on a home made motor!

June 27, 2012
by Ralphxyz
Ralphxyz's Avatar

Nice result on launching to a mile on a home made motor!

Awesome, now I always thought rocketry was cool but the idea of making my own motor and launching a mile now that would be real satisfying.

Are you using a standard propellant or some thing custom made.

I assume you are using a custom nozzle also which would be of great interest.

Ralph

October 20, 2012
by dvdsnyd
dvdsnyd's Avatar

Hey guys! Sorry for the late response...You can see my apology thread here

Thanks for the compliments.

Hans, How is your system coming? I have seen the Raven altimeter. It is a nice piece of electronics...designed and built by a single guy...pretty incredible.

Ralph, Have you ever watched the movie "October Sky"? The motors we make are similar to those...in many ways, but much less dangerous as they portray it in the movie. The nozzles are usually either molded out of quickcrete, with some steel washers at the throat...the section in the middle of the convergence and divergence sections. Or for larger projects, machined out of graphite. This is an excellent picture of what some people have done...I don't have any of our stuff online yet...There are a few videos tucked away there...

Again, So sorry for the late response...been an exciting summer..hopefully I will get some hobby stuff in here more soon and be more active on the forums!

David

October 22, 2012
by Ralphxyz
Ralphxyz's Avatar

Hi David glad to have you back!!

Wow that Link is fascinating.

29,000 feet that is amazing.

Ralph

October 24, 2012
by dvdsnyd
dvdsnyd's Avatar

Thanks Ralph, good to be back!

It is amazing what you can do with a couple simple chemicals...one being basically sugar :-) I have a long ways to go before getting to that level, but someday I hope to!

David

May 29, 2013
by dvdsnyd
dvdsnyd's Avatar

Hi all once again, I have started up on my altimeter project once again...been over a year now...I designed an built a development platform. I still need to post a picture of it... It is working well, as far as I can tell. I tried to run my old pressure sensor code, with my old BMP085 sensor, and nothing happened. I moved everything over to my old dev board, and still nothing. I had ordered another BMP085 breakout from Sparkfun a while back. So I soldered some header pins on and away she went. Although I am getting weird pressure values, but the temperature looks pretty good. So I proceeded to rewrite the entire code...

I am still getting pressure values that are WAY OFF. My calibration coefficients look good. My integer equations give the right answer when I supply the Test values provided in the datasheet...except one equation, does not...if someone could explain, maybe this is where my problem lies...

The equations are as follows:

data_UP = 23843 //long
B3 = 422    //long
B7 = ((unsigned long)data_UP - (unsigned long)B3) * (50000UL);

When I use the following to display B7 to a terminal window:

printf_P(PSTR("%ul B7_Pres7 \r\n"), B7);

I get this for an answer:

52752l B7_Pres7

According to the datasheet, the correct answer is:

1171050000

Does anyone have any idea why this would be?

The weird thing is, the subsequent equations after that calculation yield the correct answer. So, the right answer is being calculated, but it seems I am not displaying it correctly... Thanks again! Dave

May 29, 2013
by pcbolt
pcbolt's Avatar

Dave -

Looks like it's printing the lower 16 bits of the correct answer and adding an 'l' (lower case L) to the end, so it's not recognizing the 'l' as an escape character. Try using...

printf_P(PSTR("%lu B7_Pres7 \r\n"), B7);

I haven't tested it but I read somewhere it might work.

May 30, 2013
by dvdsnyd
dvdsnyd's Avatar

pcbolt Thanks again for your help. your suggestion worked. Dave

Post a Reply

Please log in to post a reply.

Did you know that a microcontroller can measure an RC time constant? Learn more...