NAN error for altitude

#include <Wire.h>
#include <MS5611.h>
#include "I2Cdev.h"
#include "MPU6050.h"
#include <SPI.h>
#include <SD.h>
#include <Servo.h>

Servo myServo; 
int state = 0;
unsigned long time;
const int chipSelect = 4;
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high
#define OUTPUT_READABLE_ACCELGYRO
int16_t ax, ay, az;
int16_t gx, gy, gz;

MS5611 ms5611;
double referencePressure;
#define LED_PIN 13
bool blinkState = false;

void setup()
{
  myServo.attach(9);
  myServo.write(0);
  // join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif


  Serial.begin(9600);

  // Initialize MS5611 sensor
  Serial.println("Initialize MS5611 Sensor");

  while (!ms5611.begin())
  {
    Serial.println("Could not find a valid MS5611 sensor, check wiring!");
    delay(500);
  }

  // Get reference pressure for relative altitude
  referencePressure = ms5611.readPressure();

  // Check settings
  checkSettings();

  // initialize device
  //   Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  //   Serial.println("Testing device connections...");
  //  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  pinMode(LED_PIN, OUTPUT);

  //    Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {// see if the card is present and can be initialized:
    // Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  // Serial.println("card initialized.");

}

void checkSettings()
{
  // Serial.print("Oversampling: ");
  // Serial.println(ms5611.getOversampling());
}

void loop()
{
  
  

  // read raw accel measurements from device
  accelgyro.getAcceleration(&ax, &ay, &az);

  // Read raw pressure and temp values
  uint32_t rawTemp = ms5611.readRawTemperature();
  uint32_t rawPressure = ms5611.readRawPressure();

  // Read true temperature & Pressure
  double realTemperature = ms5611.readTemperature();
  long realPressure = ms5611.readPressure();

  // Calculate altitude
  float absoluteAltitude = ms5611.getAltitude(realPressure);
  float relativeAltitude = ms5611.getAltitude(realPressure, referencePressure);


  //change variables to strings
  String comma = String (',');
  String altitude = String (ms5611.getAltitude(realPressure)); //absoloute altitude in meters.
  String temp = String ( ms5611.readTemperature()); //real temp in degrees, may over read initially, will take time for sensor to stabilize.
  String realpressure = String (ms5611.readPressure()); // pressure in pascals
  String accelXraw = String (ax); // raw accel in X. Divide by 2048 to get a "G" reading.
  String timer = String (millis()); //puts a millis time stamp on each string.
  //make a big string containing above strings
  String Baro_data = String  (altitude + comma + temp + comma + realpressure + comma + accelXraw + comma + timer) ;

  Serial.println (Baro_data);
  //delay(500);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(Baro_data);//put Baro_data on the SD card
    dataFile.close();

    if (millis() > 10000) //change this number to change alarm delay (1s = 1000ms)
    { tone (8, 1000); // change the second number to alter the tone of the peizo alarm



    }
    else {
      noTone(8);
    }

  }
  if(ms5611.getAltitude(realPressure) >= 1){
    myServo.write(90);
  }
  else{
    myServo.write(0);
  }
}

The code uploads correctly but whenever I use the serial monitor it shows NAN for altitude and the only numbers that seem to work are the milliseconds and the rotation monitor. Any help to correct this would be awesome! Thanks!

Why are you doing all that conversion to Strings when it is totally unnecessary ?

What do you see if you print ms5611.getAltitude(realPressure) ?

what do you mean?

What don't you understand ?

  • there is no need to convert everything to Strings as far as I can see
  • printing the value will show straight away what, if anything is being returned by the function

so just delete the part that says
//change variables to strings String comma = String (','); String altitude = String (ms5611.getAltitude(realPressure)); //absoloute altitude in meters. String temp = String ( ms5611.readTemperature()); //real temp in degrees, may over read initially, will take time for sensor to stabilize. String realpressure = String (ms5611.readPressure()); // pressure in pascals String accelXraw = String (ax); // raw accel in X. Divide by 2048 to get a "G" reading. String timer = String (millis()); //puts a millis time stamp on each string. //make a big string containing above strings String Baro_data = String (altitude + comma + temp + comma + realpressure + comma + accelXraw + comma + timer) ;

If you delete all of that then the sketch won't work so don't do it yet

I would suggest that you use the sprintf() function to put all of the values read from the ms5611 into a buffer then you can use that buffer when you want to output them ?

Have you tried printing the altitude as I suggested ?

