Cannot pass variable value

Hello,

I'm writing a program for my Arduino MEGA2560, and I just can't seem to figure out a solution for my problem.
I'm reading a series of data from incremental encoders, and calculating movement data from the received values.
I calculate the velocity, which just works fine by dividing the distance of two subsequent positions with the time passed from the beginning of the loop to the end.
I would like to calculate average velocity as well by summing the calculated velocities (Vel_Sum) and dividing the result with the number of the data (datacounter).
For some reason I cannot add the measured velocity to the summed value, it always stays 0.00.
I've tried several methods:
-adding the momentary velocity to a variable called Vel_Sum in the loop, and then dividing Vel_Sum with a datacounter value
-creating a function outside the loop which performs the summing and dividing
-creating two functions outside the loop one performing the summing and the other the dividing

I also tried to debug, by printing out the variables. Oddly enough, once it worked even after I commented out the print, but stopped working when I deleted the commented out line. I used several prints, and I couldn't determine if there was any crucial line which I should have left in.

The relevant code snippets (the Diff_Cal function calculates the distance between the subsequent positions using the received data):

//Variables for velocity
  float V0_A = 0.00;
  float V1_A = 0.00;
  unsigned long t0 = 0;
  unsigned long t1 = 0;
  unsigned long dt = 0;
  
//Max and average velocity
  float VMax_A = 0.00;
  
  int datacounter = 1;
  float VSum_A = 0.00;
  float VAvg_A = 0.00;

//Calculating Velocity
   float Vel_Cal (float Delta, float dt)  //This works
   {
     float V;
     V = Delta/dt;
     return V;
   }

//Calculating Average Velocity
   float Vel_Sum (float Vel_Sum, float Vel)
   {
     Vel_Sum = Vel_Sum + Vel;
     return Vel_Sum;
   }

   float Avg_Vel (float Vel_Sum, float datacount)
   {
     float Avg_Vel;
     Avg_Vel = Vel_Sum / datacount;
     return Avg_Vel;
   }

void loop()
{
  //Setting V0 to the previous value
  V0_A = V1_A;
  V0_B = V1_B;

  //Path
  Delta_A = Diff_Cal(Coord_A[0], Coord_A[1], Coord_A[2], X_A_Coord_prev, Y_A_Coord_prev, Z_A_Coord_prev);

  //Calculating velocity, acceleration and smoothness
  //Setting t1---------------
  t1 = millis();
      
  //Calculating elapsed time between two samples in milliseconds
  dt = abs(t1-t0);
  //-------------------------
      
  //Velocity
  V1_A = Vel_Cal(Delta_A, dt);
      
  //Average velocity
  VSum_A = Vel_Sum(VSum_A, V1_A);
  VAvg_A = Avg_Vel(VSum_A, datacounter);
      
  //Max Velocity
  if (V1_A > VMax_A) {VMax_A = V1_A;}
  
  Serial.print("V1_A: ");    
  Serial.print(V1_A, 2);
  Serial.print(", VSum_A: ");
  Serial.print(VSum_A, 2);
  Serial.print(", VAvg_A: ");
  Serial.print(VAvg_A, 2);
  Serial.print(", VMax_A: ");
  Serial.print(VMax_A, 2);
  Serial.print(", Acc1_A: "); 


  //Setting t1
  t0 = millis();
  datacounter = datacounter + 1;
}

The variables inside Vel_Sum and Avg_Vel should not be named the same as the function. Change them to something unique.

Vel_Cal doesn't protect against dt being zero, which I imagine will happen often as the two calls to millis() are close together (in time). I don't know what the Arduino does if you divide by zero, but it's not likely to be good...

I'm not sure that's the answer, just something I noticed with a quick scan.

You have two functions that essentially do nothing but a single math operation, like int add(int a, int b) { return a+b; }. That's not what functions are used for. The fact that you give functions and variables meaningful names doesn't change the fact that they're essentially redundant.

Also, you set t0 just before ending loop() and t1 just after its start. Unless Diff_Cal requires more thatn 1ms to run, t1 and t0 will be almost always the same.

tuxduino,
As I've mentioned I tried to perform the adding and the dividing in the loop, but the addition didn't change the value of the Vel_Sum variable. I've checked with serial.print lines, that before the addition the values were eg.

Vel_Sum = 0.00
Vel_A = 49.56

and after the addition, nothing has changed.
That's why I tried to write a function outside the loop, hoping that this would help.

// before setup() and loop()...

float Sum;
float Value;

// inside loop()
Value = (get value somehow)
Sum += Value

Sum must change unless Value is 0.0. If that's not happening, then the variables probably don't get the value you think they should get. Serial.println() around the addition should help. Please post the code without those two functions (BTW, they are named the same as two variables, which is a Bad Thing (TM)).

Here is the relevant code

