Help with printAttitude not being declared

Hello all,

I'm struggling to understand why my code for "printAttitude" marked by "XXXXXXXX" below is telling me that I have not declared it in the scope. Am I missing a library? Also, nothing is being printed to serial monitor.

We are using a pro micro

Cheers and thanks
#TeamNoob

The whole code:

/*****************************************************************
LSM9DS1_Basic_I2C.ino

 
*****************************************************************/
// The SFE_LSM9DS1 library requires both Wire and SPI be
// included BEFORE including the 9DS1 library.
#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>

//////////////////////////
// LSM9DS1 Library Init //
//////////////////////////
// Use the LSM9DS1 class to create an object. [imu] can be
// named anything, we'll refer to that throught the sketch.
LSM9DS1 imu;

///////////////////////
// Example I2C Setup //
///////////////////////
// SDO_XM and SDO_G are both pulled high, so our addresses are:
#define LSM9DS1_M 0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG 0x6B // Would be 0x6A if SDO_AG is LOW

////////////////////////////
// Sketch Output Settings //
////////////////////////////
#define PRINT_CALCULATED
//#define PRINT_RAW
#define PRINT_SPEED 250 // 250 ms between prints

// Earth's magnetic field varies by location. Add or subtract 
// a declination to get a more accurate heading. Calculate 
// your's here:
// http://www.ngdc.noaa.gov/geomag-web/#declination
#define DECLINATION -8.58 // Declination (degrees) in Boulder, CO.

void setup() 
{
  
  Serial.begin(115200);
  
  // Before initializing the IMU, there are a few settings
  // we may need to adjust. Use the settings struct to set
  // the device's communication mode and addresses:
  imu.settings.device.commInterface = IMU_MODE_I2C;
  imu.settings.device.mAddress = LSM9DS1_M;
  imu.settings.device.agAddress = LSM9DS1_AG;
  // The above lines will only take effect AFTER calling
  // imu.begin(), which verifies communication with the IMU
  // and turns it on.
  if (!imu.begin())
  {
    Serial.println("Failed to communicate with LSM9DS1.");
    Serial.println("Double-check wiring.");
    Serial.println("Default settings in this sketch will " \
                  "work for an out of the box LSM9DS1 " \
                  "Breakout, but may need to be modified " \
                  "if the board jumpers are.");
    while (1)
      ;
  }
}

void loop()
{
  printGyro();  // Print "G: gx, gy, gz"
  printAccel(); // Print "A: ax, ay, az"
  printMag();   // Print "M: mx, my, mz"
  
  // Print the heading and orientation for fun!
  // Call print attitude. The LSM9DS1's magnetometer x and y
  // axes are opposite to the accelerometer, so my and mx are
  // substituted for each other.
  printAttitude(imu.ax, imu.ay, imu.az, -imu.my, -imu.mx, imu.mz);
  Serial.println();
  
  delay(PRINT_SPEED);
}

