Polling BMP085 Barometric Pressure Sensor with Interrupts?

I want to read the barometric pressure with a BMP085 pressure sensor, at (say) 5 second intervals.

I've checked the sensor with the simple sketch provided with the Adafruit_BMP085 library, and it works fine.

Ideally I want to poll the sensor with interrupts, so with this in mind I tried the example sketch from the TimerOne library, which just flashes an led, and that worked fine.

I then tried to patch the code for reading the BMP085 sensor into the ISR of the TimerOne example, but it doesn't work - it seems to get stuck in the ISR. I left the code for cycling the led for troubleshooting.

This is the sketch I tried:

#include <TimerOne.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>

Adafruit_BMP085 bmp;

float t;
unsigned int p; 
 
void setup() 
{
  pinMode(13, OUTPUT);    
  Serial.begin(9600);
  bmp.begin();
  
  Timer1.initialize(100000);
  Timer1.attachInterrupt(timerIsr);
}
 
void loop()
{
  Serial.print("Temperature = ");
  Serial.print(t);
  Serial.println(" C");
  Serial.print("Pressure = " );
  Serial.print(p * 7.5006168E-3);
  Serial.println(" mmHg");
}
 
/// --------------------------
/// Custom ISR Timer Routine
/// --------------------------
void timerIsr()
{
  digitalWrite( 13, digitalRead( 13 ) ^ 1 );
  t = bmp.readTemperature();
  p = bmp.readPressure();
}

I've got a feeling that I'm missing something regarding interrupts, and would be grateful for any suggestions, please.

Jim

You haven't said what the problem is (or even if there is one), but 't' and 'p' should be qualified "volatile".

I don't really see that a slowly changing parameter like barometric pressure really warrants an interrupt.

Why are you using an interrupt for this? I don't know the BMP085 library but chances are that it's not possible to call the routines within an ISR.

AWOL:
You haven't said what the problem is (or even if there is one)

The problem is that the program gets stuck in in the ISR and doesn't return (I did mention it in my original post).

I don't really see that a slowly changing parameter like barometric pressure really warrants an interrupt.

I agree, but I wanted to do other tasks in the meantime - a simple delay would tie the arduino up.

Jim

pylon:
Why are you using an interrupt for this?

Because I want to do other measurement tasks in the meantime.

I don't know the BMP085 library but chances are that it's not possible to call the routines within an ISR.

Hmm, I wonder if that's it - is there an easy way to tell without inspecting the library code?

Jim

Because I want to do other measurement tasks in the meantime.

I don't understand that answer.

I guess you never seen a solution like this:

#include <TimerOne.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>

Adafruit_BMP085 bmp;

float t;
unsigned int p; 
unsigned long last = 0;

void setup() {
  Serial.begin(9600);
  bmp.begin();
}

void loop() {
  if (millis() - last > 5000) {
    last = millis();
    t = bmp.readTemperature();
    p = bmp.readPressure();
    Serial.print("Temperature = ");
    Serial.print(t);
    Serial.println(" C");
    Serial.print("Pressure = " );
    Serial.print(p * 7.5006168E-3);
    Serial.println(" mmHg");
  }
  // do other stuff like your measurements
}

It's more or less your example but without using an interrupt and with masses of time to do other stuff.

jimford:
I agree, but I wanted to do other tasks in the meantime - a simple delay would tie the arduino up.

Try reading this:

You don't have to use delay in order to do things at a fixed interval.

Just ignore "JustTaGuy" - we are not mindless morons here.

Hi

There is a pin in the BMP085 module labeled EOC. This stands for End Of Conversion, and it essentially goes LOW when you request the BMP085 to sample something (pressure or temperature), and turns HIGH when the sensor module has finished sampling the requested value. We can take advantage of this by using pin change interrupts on a given digital pin.

So, simply connect the EOC pin from the BMP085 to, say, digital pin 4 of your arduino. Configure the appropriate PCINT registers to allow pin change interrupts on that pin, and handle the EOC event response from inside the ISR routine.

The following is to configure pin change interrupts on digital pin 4 (PD4)

PCICR |= (1 << PCIE2) /* Allow PCINT interrupts on port D */
PCMSK2 |= (1 << PCINT20) /* Allow PCINT on pin PD4 */

You should add the 2 lines above somewhere in your initialization routine/code. For a better, more in-depth explanation, you can check It's over 9000!!: Arduino (atmega328) Interrupt-based BMP085 (Barometric Pressure Sensor)

OK, so noted your blogspot article.

aamartir:
and handle the EOC event response from inside the ISR routine.

And just how do you propose to do this? By calling library routines that cannot operate within an ISR?

The code inside the ISR should ideally execute very fast. It is not advised for you to use i2c within the ISR (since your program will probably freeze). The solution I found was to set a flag within the ISR, and check this in your main loop (outside ISR) through a simple state machine.

void loop()
{
  /* The acquire() function acts as a state machine */
  if( bmp085.acquire())
  {
    Serial.println(bmp085.calculateDistance_cm());
  }
}

This would be the interrupt routine, where you simply set the End of Coversion flag. You want to avoid putting a lot of code within this function (Let the state-machine do the rest).

ISR( PCINT2_vect )
{
  if( (PIND & EOC_PIN_MASK) > 0 )
  {
      bmp085.eoc_received = 1;
  }
}

For a complete running code, please check http://github.com/aamartir/ISR_based_BMP085

use the metro library instead.