Using Arduinowith the BMP180

Temperature and Pressure module

Dr. Padraig Houlahan

Dept. of Physics, Embry-Riddle Aeronautical University, Prescott, AZ.

Table of Contents

Using Arduino with GPS Modules

Working with GPS and OLED Displays

Software

Wiring the project

Operational considerations

Web Sources

Software Listing

Working with the BMP180 and OLED Displays

BMP180 temperature and pressure modules are relatively inexpensive and can be purchased for about $10 from Adafruit or Sparkfun – see fig.1 A set of header pins is provided for the user to solder before use.

Fig. 1 The Adafruit GPS module retails for about $40.

In addition, for this project we use Adafruit’s 32x128 LCD/OLED display (see figure 2) so we can display data in real time from the GPS module.

Fig. 2 A 32x128 OLED display – about $17.

Software

To work with these devices we used knowledge and expertise encapsulated in the form of libraries contributed to the community in the form of software libraries, example software, and related documentation. Some sources are vendors; others are hobbyists and enthusiasts. We used the Sparkfun libraries and examples as the basis of our sensor code segments, andAdafruit’s SSD1306 libraries and samples for the OLED display.

The software is included as an appendix to this document, and while not trivial, it does contain the typical elements one would expect for this kind of project.

The only issue encountered with the OLED libraries was that they were written to support general formats and needed to be configured to explicitly support the 32x128 pixel version used here, by adding the statement: #define SSD1306_128_32to the header file.

Since this particular display is small, in order to allow more information to be shown a simple counter was incremented every time through the main loop, and by using a modulus 2 calculation, two different pages could be displayed in turn.

Wiring the project

Wiring up the GPS and OLED modules to an Arduino UNO is straightforward, and shown in Fig. 3.

Fig. 3. Wiring the GPS and OLED display modules to the Arduino UNO

The wiring is as following:

SDL (green) and SDA (blue) support the I2C bus connecting to Arduino analog 4 and 5 ports

BMP180 Vin voltage (red) comes from the Arduino5v port

BMP180 GPS ground (black) connects to an Arduino GND port

OLED RST (orange) connects to Arduino digital port 4.

OLED voltage (red) is sourced from the Arduino 3.3v port

OLED Ground (black) connects to the remaining GND port

Operational considerations

This project works well and can detect pressure changes between a floor and a desktop - a compelling demonstration for students! The Arduino power sources seem to be adequate, and a 9v battery was sufficient to allow the system to operate independent of the USB cable.

Sample OLED display screens are shown in figure 4, but the possibilities of further customizations makes for ideal student projects.

Fig. 4. Different screen display produced by the included code. Customized alternating displays showtemperature data and pressure data.

Web Sources

BMP180 Support:

OLED Support:

Software Listing

[Heavily based on a sparkfun.com BMP180 example and OLED example from Adafruit.]

#include <SFE_BMP180.h>//sparkfun.com library

#include <SPI.h

#include <Wire.h

#include <Adafruit_GFX.h

#include <Adafruit_SSD1306.h>

#include <stdlib.h

SFE_BMP180 pressure;

#define ALTITUDE 2130.0 // Flagstaff

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

#define LOGO16_GLCD_HEIGHT 16

#define LOGO16_GLCD_WIDTH 16

staticconst unsigned char PROGMEM logo16_glcd_bmp[] =

{ B00000000, B11000000,

B00000001, B11000000,

B00000001, B11000000,

B00000011, B11100000,

B11110011, B11100000,

B11111110, B11111000,

B01111110, B11111111,

B00110011, B10011111,

B00011111, B11111100,

B00001101, B01110000,

B00011011, B10100000,

B00111111, B11100000,

B00111111, B11110000,

B01111100, B11110000,

B01110000, B01110000,

B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 32)

#error("Height incorrect, please fix Adafruit_SSD1306.h!");

#endif

int count;

void setup() {

Serial.begin(9600);

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)

display.display();

delay(1000);

// Clear the buffer.

display.clearDisplay();

// draw the first ~12 characters in the font

//testdrawchar();

display.display();

delay(2000);