void printGyro()
{
  // To read from the gyroscope, you must first call the
  // readGyro() function. When this exits, it'll update the
  // gx, gy, and gz variables with the most current data.
  imu.readGyro();
  
  // Now we can use the gx, gy, and gz variables as we please.
  // Either print them as raw ADC values, or calculated in DPS.
  Serial.print("G: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcGyro helper function to convert a raw ADC value to
  // DPS. Give the function the value that you want to convert.
  Serial.print(imu.calcGyro(imu.gx), 2);
  Serial.print(", ");
  Serial.print(imu.calcGyro(imu.gy), 2);
  Serial.print(", ");
  Serial.print(imu.calcGyro(imu.gz), 2);
  Serial.println(" deg/s");
#elif defined PRINT_RAW
  Serial.print(imu.gx);
  Serial.print(", ");
  Serial.print(imu.gy);
  Serial.print(", ");
  Serial.println(imu.gz);
#endif
}

void printAccel()
{
  // To read from the accelerometer, you must first call the
  // readAccel() function. When this exits, it'll update the
  // ax, ay, and az variables with the most current data.
  imu.readAccel();
  
  // Now we can use the ax, ay, and az variables as we please.
  // Either print them as raw ADC values, or calculated in g's.
  Serial.print("A: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcAccel helper function to convert a raw ADC value to
  // g's. Give the function the value that you want to convert.
  Serial.print(imu.calcAccel(imu.ax), 2);
  Serial.print(", ");
  Serial.print(imu.calcAccel(imu.ay), 2);
  Serial.print(", ");
  Serial.print(imu.calcAccel(imu.az), 2);
  Serial.println(" g");
#elif defined PRINT_RAW 
  Serial.print(imu.ax);
  Serial.print(", ");
  Serial.print(imu.ay);
  Serial.print(", ");
  Serial.println(imu.az);
#endif

}

void printMag()
{
  // To read from the magnetometer, you must first call the
  // readMag() function. When this exits, it'll update the
  // mx, my, and mz variables with the most current data.
  imu.readMag();
  
  // Now we can use the mx, my, and mz variables as we please.
  // Either print them as raw ADC values, or calculated in Gauss.
  Serial.print("M: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcMag helper function to convert a raw ADC value to
  // Gauss. Give the function the value that you want to convert.
  Serial.print(imu.calcMag(imu.mx), 2);
  Serial.print(", ");
  Serial.print(imu.calcMag(imu.my), 2);
  Serial.print(", ");
  Serial.print(imu.calcMag(imu.mz), 2);
  Serial.println(" gauss");
#elif defined PRINT_RAW
  Serial.print(imu.mx);
  Serial.print(", ");
  Serial.print(imu.my);
  Serial.print(", ");
  Serial.println(imu.mz);
#endif
}

// Calculate pitch, roll, and heading.
// Pitch/roll calculations take from this app note:
// http://cache.freescale.com/files/sensors/doc/app_note/AN3461.pdf?fpsp=1
// Heading calculations taken from this app note:
// http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/Magnetic__Literature_Application_notes-documents/AN203_Compass_Heading_Using_Magnetometers.pdf
void printAttitude(
float ax, float ay, float az, float mx, float my, float mz)
{
  float roll = atan2(ay, az);
  float pitch = atan2(-ax, sqrt(ay * ay + az * az));
  
  float heading;
  if (my == 0)
    heading = (mx < 0) ? 180.0 : 0;
  else
    heading = atan2(mx, my);
    
  heading -= DECLINATION * PI / 180;
  
  if (heading > PI) heading -= (2 * PI);
  else if (heading < -PI) heading += (2 * PI);
  else if (heading < 0) heading += 2 * PI;
  
  // Convert everything from radians to degrees:
  heading *= 180.0 / PI;
  pitch *= 180.0 / PI;
  roll  *= 180.0 / PI;
  
  Serial.print("Pitch, Roll: ");
  Serial.print(pitch, 2);
  Serial.print(", ");
  Serial.println(roll, 2);
  Serial.print("Heading: "); Serial.println(heading, 2);
}

The code in question:

The Error message:

Libraries:

Post the actual error message(s) produced, please.
All of them.

Please use code tags when posting code. - you can edit your post to add them.

Miss matched braces, my guess.

Please read this:-
How to use this forum
Because your post is breaking the rules about posting code.

Looks to me like you aren't initializing your imu variable.

imu.begin()

But I'm no expert...

chipwitch:
Looks to me like you aren't initializing your imu variable.

imu.begin()

But I'm no expert...

You mean the imu.begin in setup?

That wouldn't account for a not declared in scope error.

It wouldn't? Your call to the printAttitude() function includes imu object parameters which was never initialized.

I'm a beginner too so I'm not sure...

The printAttitude function is defined as having six float parameters. If you're trying to call the function with an uninitialized object, the "float" you're sending is maybe some other type by default? A long? Just a guess.

I don't have the library in question, but the statements that precede the "begin" in setup() suggests to me that the class has multiple public variable members.
More than are probably desirable, IMO, but that's not the issue here, if the OP is to be believed.

Just downloaded the sparkfun class...

The variable members are type int16_t. printAttitude() is looking for floats, based on the OP code

class LSM9DS1
{
public:
	IMUSettings settings;
	
	// We'll store the gyro, accel, and magnetometer readings in a series of
	// public class variables. Each sensor gets three variables -- one for each
	// axis. Call readGyro(), readAccel(), and readMag() first, before using
	// these variables!
	// These values are the RAW signed 16-bit readings from the sensors.
	int16_t gx, gy, gz; // x, y, and z axis readings of the gyroscope
	int16_t ax, ay, az; // x, y, and z axis readings of the accelerometer
	int16_t mx, my, mz; // x, y, and z axis readings of the magnetometer
    int16_t temperature; // Chip temperature
	float gBias[3], aBias[3], mBias[3];
	int16_t gBiasRaw[3], aBiasRaw[3], mBiasRaw[3];

Sorry I did not follow the rules for posting on here. Does this new upload help understand?

So chip you're saying change int16_ ... to float16 ?

Thanks for giving it a look

So i need to find a function to replace printAttitude since it is not recognized here?

I posted the libraries. I looked through them but did not see printAttitude anywhere in them. I don't think all of of the libraries he has up are being used in this example but I might be wrong.

It's not defined in the sketch itself that I'm seeing. I don't think I'll be over to show the libraries bc it exceeds 9000 characters.

Now to throw a spanner in the works.....

I just downloaded and installed the "SparkFun_LSM9DS1" library, copied the code from the opening post exactly as posted, pasted it into my IDE, and it compiled fine with no errors or warnings. (Compiled for UNO with IDE V1.6.5) There was no need to move the offending function up before 'setup()' or provide a forward declaration. The compiler found it OK.

Sketch uses 10,652 bytes (33%) of program storage space. Maximum is 32,256 bytes.
Global variables use 807 bytes (39%) of dynamic memory, leaving 1,241 bytes for local variables. Maximum is 2,048 bytes.

Edit: I suspect that this is yet another IDE version issue.
@trburger, which version of the Arduino IDE are you using?

Thanks so much @Delta_G. I knew at one point to make sure everything was declared beforehand. Not having C in a few years and then being thrown a simple problem like that turn me upside down.
Moving ahead of the loop fixed the problem.Thanks again.

@OldSteve I'm running 1.6.8 so it does seem to be an issue. The other people I am working on this with had the same version so there was no telling.

trburger:
Thanks so much @Delta_G. I knew at one point to make sure everything was declared beforehand. Not having C in a few years and then being thrown a simple problem like that turn me upside down.
Moving ahead of the loop fixed the problem.Thanks again.

@OldSteve I'm running 1.6.8 so it does seem to be an issue. The other people I am working on this with had the same version so there was no telling.

By rights in C++ functions should be forward declared, so it's not a bad thing. Obviously it's just something that's been 'fixed' in the later IDE versions.

I don't like putting other functions before 'setup()' and 'loop()', because it makes them hard to find, but it's not hard to declare all functions at the beginning of the code, then define them later. I should too, but using V1.6.5 I've got lazy. :frowning:

Edit: But I'd better start doing it properly again now, or when I do eventually update the IDE, none of my current code will compile without messing around fixing it.