Try that before changing the Strings as you don't have to change them as long as the altitude is correct, which I suspect it won't be. I note that the altitude depends on the value of realPressure so try printing that too

What do you mean by printing? I am using pre built code that I edited, and I am still learning parts of Arduino.

Serial.println (Baro_data);
That line of code prints the value of the Baro_data String after it has been built by concatenating the elements together.

I am suggesting that you print ms5611.getAltitude(realPressure) and realPressure. Do it before //change variables to strings

If the altitude is wrong then it will be wrong after converting to a String and you will need to investigate the problem

#include <Wire.h>
#include <MS5611.h>
#include "I2Cdev.h"
#include "MPU6050.h"
#include <SPI.h>
#include <SD.h>
#include <Servo.h>

Servo myServo; 
int state = 0;
unsigned long time;
const int chipSelect = 4;
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high
#define OUTPUT_READABLE_ACCELGYRO
int16_t ax, ay, az;
int16_t gx, gy, gz;

MS5611 ms5611;
double referencePressure;
#define LED_PIN 13
bool blinkState = false;

void setup()
{
  myServo.attach(9);
  myServo.write(0);
  // join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif


  Serial.begin(9600);

  // Initialize MS5611 sensor
  Serial.println("Initialize MS5611 Sensor");

  while (!ms5611.begin())
  {
    Serial.println("Could not find a valid MS5611 sensor, check wiring!");
    delay(500);
  }

  // Get reference pressure for relative altitude
  referencePressure = ms5611.readPressure();

  // Check settings
  checkSettings();

  // initialize device
  //   Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  //   Serial.println("Testing device connections...");
  //  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  pinMode(LED_PIN, OUTPUT);

  //    Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {// see if the card is present and can be initialized:
    // Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  // Serial.println("card initialized.");

}

void checkSettings()
{
  // Serial.print("Oversampling: ");
  // Serial.println(ms5611.getOversampling());
}

void loop()
{
  
  

  // read raw accel measurements from device
  accelgyro.getAcceleration(&ax, &ay, &az);

  // Read raw pressure and temp values
  uint32_t rawTemp = ms5611.readRawTemperature();
  uint32_t rawPressure = ms5611.readRawPressure();

  // Read true temperature & Pressure
  double realTemperature = ms5611.readTemperature();
  long realPressure = ms5611.readPressure();

  // Calculate altitude
  float absoluteAltitude = ms5611.getAltitude(realPressure);
  float relativeAltitude = ms5611.getAltitude(realPressure, referencePressure);

  Serial.println(ms5611.getAltitude(realPressure));
  //change variables to strings
  String comma = String (',');
  String altitude = String (ms5611.getAltitude(realPressure)); //absoloute altitude in meters.
  String temp = String ( ms5611.readTemperature()); //real temp in degrees, may over read initially, will take time for sensor to stabilize.
  String realpressure = String (ms5611.readPressure()); // pressure in pascals
  String accelXraw = String (ax); // raw accel in X. Divide by 2048 to get a "G" reading.
  String timer = String (millis()); //puts a millis time stamp on each string.
  //make a big string containing above strings
  String Baro_data = String  (altitude + comma + temp + comma + realpressure + comma + accelXraw + comma + timer) ;

  Serial.println (Baro_data);
  //delay(500);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(Baro_data);//put Baro_data on the SD card
    dataFile.close();

    if (millis() > 10000) //change this number to change alarm delay (1s = 1000ms)
    { tone (8, 1000); // change the second number to alter the tone of the peizo alarm



    }
    else {
      noTone(8);
    }

  }
  if(ms5611.getAltitude(realPressure) >= 1){
    myServo.write(90);
  }
  else{
    myServo.write(0);
  }
}

does this look good?

Whenever I uploaded the code I got this:
->Initialize MS5611 Sensor
->nan
->NAN, -134.24, -10968,-388, 2174
->nan
and that repeats over and over

It certainly seems that pressure is Not A Number

Try adding these lines

  Serial.print("realPressure = ");
  Serial.println(realPressure);
  Serial.print("ms5611.getAltitude(realPressure) = ");
  Serial.println(ms5611.getAltitude(realPressure));

This may show whether the value of realPressure is the problem

I assume I put that above the variables into strings in void loop?

It still says that altitude is NAN

What about realPressure ?

realPressure shows up as -10968 like it did previously

That sounds very wrong

Why would realPressure be a negative number with such a large value, but bear in mind I have no experience of the hardware that you are using !

Have you any idea what range of values the pressure is likely to have ?

