Cannot pass variable value

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:

Sorry for the long break, here is the complete sourcecode and I try to attach a screenshot from the output.
I removed any not intended Serial.print

#include <math.h>
#define PI 3.14159


//Pins
#define Pin_Ai_AT 2  //interrupt 0
#define Pin_B_AT 5
#define Pin_Ai_AS 3  //interrupt 1
#define Pin_B_AS 4
#define Pin_Ai_AZ 18  //interrupt 5
#define Pin_B_AZ 17
#define Pin_Ai_BT 19  //interrupt 4
#define Pin_B_BT 22
#define Pin_Ai_BZ 21  //interrupt 2
#define Pin_B_BZ 24
#define Pin_Ai_BS 20  //interrupt 3
#define Pin_B_BS 23

//Resolutions
#define ResTS 2048 // coefficient for EDeg to Deg conversion, the coefficient is: resolution/(360 * No of detected Edges)
#define ResZ 320

#define R_Z 6.99          //radius of the wheel used for depth measurement
#define Z_Dist 19.5      //Distance of the depth measuring unit from the origin of the port

//Port A, Encoder T variables
//Channels
volatile int Ch_A_AT = 0;
volatile int Ch_B_AT = 0;
//EAngle
float EAng_AT = 0;
//Angle (rad)
float Ang_AT = 0.00;
//--------------------------
//
//Port A, Encoder S variables
//Channels
volatile int Ch_A_AS = 0;
volatile int Ch_B_AS = 0;
//EAngle
float EAng_AS = 0;
//Angle (rad)
float Ang_AS = 0.00;
//--------------------------
//
//Port A, Encoder Z variables
//Channels
volatile int Ch_A_AZ = 0;
volatile int Ch_B_AZ = 0;
//EAngle
float EAng_AZ = 0;
//Angle (rad)
float Depth_AZ = 0.00;
//--------------------------
//
//Port B, Encoder T variables
//Channels
volatile int Ch_A_BT = 0;
volatile int Ch_B_BT = 0;
//EAngle
float EAng_BT = 0;
//Angle (rad)
float Ang_BT = 0.00;
//--------------------------
//
//Channels
volatile int Ch_A_BS = 0;
volatile int Ch_B_BS = 0;
//EAngle
float EAng_BS = 0;
//Angle (rad)
float Ang_BS = 0.00;
//--------------------------
//
//Port B, Encoder Z variables
//Channels
volatile int Ch_A_BZ = 0;
volatile int Ch_B_BZ = 0;
//EAngle
float EAng_BZ = 0;
//Angle (rad)
float Depth_BZ = 0.00;
//--------------------------
//
//Variables for path length calculation
float X_A_Coord_prev = 0.00;
float Y_A_Coord_prev = 0.00;
float Z_A_Coord_prev = 0.00;
float X_B_Coord_prev = 0.00;
float Y_B_Coord_prev = 0.00;
float Z_B_Coord_prev = 0.00;
float Delta_A = 0.00;
float Delta_B = 0.00;
float Path_A = 0.00;
float Path_B = 0.00;

//Variables for coordinates
  float Coord_A[3] = {0.00, 0.00, 0.00};
  float Coord_B[3] = {0.00, 0.00, 0.00};
  
//Variables for velocity, acceleration and smoothness
  float V0_A = 0.00;
  float V1_A = 0.00;
  float Acc0_A = 0.00;
  float Acc1_A = 0.00;
  float S_A = 0.00;
  float V0_B = 0.00;
  float V1_B = 0.00;
  float Acc0_B = 0.00;
  float Acc1_B = 0.00;
  float S_B = 0.00;
  unsigned long t0 = 0;
  unsigned long t1 = 0;
  unsigned long dt = 0;
  
//Max and average velocity and acceleration
  float VMax_A = 0.00;
  float AccMax_A = 0.00;
  float VMax_B = 0.00;
  float AccMax_B = 0.00;
  
  float datacounter = 1.00;
  float VSum_A = 0.00;
  float VAvg_A = 0.00;
  float AccSum_A = 0.00;
  float AccAvg_A = 0.00;
  float VSum_B = 0.00;
  float VAvg_B = 0.00;
  float AccSum_B = 0.00;
  float AccAvg_B = 0.00;
  
  //Variables for Economy of Motion
  float Eco_A = 0.00;
  float Eco_B = 0.00;
  
  //Variables for PC communication
  int PC_msg;
  
  //Variables for Time measurement
  unsigned long t_start = 0;
  float Time = 0.00;