display.clearDisplay();

// draw scrolling text

testscrolltext();

delay(2000);

display.clearDisplay();

// text display tests

display.setTextSize(1);

display.setTextColor(WHITE);

display.setCursor(0,0);

display.println("Embry-Riddle!");

display.display();

delay(2000);

if (pressure.begin())

Serial.println("BMP180 init success");

else

{

Serial.println("BMP180 init fail\n\n");

while(1); // Pause forever.

}

display.clearDisplay();

}

void loop() {

char status, buff[10];

String t_str, p_str;

double T,P,p0,a;

int res;

count = count+1;

Serial.println();

Serial.print("provided altitude: ");

Serial.print(ALTITUDE,0);

Serial.print(" meters, ");

Serial.print(ALTITUDE*3.28084,0);

Serial.println(" feet");

status = pressure.startTemperature();

if (status != 0)

{

delay(status);

status = pressure.getTemperature(T);

if (status != 0)

{

// Print out the measurement:

Serial.print("temperature: ");

Serial.print(T,2);

Serial.print(" deg C, ");

Serial.print((9.0/5.0)*T+32.0,2);

Serial.println(" deg F");

status = pressure.startPressure(3);

if (status != 0)

{

// Wait for the measurement to complete:

delay(status);

status = pressure.getPressure(P,T);

if (status != 0)

{

// Print out the measurement:

Serial.print("absolute pressure: ");

Serial.print(P,2);

Serial.print(" mb, ");

Serial.print(P*0.0295333727,2);

Serial.println(" inHg");

// The pressure sensor returns abolute pressure, which varies with altitude.

// To remove the effects of altitude, use the sealevel function and your current altitude.

// This number is commonly used in weather reports.

// Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.

// Result: p0 = sea-level compensated pressure in mb

p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)

Serial.print("relative (sea-level) pressure: ");

Serial.print(p0,2);

Serial.print(" mb, ");

Serial.print(p0*0.0295333727,2);

Serial.println(" inHg");

// On the other hand, if you want to determine your altitude from the pressure reading,

// use the altitude function along with a baseline pressure (sea-level or other).

// Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb.

// Result: a = altitude in m.

a = pressure.altitude(P,p0);

Serial.print("computed altitude: ");

Serial.print(a,0);

Serial.print(" meters, ");

Serial.print(a*3.28084,0);

Serial.println(" feet");

display.setTextSize(2);

display.setTextColor(WHITE);

display.setCursor(0,0);

dtostrf(T,4,2,buff);

t_str = buff;

t_str += " oC";

dtostrf(P,4,2,buff);

p_str = buff;

p_str += " mb";

res=count %2;

display.clearDisplay();

if (res ==0 ){

display.println("Temp: ");

display.setTextColor(BLACK, WHITE); // 'inverted' text

display.println(t_str);

}

else {

display.setTextColor(WHITE);

display.println("Abs. P: ");

display.println(p_str);

}

display.display();

}

elseSerial.println("error retrieving pressure measurement\n");

}

elseSerial.println("error starting pressure measurement\n");

}

elseSerial.println("error retrieving temperature measurement\n");

}

elseSerial.println("error starting temperature measurement\n");

delay(5000); // Pause for 5 seconds.

}

voidtestdrawchar(void) {

display.setTextSize(1);

display.setTextColor(WHITE);

display.setCursor(0,0);

for (uint8_t i=0; i < 168; i++) {

if (i == '\n') continue;

display.write(i);

if ((i > 0) & (i % 21 == 0))

display.println();

}

display.display();

}

voidtestscrolltext(void) {

display.setTextSize(2);

display.setTextColor(WHITE);

display.setCursor(10,0);

display.clearDisplay();

display.println("ERAU");

display.display();

display.startscrollright(0x00, 0x0F);

delay(2000);

display.stopscroll();

delay(1000);

display.startscrollleft(0x00, 0x0F);

delay(2000);

display.stopscroll();

delay(1000);

display.startscrolldiagright(0x00, 0x07);

delay(2000);

display.startscrolldiagleft(0x00, 0x07);

delay(2000);

display.stopscroll();

}