Arithmetic doesn't work

When I add two numbers together, nothing happens. This is the test code:

Vector3D OrientationBoard::GetGravityVector()
{
// returns gravity vector derived from accelerations
Vector3D ReturnVector;

double dblAxis1Grav;
double dblAxis2Grav;
double dblAxis3Grav;
double dblWork; // work variable
double dblWork2; // work variable

Serial.println("in GetGravityVector");

// gravity is the average of all the accelerations (more or less)

dblAxis1Grav = 0.0;
dblAxis2Grav = 0.0;
dblAxis3Grav = 0.0;

for (int intLoop = 0; intLoop < intDesiredHistoryDepth; intLoop++)
{

dblWork = (double)SensorStream[intLoop].Accel01;
// dblAxis1Grav += (double)SensorStream[intLoop].Accel01;
// dblAxis1Grav += dblWork; <==== doesn't work
// dblAxis1Grav = dblAxis1Grav + dblWork; <==== doesn't work
// dblAxis1Grav = dblWork; // this works, but it's not what I need
dblWork2 = dblAxis1Grav;
dblAxis1Grav = dblWork + dblWork2; // <=== doesn't work

dblAxis2Grav += (double)SensorStream[intLoop].Accel02;
// dblAxis2Grav = (float)7.0; <=== works

dblAxis3Grav += (double)SensorStream[intLoop].Accel03;

// flJunk = SensorStream[intLoop].Accel03;
// dblAxis3Grav = dblAxis3Grav + flJunk; // <=== doesn't work

Serial.println();
Serial.print(" intLoop: ");
Serial.print(intLoop);
// Serial.print(" flJunk: ");
// Serial.print(flJunk);
Serial.print(" SensorStream[intLoop].Accel01: ");
Serial.print(SensorStream[intLoop].Accel01);
Serial.print(" SensorStream[intLoop].Accel02: ");
Serial.print(SensorStream[intLoop].Accel02);
Serial.print(" SensorStream[intLoop].Accel03: ");
Serial.print(SensorStream[intLoop].Accel03);

Serial.print(" dblWork: ");
Serial.print(dblWork);
Serial.print(" dblAxis1Grav: ");
Serial.print(dblAxis1Grav);
Serial.print(" dblAxis2Grav: ");
Serial.print(dblAxis2Grav);
Serial.print(" dblAxis3Grav: ");
Serial.println(dblAxis3Grav);

}

dblAxis1Grav = dblAxis1Grav/(double)intDesiredHistoryDepth;
dblAxis2Grav = dblAxis2Grav/(double)intDesiredHistoryDepth;
dblAxis3Grav = dblAxis3Grav/(double)intDesiredHistoryDepth;

ReturnVector.Axis01 = dblAxis1Grav;
ReturnVector.Axis02 = dblAxis2Grav;
ReturnVector.Axis03 = dblAxis3Grav;

return ReturnVector;

}

Result:

in GetGravityVector

intLoop: 0 SensorStream[intLoop].Accel01: 0.00 SensorStream[intLoop].Accel02: 0.00 SensorStream[intLoop].Accel03: 0.00 dblWork: 0.00 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 1 SensorStream[intLoop].Accel01: 0.00 SensorStream[intLoop].Accel02: 0.00 SensorStream[intLoop].Accel03: 0.00 dblWork: 0.00 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 2 SensorStream[intLoop].Accel01: 0.00 SensorStream[intLoop].Accel02: 0.00 SensorStream[intLoop].Accel03: 2048.00 dblWork: 0.00 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 3 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: 0.00 SensorStream[intLoop].Accel03: 0.00 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 4 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.77 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 5 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.77 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 6 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.77 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 7 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.92 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 8 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.77 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00

intLoop: 9 SensorStream[intLoop].Accel01: 0.92 SensorStream[intLoop].Accel02: -0.92 SensorStream[intLoop].Accel03: -9.50 dblWork: 0.92 dblAxis1Grav: 0.00 dblAxis2Grav: 0.00 dblAxis3Grav: 0.00
***************** returned gravity vectors ******************

From roll board: (0.00, 0.00, 0.00)
From pitch board: (0.00, 0.00, 0.00)
Average of two vectors: (0.00, 0.00, 0.00)

***************** returned gravity vectors ****************

Same problem with this code:

double OrientationBoard::CalcAccVal( int intValueDesired) // returns a smoothed acceleration value
{
// returns a smoothed acceleration value
// intValue Desired acceleration value

double AccVal=0.0; // the returned accleration value
double sum;

Serial.println("Enter CalcAccVal");
Serial.print("intValueDesired: ");
Serial.print(intValueDesired);

Serial.println();
Serial.println("Weighted average loop");
Serial.println();

for (int intLoop = 0; intLoop < intDesiredHistoryDepth; intLoop++)
{

Serial.println();
Serial.println("Weights[intLoop]: ");
Serial.println(Weights[intLoop]);
Serial.println();

switch (intValueDesired)
{
case 1: // acceleration 1
AccVal+= SensorStream[intLoop].Accel01Weights[intLoop];
break;
case 2: // acceleration 2
AccVal+= SensorStream[intLoop].Accel02
Weights[intLoop];
break;
case 3: // acceleration 3
AccVal+= SensorStream[intLoop].Accel03Weights[intLoop];
break;
case 4: // rotation
AccVal+= SensorStream[intLoop].YawRate01
Weights[intLoop];
}

Serial.print("Weighted average loop: ");
Serial.println(AccVal);

}

// return the average

Serial.println();
Serial.print("Returned weighted average: ");
Serial.println(AccVal);
Serial.println("Leaving CalcACCVal");
Serial.println();

return AccVal;

}

Result:

Enter CalcAccVal
intValueDesired: 1
Weighted average loop

Weights[intLoop]:
0.22

Weighted average loop: 0.00

Weights[intLoop]:
0.18

Weighted average loop: 0.00

Weights[intLoop]:
0.14

Weighted average loop: 0.00

Weights[intLoop]:
0.11

Weighted average loop: 0.00

Weights[intLoop]:
0.09

Weighted average loop: 0.00

Weights[intLoop]:
0.07

Weighted average loop: 0.00

Weights[intLoop]:
0.06

Weighted average loop: 0.00

Weights[intLoop]:
0.05

Weighted average loop: 0.00

Weights[intLoop]:
0.04

Weighted average loop: 0.00

Weights[intLoop]:
0.03

Weighted average loop: 0.00

Returned weighted average: 0.00
Leaving CalcACCVal

Thanks for any help or ideas!

The output that you show does not appear to come from the code you posted.

Sorry -- fixed. There are two different subroutines with two different outputs. Both exhibit the same problem.

Also, Vector3D is a structure, defined as:

struct Vector3D {
double Axis01; // value along axis 1
double Axis02; // value along axis 2
double Axis03; // value along axis 3
};

and these values:

SensorStream[intLoop].Accel01, SensorStream[intLoop].Accel02, etc. are floats.

Can't get anything to sum them up! :cry:

I'm not sure exactly what the problem is, but there are some code issues.

Vector3D OrientationBoard::GetGravityVector()
{
 // returns gravity vector derived from accelerations
 Vector3D ReturnVector;

ReturnVector is a local vector. It goes out of scope at the end of the function. Yet, you have this:

   ReturnVector.Axis01 = dblAxis1Grav;
   ReturnVector.Axis02 = dblAxis2Grav;
   ReturnVector.Axis03 = dblAxis3Grav;
   
 
   return ReturnVector;
}

That won't pass anything useful back to the calling routine.

Adding some more Serial.print statements might help discover what the problem is with GetGravityVector.

The order that the two functions are called is not shown, and whether there are other places where you are returning local variables is also not known.

Thanks. That's a new on on me. I've never before heard that you can't use a local variable in a return value. See, for example, this from a C++ reference. It describes a function which returns the value of a local loop variable (i):

The following function searches through an array of integers to determine if a match exists for the variable number. If a match exists, the function match returns the value of i. If a match does not exist, the function match returns the value -1 (negative one).

int match(int number, int array[ ], int n)
{
int i;

for (i = 0; i < n; i++)
if (number == array*)*

  • return (i);*
  • return(-1);*
    }
    Also, this example from another C++ instruction site:
    // function example
    #include
    using namespace std;
    int addition (int a, int b)
    {
  • int r;*
  • r=a+b;*
  • return (r);*
    }
    This example clearly has a local variable returned as the value of the function. So, I'm not sure your comment is correct. Nevertheless, the problem with addition occurred before that, so the return value shouldn't have any effect on the addition problem. It's a very strange problem! Perfectly repeatable.
    Thanks for the comment.

Another bizarre note about this programme: If I add more Serial.print statements, it stops printing on the Serial line completely -- nothing shows up at all. It's as if there were a limit to the number of Serial.print statements you can have in the programme. So, for example, if I add 10 Serial.print statements, the programme will stop working. If I then REMOVE Serial.print statements from another part of the programme, it will work OK again. As I said, it's as if there were a limit of, say 137 Serial.print statements. Any time I exceed that, the programme freezes. I made up that number of 137. If the limit exists, it's much more than that, but I haven't counted the number of print statements I have.

Apropos of nothing, I just saw that PaulS is in Seattle. I graduated from Newport HS in Bellevue, Wa, right across the bridge. My brother lives in Bothell. ;D

Just a guess. I can't see your setup function so i don't know what baudrate you are using for the serial statements, but i don't see any delay() statements in your code, so you are probably sending serial data very frequently / fast, and maybee simply overloading the recieving end.

Adding and removing serial statements may be overloading the receive buffer, but that shouldn't stop the program from working. The data in excess of what the serial monitor can handle would simply be lost. The Arduino would have no idea that that had happened.

It's more likely that adding more Serial.print statements means adding more strings to the program, resulting in running out of memory for those strings, causing the program to overwrite some code, resulting in a program crash.

Returning 'ReturnVector' is valid as a "copy" of 'ReturnVector' will be returned on the stack.

Perhaps you could post a cleaned up version of both routines. Minus the conditional code and incorrect comments. In doing so you may see the problem. It would also be useful if you included the math formula you're attempting to implement.

PaulS,

Just as you can pass a struct by value to a function, a function can return a struct by value. It doesn't matter that the structure returned is a local variable, since the values of the structure elements are copied to the stack as the return value.

Of course, if the program were returning a pointer to a local variable, it would be a different story, and the results would be undefined.

Regards,

-Mike

//That won't pass anything useful back to the calling routine//
That's a common misconception amongst C noobs.
Confusing here the difference between a reference (or pointer) to a local variable and the variable itself.

Thanks for all the suggestions. Baud rate on the serial line is 19200. I've made some progress by eliminating Serial.print statements from the programme. It's still disconcerting to think that the system can't handle them, or, at the very least, warn you that you've used too many. I'm used to working on larger computers, so I've yet to discover all the hidden limitations of these microprocessors. Having said all that, it does make sense that large numbers of literal strings can eat up memory. Nevertheless, I'm using a 328 Mega board with tons of memory. According to the map on compilation, I'm only using about 1/4 of what's available.

As for formula, it's basically a weighted average:

Avg = sum ( weight(i) * value(i) ) where the sum of the weight(i) values is 1.

One thing that might be confusing you is that the Arduino has 3 kinds of memory - SRAM, Flash, and EEPROM.

The size reported by the compiler is the amount of flash memory you are using. EEPROM is not used, unless you explicitly use it. Character constants are loaded into SRAM.

So, even though their may be plenty of space available in Flash memory, you could have over-filled SRAM, with disastrous results. Unfortunately, the compiler does not tell you how much SRAM you are using.

Thanks! That's really helpful. It's consistent with everything I've seen. I thought something like that might be happening, as removing print statements from ANY part of the programme seemed to remedy. From what you've said, it wasn't the print statements per se, but the explanatory strings to explain what was being printed, e.g. Serial.print("The phase of the moon today is: ");
Serial.println(MoonPhase);

Any suggestions on what to do about it? Obviously, removing print statements would help. Is there any way to track how much of the memory I'm using? Could I add more memory and if I did would the compiler use it?

For the moment, I'll rip out a bunch of diagnostics and limit myself to debuggin in one small area at a time. Yuck. :slight_smile: As this type of problem could cause any imaginable type of strange behaviour, I expect that it's responsible for the inability to add numbers, as well.

Thanks again for the advice. I'll kill a bunch of print statements now. Any other suggestinos are welcome.

It's possible to put the constant strings in flash memory, instead of SRAM.
http://www.arduino.cc/en/Reference/PROGMEM

Accessing them, then, for printing is possible, but not entirely straightforward. There are requests pending to enable the print class to print strings directly from PROGMEM, but that is not possible yet.

As for adding more memory, no. The flash and SRAM memory are built into the various chips, and the amount of memory is a physical as well as logical limit. Adding more memory usually requires replacing the chip. That's one reason why there are so many Arduino variants.

As this type of problem could cause any imaginable type of strange behaviour, I expect that it's responsible for the inability to add numbers, as well.

Maybe, but I seriously doubt it. More likely some logic error that we can't see, yet, because we can't see enough output to trace it down yet.