void setup()
{
  //Preparing serial port
  Serial.begin(9600);
  Serial.flush();
  //Switching on pull-down resistors
  pinMode(Pin_Ai_AT,LOW);
  pinMode(Pin_B_AT,LOW);
  pinMode(Pin_Ai_AS,LOW);
  pinMode(Pin_B_AS,LOW);
  pinMode(Pin_Ai_AZ,LOW);
  pinMode(Pin_B_AZ,LOW);
  pinMode(Pin_Ai_BT,LOW);
  pinMode(Pin_B_BT,LOW);
  pinMode(Pin_Ai_BS,LOW);
  pinMode(Pin_B_BS,LOW);
  pinMode(Pin_Ai_BZ,LOW);
  pinMode(Pin_B_BZ,LOW);
  //Attaching interrupts
  attachInterrupt(0, detectChA_AT, CHANGE);
  attachInterrupt(1, detectChA_AS, CHANGE);
  attachInterrupt(5, detectChA_AZ, CHANGE);
  attachInterrupt(4, detectChA_BT, CHANGE);
  attachInterrupt(3, detectChA_BS, CHANGE);
  attachInterrupt(2, detectChA_BZ, CHANGE);
  //Printing header as start signal
  Serial.println();
  Serial.println("Time, X_A, Y_A, Z_A, Path_A, Vel_A, VAvg_A, VMax_A, Acc_A, AccAvg_A, AccMax_A, Smooth_A, Eco_A, X_B, Y_B, Z_B, Path_B, Vel_B, VAvg_B, VMax_B, Acc_B, AccAvg_B, AccMax_B, Smooth_B, Eco_B");
}

//interrupt routines
void detectChA_AT()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_AT);
  Ch_B = digitalRead(Pin_B_AT);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_AT--;
  } else {
    EAng_AT++;    
  }   
}

void detectChA_AS()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_AS);
  Ch_B = digitalRead(Pin_B_AS);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_AS--;
  } else {
    EAng_AS++;    
  }   
}

void detectChA_AZ()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_AZ);
  Ch_B = digitalRead(Pin_B_AZ);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_AZ--;
  } else {
    EAng_AZ++;    
  }   
}

void detectChA_BT()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_BT);
  Ch_B = digitalRead(Pin_B_BT);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_BT--;
  } else {
    EAng_BT++;    
  }   
}

void detectChA_BS()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_BS);
  Ch_B = digitalRead(Pin_B_BS);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_BS--;
  } else {
    EAng_BS++;    
  }   
}

void detectChA_BZ()
{
  int Ch_A = 0;
  int Ch_B = 0;
  
  Ch_A = digitalRead(Pin_Ai_BZ);
  Ch_B = digitalRead(Pin_B_BZ);
  
  if (Ch_A ^ Ch_B)
  {
    EAng_BZ--;
  } else {
    EAng_BZ++;    
  }   
}
//End of interrupt routines

//Functions
//Converting electronic degrees to radians
float EdegToRad (float Edeg)
{
  //Converting to radians: When powering up the device all trocars MUST be perpendicular to the plane of the encoders
  //Base equation of EDeg => Rad conversion: (Edeg * 2 * PI) / Res IF ALL edges are detected
  //As only every second edge is detected, the equation is: (Edeg * 2 * PI) / (Res / 2)
  float RadEAng;
  RadEAng = (Edeg * 4 * PI) / ResTS;
  return RadEAng;
}

//Compute depth from Z encoders
float EdegToDepth (float Edeg)
{
  //Computing depth
  float Depth;
  Depth = ((Edeg * 4 * PI) / ResZ) * R_Z;
  if (Depth != 0)
    Depth = Depth + Z_Dist;
  return Depth;  
}