//Before setup and loop
//Distance between two subsequent coordinates
float Delta_A = 0.00;  //calculated elsewhere
//Variables for velocity
  float V0_A = 0.00;
  float V1_A = 0.00;
  unsigned long t0 = 0;
  unsigned long t1 = 0;
  unsigned long dt = 0;
  
//Average velocity
  float datacounter = 1.00;
  float VSum_A = 0.00;
  float VAvg_A = 0.00;

//In the loop
//Calculating velocity, acceleration and smoothness
      //Setting t1---------------
      //Set t1
      t1 = millis();
      
      //Calculating elapsed time between two samples in seconds
      dt = abs(t1-t0);
      //-------------------------
      
      //Port A
        //Velocity
        V1_A = Delta_A / dt;

        //Average velocity
        VSum_A = VSum_A + V1_A;
        VAvg_A = VSum_A / datacounter;

As stated earlier, t0 and t1 are very likely the exact same value because of the way they're updated (during 1ms the uP can execute a lot of code), therefore dt is zero and dividing by zero produces NaN (not-a-number). Summing a float and a NaN probably produces the same float value, i.e. has the same practical effect of summing 0.
So the solution to your problem is to revise the logic behind t0 and t1.

HTH

There is plenty of code in the loop, but thanks for the warning.
Anyway the V1_A does change, so I still do not understand why VSum does not.

AFAICS, t1 is set at the end of loop(), while t0 is set at the beginning. loop() is executed continuously, i.e. as soon as it ends (i.e. returns) it's called again, so from the last instruction of one loop() invocation to the first instruction of the next invocation almost no time passes (some usecs probably). The situation I'm trying to describe is this:

unsigned long t0;
unsigned long t1;

void loop() {
    t0 = millis();

    Serial.println(t1 - t0);

    t1 = millis();
}

(Disclaimer: I might have overlooked something, so please take my replies just as suggestions...)

Anyway the V1_A does change,

I'd check this by putting Serial.println() in the right place(s).

I've tried the following variations, using serial.println -s as debug:
1)
Adding a fixed value to VSum_A in every loop
WORKS!

Adding a variable with a constant value to VSum_A in every loop
WORKS!

Adding V1_A to VSum_A in every loop. Checked the value of V1_A: it does change.
DOESN'T WORK!
VSum_A remains zero. Moreover, if I initialize VSum_A to a value other than 0, it still goes back to 0. There is absolutely no other mention of this variable in the code elsewhere, and every relevant variable is float.

Moreover, if I initialize VSum_A to a value other than 0, it still goes back to 0.

This happens because there is a failure to properly assign the new value to VSum_A, either because of overflow, underflow, or undefined operation. The value stored in the variable is the special value NaN, but the print function doesn't display NaN correctly. It displays it as 0.

@Batka

Good debugging session, but you're still avoiding the t0 vs. t1 problem. I think that's the problem (division by zero because dt = t1 - t0 is 0). PaulS seems to confirm this.

HTH

I will print out the t0 and t1 variables as soon as I can. But there is one thing I cannot understand.

Assuming, that t0 = t1, when I print out VSum_A and the add V1_A to it (about which I know that is NOT zero) and I print it VSum_A out again there should be some change, shouldn't there? Even if there is a division by zero in the next line (which would make VAvg_A N/A, but wouldn't affect VSum_A).

Is there any fault in the thinking above?

V1_A = Delta_A / dt;
VSum_A = VSum_A + V1_A;

How do you know V1_A is NOT (your words) zero ? V1_A becomes NaN because dt is zero and you cannot divide by zero. That's the problem (or so it seems).

In one of the debugging sessions I've printed out V1_A and VSum_A before and after the addition. And the velocity is a member of the parameters the microcontroller sends to serial (amongst others).

In one of the debugging sessions I've printed out V1_A and VSum_A before and after the addition. And the velocity is a member of the parameters the microcontroller sends to serial (amongst others).

So, you are changing the code, and not showing us the modified code or the output that you see. And, yet, you still want help. Sorry, by crystal ball is at the cleaners.

Batka:
In one of the debugging sessions I've printed out V1_A and VSum_A before and after the addition. And the velocity is a member of the parameters the microcontroller sends to serial (amongst others).

Show us that code and its serial output. Explain what you did in detail, or it will be difficult to help.

First of all, sorry if I made anything inappropriate.
In fact I did not changed the code since my first post, where I described everything as good as I could.
If I say, that I know that a variable doesn't change, that means that I've tested it.
And one more thing. There was no real change suggested, so the only modification would be a few Serial.print.

Of course I will send you the code and the output as soon as I can, and thank you for your efforts to help.

If I say, that I know that a variable doesn't change, that means that I've tested it.

That's not how it works when debugging through a forum :wink: We cannot trust you by the word (the same would be true if it was me asking a question, of course). It's not about faith, it's about the details, in which the devil, as everybody know, hides. :smiley: