Jump to content
Sign in to follow this  
gwdeveloper

Stellaris Launchpad, OLED and BMP085

Recommended Posts

Just dropping off a super simple code snippet. This uses aBugsWorstNightmare's I2C API (http://forum.stellarisiti.com/topic/417-i2c-with-stellaris-lm4f120h5qr-working-driver-api-example-code/) to collect data from a BMP085 barometric pressure sensor. I've been rolling my own interrupt based I2C API to utilize the EOC on the BMP085 as well as another I2C device that has interrupt abilities. ABWN's API was super simple to use for testing.

post-2341-135135500649_thumb.png

In the picture, the last 2 digits of the barometric pressure look blurred simply from the sample rate being so fast. The MSP430 version of this software takes a substantial amount more time than the LM4F. The calculations are not yet optimized for the 32 bit mcu so things might get even faster.

 

#define SYSTICKHZ               1000
#define SYSTICKMS               (1000 / SYSTICKHZ)

/* bmp085 defines */
#define BMP085_ADDR		0x77
#define BMP085_CTRL_REG 0xF4
#define BMP085_TEMP_REG 0x2E
#define BMP085_PRESSURE_REG 0x34		// oss =0
//#define BMP085_PRESSURE_REG_OSS1 0x74	// oss =1, longer delays needed 7.5ms
//#define BMP085_PRESSURE_REG_OSS2 0xB4 	// oss =2, 13.5ms
//#define BMP085_PRESSURE_REG_OSS3 0xF4 	// oss =3, 25.5ms
#define BMP085_MSB_REG	0xF6
#define BMP085_LSB_REG	0xF7
#define BMP085_CONV_REG_XLSB 0xF8

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_ints.h"

#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/interrupt.h"
#include "driverlib/ssi.h"

#include "OLED_SSD1306.h"
#include "FontPack.h"

#include "utils/ustdlib.h"

#include "I2C_Stellaris_API.h"

void bmp_get_cal(void);

/* variables */
	// bmp085
	// cal data
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;
	// true temp
long ut;
long x1;
long x2;
long b5;
long bmp_temp = 0;
	//true pressure
long up;
long x3;
long b3;
unsigned long b4;
long b6;
unsigned long b7;
long p;
long bmp_pres = 0;
	// adjusters
long b6Temp;
long x1Temp;

char temp_buffer[8];
char pres_buffer[10];