//Compute coordinates (with the origin of the port)
//Computing coordinates using independent equations
void PortCoord (float *coord, float RadT, float RadS, float Depth)
{
  float P_x = 0;
  float P_y = 0;
  float P_z = 0;
  //Computing coordinates
  if (RadS == 0 && RadT == 0)
  {
    P_x=0;
    P_y=0;
    P_z=Depth;
  } else if (RadT == 0)
  {
   P_x = 0;
   P_y = Depth * sin(RadS);
   P_z = Depth * cos(RadS);
  } else if (RadS == 0)
  {
   P_x = Depth * sin(RadT);
   P_y = 0;
   P_z = Depth * cos(RadT);
  } else 
  {
   P_y = Depth * sin(atan(cos(RadT) * tan(RadS)));
   P_z = P_y / tan(RadS);
   P_x = P_z * tan(RadT);
  }
  //Generating result
  coord[0] = P_x;
  coord[1] = P_y;
  coord[2] = P_z;
}

I will attach the second part of the sourcecode in the next post (exceeded the 9500 character)

And the output is attached.

The second part:

float Diff_Cal (float X, float Y, float Z, float X_prev, float Y_prev, float Z_prev)
{
  float Delta;
  Delta = sqrt(pow(X-X_prev, 2) + pow(Y-Y_prev, 2) + pow(Z-Z_prev,2));
  return Delta;
}

//Calculating Motion Smoothness
float Smooth (float A0, float A1, float dt)
{
  float S;
  S = (A1-A0)/dt;
  return S;
}

void loop()
{
  //Checking Start Signal
  if (PC_msg = 0)
  {
  PC_msg = Serial.read();
  }  
  else if (PC_msg == 1)
  {
    t_start = millis();
    PC_msg = -1;
  }
  else if (PC_msg == 2)
  {
    PC_msg = 0;
  }
  
  //Setting V0 to the previous value
  V0_A = V1_A;
  V0_B = V1_B;
  
  //Setting A0 to the previous value
  Acc0_A = Acc1_A;
  Acc0_B = Acc1_B;
  
  //Calculating Radians and Depths from electronic degrees
  Ang_AT = EdegToRad(EAng_AT);
  Ang_AS = EdegToRad(EAng_AS);
  Depth_AZ = EdegToDepth (EAng_AZ);
  Ang_BT = EdegToRad(EAng_BT);
  Ang_BS = EdegToRad(EAng_BS);
  Depth_BZ = EdegToDepth (EAng_BZ);
  //Computing coordinates
      //Saving previous coordinates for path length calculation
      X_A_Coord_prev = Coord_A[0];
      Y_A_Coord_prev = Coord_A[1];
      Z_A_Coord_prev = Coord_A[2];
      X_B_Coord_prev = Coord_B[0];
      Y_B_Coord_prev = Coord_B[1];
      Z_B_Coord_prev = Coord_B[2];
      
      //Port A calculations
      //Coordinates
      PortCoord (Coord_A, Ang_AT, Ang_AS, Depth_AZ);
      //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);
      Path_A = Path_A + Delta_A;
      
      //Port B calculations
      //Coordinates
      PortCoord (Coord_B, Ang_BT, Ang_BS, Depth_BZ);
      //Path
      Delta_B = Diff_Cal(Coord_B[0], Coord_B[1], Coord_B[2], X_B_Coord_prev, Y_B_Coord_prev, Z_B_Coord_prev);
      Path_B = Path_B + Delta_B;
      
  //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;

        //Max Velocity
        if (V1_A > VMax_A) {VMax_A = V1_A;}
        
        //Acceleration
        Acc1_A = (2 * Delta_A)/ pow(dt, 2);
      
        //Average acceleration
        AccSum_A = AccSum_A + Acc1_A;
        AccAvg_A = AccSum_A / datacounter;
        
        //Max Acceleration
        if (Acc1_A > AccMax_A) {AccMax_A = Acc1_A;}
        
        //Smoothness
        S_A = Smooth(Acc0_A, Acc1_A, dt);
        
        //Economy of Motion
        Eco_A = Path_A / Time;
   
      //Port_B
        V1_B = Delta_B / dt;;
        
        //Acceleration
        Acc1_B = (2 * Delta_B)/ pow(dt, 2);
        
        //Smoothness
        S_B = Smooth(Acc0_B, Acc1_B, dt);
            
        //Average velocity
        VSum_B = VSum_B + V1_B;
        VAvg_B = VSum_B / datacounter;
      
        //Max Velocity
        if (V1_B > VMax_B) {VMax_B = V1_B;}

         //Average acceleration
        AccSum_B = AccSum_B + Acc1_B;
        AccAvg_B = AccSum_B / datacounter;
      
        //Max Acceleration
        if (Acc1_B > AccMax_B) {AccMax_B = Acc1_B;}
        
        //Economy of Motion
        Eco_B = Path_B / Time;

  //Writing coordinates to serial port Format: Time; X_A; Y_A; Z_A; Path_A; Vel_A; VAvg_A; VMax_A; Acc_A; AccAvg_A; AccMax_A; Smooth_A; Eco_A; X_B; Y_B; Z_B; Path_B; Vel_B; VAvg_B; VMax_B; Acc_B; AccAvg_B; AccMax_B; Smooth_B; Eco_B
  //Display angles (for debug)
  /*
  Serial.print("AT: ");
  Serial.print(EAng_AT, 2);
  Serial.print(" => ");
  Serial.print(Ang_AT, 2);
  Serial.print(", AS: ");
  Serial.print(EAng_AS, 2);
  Serial.print(" => ");
  Serial.print(Ang_AS, 2);
  Serial.print(", AZ: ");
  Serial.print(EAng_AZ, 2);
  Serial.print(" => ");
  Serial.print(Depth_AZ, 2);
  Serial.print(", BT: ");
  Serial.print(EAng_BT, 2);
  Serial.print(" => ");
  Serial.print(Ang_BT, 2);
  Serial.print(", BS: ");
  Serial.print(EAng_BS, 2);
  Serial.print(" => ");
  Serial.print(Ang_BS, 2);
  Serial.print(", BZ: ");
  Serial.print(EAng_BZ, 2);
  Serial.print(" => ");
  Serial.println(Depth_BZ, 2);
  //=========================
  */
  Serial.print(Time, 2);
  Serial.print(", ");
  Serial.print(Coord_A[0], 2);
  Serial.print(", ");
  Serial.print(Coord_A[1], 2);
  Serial.print(", ");
  Serial.print(Coord_A[2], 2);
  Serial.print(", ");
  Serial.print(Path_A, 2);
  Serial.print(", ");
  Serial.print(V1_A, 2);
  Serial.print(", ");
  Serial.print(VAvg_A, 2);
  Serial.print(", ");
  Serial.print(VMax_A, 2);
  Serial.print(", ");
  Serial.print(Acc1_A, 2);
  Serial.print(", ");
  Serial.print(AccAvg_A, 2);
  Serial.print(", ");
  Serial.print(AccMax_A, 2);
  Serial.print(", ");
  Serial.print(S_A, 2);
  Serial.print(", ");
  Serial.print(Eco_A, 2);
  Serial.print(", ");
  Serial.print(Coord_B[0], 2);
  Serial.print(", ");
  Serial.print(Coord_B[1], 2);
  Serial.print(", ");
  Serial.print(Coord_B[2], 2);
  Serial.print(", ");
  Serial.print(Path_B, 2);
  Serial.print(", ");
  Serial.print(V1_B, 2);
  Serial.print(", ");
  Serial.print(VAvg_B, 2);
  Serial.print(", ");
  Serial.print(VMax_B, 2);
  Serial.print(", ");
  Serial.print(Acc1_B, 2);
  Serial.print(", ");
  Serial.print(AccAvg_B, 2);
  Serial.print(", ");
  Serial.print(AccMax_B, 2);
  Serial.print(", ");
  Serial.print(S_B, 2);
  Serial.print(", ");
  Serial.println(Eco_B, 2);

  //Setting t1
  t0 = millis();
  Time = (t0 - t_start) / 1000.00;
  datacounter = datacounter + 1.00;
}

Sorry, I don't have the time to read all of the code right now, but I'd like to concentrate on the bits I've been pointing you at (t1, t0 and the fact that dt is probably zero, leading to a NaN when calculating V1_A).
Can you put something like this in the code and report the output:

//Velocity
Serial.print("Delta_A=");
Serial.println(Delta_A);
Serial.print("dt=");
Serial.println(dt);
V1_A = Delta_A / dt;
Serial.print("V1_A=");
Serial.println(V1_A);

Sure.

Here is the code:

//Velocity
        Serial.print("Delta_A=");
        Serial.println(Delta_A);
        Serial.print("dt=");
        Serial.println(dt);
        V1_A = Delta_A / dt;
        Serial.print("V1_A=");
        Serial.println(V1_A);
        //Average velocity
        VSum_A =+ V1_A;
        VAvg_A = VSum_A / datacounter;

The output:

Delta_A=14.03
dt=1
V1_A=14.03
14.98, 13.81, -10.42, -52.38, 526.36, 14.03, 0.18, 23.61, 28.06, 0.00, 47.22, 3.77, 35.14, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00

dt is not zero, although it might be wiser to use micros() instead of millis().

dt == 1 means you're risking a divide-by-zero error.

I still think there might be a logic error in how you treat t0 and t1.

At the end of loop() you have:

 //Setting t1
  t0 = millis();
  Time = (t0 - t_start) / 1000.00;
  datacounter = datacounter + 1.00;

The comment refers to t1, while the code sets t0, but that may be a copy-n-paste leftover.
The important thing however is that you're not sampling anything (or so it seems to me...)

Earlier in loop() you have instead:

//Calculating elapsed time between two samples in seconds
dt = abs(t1-t0);

but t0 is just the millis() value of the previous execution of loop() (i.e. a few usecs ago). Please understand that after the last instruction of loop(), the loop() function is immediately called again.

You probably need a previous_millis variable and use it like this (untested):

void loop() {
    ///... many calculations...

    dt = millis() - previous_millis;
    previous_millis = millis();

    V1_A = Delta_A / dt;

    // etc.
}

Just like you have prev_coord, you need to have prev_millis.

My 2 cents as usual, HTH.

So I've switched to micros() and it seems it does work, so I would like to thank you very very much.
I have one more question though:
The function micros() will overturn after about 70 min. I guess that will corrupt data in a few cycles. Is there any way to avoid this?

The function micros() will overturn after about 70 min.

You mean overflow.

I guess that will corrupt data in a few cycles.

Why would you guess that? It is not true.

Is there any way to avoid this?

There is nothing to avoid.

The reason I guessed that:
When the one of the micro() variables reach 2^32 the next one will be a relatively small number. That means that dt will be pretty big seeming as if the cycle would have taken for about 70 minutes. That could corrupt the velocity and acceleration values. That's why.

My watch rolls over every night. I never have problems when that happens.

t0 = micros();
// do a bunch of stuff that takes time
t1 = micros();

dt = t1 - t0; // dt will be correct, even if micros rolled over between the two readings

(As long, of course, as the "takes time" stuff takes less than 70 minutes. If it takes longer than that, micros is not appropriate).

Just for the sake of simplicity let's say that micros() will roll over after 100 usec. In this case a worst case scenario for the code is:
t0 = micros(); // t0=100

V1 = Delta/dt

t1 = micros(); // t1 = 10

dt = abs(t1 - t0); //dt = 90 --> this will generate a bad data in the next cycle, as the dt is 10 usec and not 90

Of course there is a chance that I am wrong, but please show me where.

Just for the sake of simplicity let's say that micros() will roll over after 100 usec

OK.

t0 = micros(); // t0=100

OK.

t1 = micros(); // t1 = 10

OK.

dt = abs(t1 - t0); //dt = 90 --> this will generate a bad data in the next cycle, as the dt is 10 usec and not 90

No. The abs() function is silly. t0 and t1 are (supposed to be) unsigned. Time marches forward, so t1 will always be greater than t0, even when it isn't.

So, when t1 is 10 and t0 is 100, 10 - 100 is 10. It is not -90, because the values are unsigned. The subtraction work. Don't worry about it.

OK, I think I got it. Tuxduino, PaulS: Thank you very much for helping me, you've been a tremendous help for me.
I think we can flag this problem solved.Oh, and sorry if I was a bit "slow" sometimes.
Thank you very much.

P.S.: Just my curiosity: If we assume that using millis() caused a division by zero, how that affected the VSum variable and still displayed a correct value for V1_A?