Just out of interest try changing the print statement to this

  Serial.print("ms5611.getAltitude(1000) = ");
  Serial.println(ms5611.getAltitude(1000));

What do you get for altitude now ?

I got
->ms5611.getAltitude(1000) = 25921.43
->NAN,-134.24,-10968,-356,2174

Is there anything I did wrong with the code?

#include <Wire.h>
#include <MS5611.h>
#include "I2Cdev.h"
#include "MPU6050.h"
#include <SPI.h>
#include <SD.h>
#include <Servo.h>

Servo myServo; 
int state = 0;
unsigned long time;
const int chipSelect = 4;
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high
#define OUTPUT_READABLE_ACCELGYRO
int16_t ax, ay, az;
int16_t gx, gy, gz;

MS5611 ms5611;
double referencePressure;
#define LED_PIN 13
bool blinkState = false;

void setup()
{
  myServo.attach(9);
  myServo.write(0);
  // join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif


  Serial.begin(9600);

  // Initialize MS5611 sensor
  Serial.println("Initialize MS5611 Sensor");

  while (!ms5611.begin())
  {
    Serial.println("Could not find a valid MS5611 sensor, check wiring!");
    delay(500);
  }

  // Get reference pressure for relative altitude
  referencePressure = ms5611.readPressure();

  // Check settings
  checkSettings();

  // initialize device
  //   Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  //   Serial.println("Testing device connections...");
  //  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  pinMode(LED_PIN, OUTPUT);

  //    Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {// see if the card is present and can be initialized:
    // Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  // Serial.println("card initialized.");

}

void checkSettings()
{
  // Serial.print("Oversampling: ");
  // Serial.println(ms5611.getOversampling());
}

void loop()
{
  
  

  // read raw accel measurements from device
  accelgyro.getAcceleration(&ax, &ay, &az);

  // Read raw pressure and temp values
  uint32_t rawTemp = ms5611.readRawTemperature();
  uint32_t rawPressure = ms5611.readRawPressure();

  // Read true temperature & Pressure
  double realTemperature = ms5611.readTemperature();
  long realPressure = ms5611.readPressure();

  // Calculate altitude
  float absoluteAltitude = ms5611.getAltitude(realPressure);
  float relativeAltitude = ms5611.getAltitude(realPressure, referencePressure);

Serial.print("ms5611.getAltitude(1000) = ");
  Serial.println(ms5611.getAltitude(1000));
  
  //change variables to strings
  String comma = String (',');
  String altitude = String (ms5611.getAltitude(realPressure)); //absoloute altitude in meters.
  String temp = String ( ms5611.readTemperature()); //real temp in degrees, may over read initially, will take time for sensor to stabilize.
  String realpressure = String (ms5611.readPressure()); // pressure in pascals
  String accelXraw = String (ax); // raw accel in X. Divide by 2048 to get a "G" reading.
  String timer = String (millis()); //puts a millis time stamp on each string.
  //make a big string containing above strings
  String Baro_data = String  (altitude + comma + temp + comma + realpressure + comma + accelXraw + comma + timer) ;

  Serial.println (Baro_data);
  //delay(500);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(Baro_data);//put Baro_data on the SD card
    dataFile.close();

    if (millis() > 10000) //change this number to change alarm delay (1s = 1000ms)
    { tone (8, 1000); // change the second number to alter the tone of the peizo alarm



    }
    else {
      noTone(8);
    }

  }
  if(ms5611.getAltitude(realPressure) >= 1){
    myServo.write(90);
  }
  else{
    myServo.write(0);
  }
}

Thanks for all of the help!!!
The pressure should also be at around 99kpa

Hi,
What model Arduino are you using?

If you google

ms5611 arduino altimeter

You get;

Which may be of help.

It would be better for you to learn by starting at basics, use the examples supplied with the libraries and google.
From what I can see of the link I have posted, this is a very concise tutorial on how to get altitude.

Tom... :grinning: :+1: :coffee: :australia:

Arduino Uno

So the problem seems to be the value of realPressure

By using a false value of 1000 the altitude function returns a value, albeit a false one. Looking at your code, you have multiple variables named realPressure. That isn't going to end well !

I am short of time but start by commenting out this line

String realpressure = String (ms5611.readPressure()); // pressure in pascals 

and substituting this line

  String Baro_data = String  (altitude + comma + temp + comma + String(realpressure) + comma + accelXraw + comma + timer) ;

I am not sure whether it will even compile because I can't try it