char BMP085_calValues[22] = {0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char BMP085_tempValues[2] = {0x00, 0x00};
char BMP085_presValues[3] = {0x00, 0x00, 0x00};

void main(void)
{
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Configure SysTick for a periodic interrupt.
    //ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKHZ);
    //ROM_SysTickEnable();
    //ROM_SysTickIntEnable();

    ROM_IntMasterEnable();

    SSD1306PinSetup();
    SSD1306Init();
    clearScreen(0);
    clearScreen(1);

    I2CSetup(I2C0_MASTER_BASE, 0);

    bmp_get_cal();

    while(1)
    {
    	I2CRegWrite(I2C0_MASTER_BASE, BMP085_ADDR, BMP085_CTRL_REG, BMP085_TEMP_REG);
    	// replace with timer for 4.5ms delay
    	SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
    	I2CReadData(I2C0_MASTER_BASE, BMP085_ADDR, BMP085_MSB_REG, BMP085_tempValues, 2);
    	ut = (int)BMP085_tempValues[0] << 8 | (int)BMP085_tempValues[1];

    	I2CRegWrite(I2C0_MASTER_BASE, BMP085_ADDR, BMP085_CTRL_REG, BMP085_PRESSURE_REG);
    	// replace with timer for 4.5ms delay
    	SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
    	I2CReadData(I2C0_MASTER_BASE, BMP085_ADDR, BMP085_MSB_REG, BMP085_presValues, 3);
    	up = ((int)BMP085_presValues[0] << 16 | (int)BMP085_presValues[1] << 8 | (int)BMP085_presValues[2]) >> 8;

    	// calc true temp
    	x1 = (ut - ac6) * ac5 >> 15;
        x2 = (mc << 11) / (x1 + md);
        b5 = x1 + x2;
        bmp_temp = (b5 + 8) >> 4;

     	// calc true pressure
        b6 = b5 - 4000;

    	//x1 = (b2 * (b6 * b6) >> 12) >> 11; // won't work this way on the value line LSR_23 error
    	b6Temp = b6 * b6;
    	x1Temp = b2 * b6Temp;
    	x1Temp = x1Temp >> 12;
    	x1 = x1Temp >> 11;

    	x2 = (ac2 * b6) >> 11;
    	x3 = x1 + x2;

    	b3 = (ac1 * 4 + x3 + 2) >> 2;  // ????  so many 'corrections' on the web this one works though

    	x1 = ac3 * b6 >> 13;
    	x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
    	x3 = ((x1 + x2) + 2) >> 2;
    	b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;
    	b7 = ((unsigned long)up - b3) * 50000;

    	if (b7  < 0x80000000)
    	{ p = (b7 * 2) / b4;}
    	else {p = (b7 / b4) *2;}

    	x1 = (p >> 8) * (p >> 8);
    	x1 = (x1 * 3038) >> 16;
    	x2 = (-7357 * p) >> 16;
    	bmp_pres = p + ((x1 + x2 + 3791) >> 4);

			usprintf(temp_buffer, "%5d C", bmp_temp);
			stringDraw(0, 2, 0, (char *)temp_buffer);

			usprintf(pres_buffer, "%3d hPa", bmp_pres);
        	stringDraw(0, 3, 0, (char *)pres_buffer);

    	asm(" NOP");
    }
}

void bmp_get_cal(void)
{
    I2CReadData(I2C0_MASTER_BASE, BMP085_ADDR, 0xAA, BMP085_calValues, 22);

    ac1 = BMP085_calValues[0] << 8 | BMP085_calValues[1];
    ac2 = (int)BMP085_calValues[2] << 8 | (int)BMP085_calValues[3];
    ac3 = (int)BMP085_calValues[4] << 8 | (int)BMP085_calValues[5];
    ac4 = (int)BMP085_calValues[6] << 8 | (int)BMP085_calValues[7];
    ac5 = (int)BMP085_calValues[8] << 8 | (int)BMP085_calValues[9];
    ac6 = (int)BMP085_calValues[10] << 8 | (int)BMP085_calValues[11];
    b1 = (int)BMP085_calValues[12] << 8 | (int)BMP085_calValues[13];
    b2 = (int)BMP085_calValues[14] << 8 | (int)BMP085_calValues[15];
    mb = (int)BMP085_calValues[16] << 8 | (int)BMP085_calValues[17];
    mc = (int)BMP085_calValues[18] << 8 | (int)BMP085_calValues[19];
    md = (int)BMP085_calValues[20] << 8 | (int)BMP085_calValues[21];
}

void SysTickIntHandler(void)
{

}

 

Share this post


Link to post
Share on other sites

Hi,

 

excellent! Great to the the I2C API being used already!

 

Doing i.e.:

 

#define BMP085I2CPORT    I2C0_MASTER_BASE

 

...

 

I2CRegWrite(BMP085I2CPORT, BMP085_ADDR, BMP085_CTRL_REG, BMP085_TEMP_REG);

.... 

 

will result in an easy to re-use code (once your I2C interface needs to be changed).

 

aBUGsworstnightmare

 

P.S. Find the original Bosch Sensortec BMP085 API enclosed! 

API_BMP085.zip

Share this post


Link to post
Share on other sites

Yes, thank you for the code. Makes testing I2C devices on the Stellaris LP super easy.

 

Instead of:

#define BMP085I2CPORT    I2C0_MASTER_BASE

maybe, simply:

#define I2C0 I2C0_MASTER_BASE

 

so it becomes:

I2CRegWrite(I2C0, BMP085_ADDR, BMP085_CTRL_REG, BMP085_TEMP_REG);
I2CRegWrite(I2C0, ACC_ADDRESS , CTRL_REG1_A, 0X27);
I2CRegWrite(I2C0, MAG_ADDRESS , CTRL_REG4_A, 0X00);

...

 

Less to type and allows for easier use with multiple devices on the same bus.

Share this post


Link to post
Share on other sites

Yes, thank you for the code. Makes testing I2C devices on the Stellaris LP super easy.

 

Instead of:

#define BMP085I2CPORT    I2C0_MASTER_BASE

maybe, simply:

#define I2C0 I2C0_MASTER_BASE

 

so it becomes:

I2CRegWrite(I2C0, BMP085_ADDR, BMP085_CTRL_REG, BMP085_TEMP_REG);
I2CRegWrite(I2C0, ACC_ADDRESS , CTRL_REG1_A, 0X27);
I2CRegWrite(I2C0, MAG_ADDRESS , CTRL_REG4_A, 0X00);

...

 

Less to type and allows for easier use with multiple devices on the same bus.

 

Yes, just wanted to say that using a symbolic name makes code porting (re-using) much easier.

 

aBUGSworstnightmare

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×