Go Down

### Topic: Problem: subraction giving very strange results (Read 2541 times)previous topic - next topic

#### ned112

##### Jun 05, 2012, 10:26 pm
Guys I'm having a strange problem with my code.
Basically I'm performing the same operation in a loop, but after the first time I got wrong values back.
The strange part is the vector subtraction Kreference[]-Kstate[], this gives strange results.
In the first run the result is correct but as you can see from the log from the serial port after the first run the results are wrong.
Basically Kreference-Kstate returns four 0. while Kreference is {0,-0.57,0,0.57}. Kstate is {0,0,0,0}.
All the vector are initialized as float.

Code: [Select]
`void loop(){  Serial.println("Press one button to start moving");  beta = state[2];//maybe unuseful  rotationmatrix(beta);  math.MatrixMult((float*)K,(float*) state, 4, 6, 1,(float*) Kstate);  Serial.println("state[:]");  Serial.println(state[0]);  Serial.println(state[1]);  Serial.println(state[2]);  Serial.println(state[3]);  Serial.println(state[4]);  Serial.println(state[5]);  Serial.println("Kstate[:]");  Serial.println(Kstate[0]);  Serial.println(Kstate[1]);  Serial.println(Kstate[2]);  Serial.println(Kstate[3]);  math.MatrixMult((float*)K,(float*) reference, 4, 6, 1,(float*) Kreference);  Serial.println("Kreference[:]");    Serial.println(Kreference[0]);  Serial.println(Kreference[1]);  Serial.println(Kreference[2]);  Serial.println(Kreference[3]);  Serial.println("Kreference[:]-Kstate[:]");    Serial.println(Kreference[0]-Kstate[0]);  Serial.println(Kreference[1]-Kstate[1]);  Serial.println(Kreference[2]-Kstate[2]);  Serial.println(Kreference[3]-Kstate[3]);  u[0]=(Kreference[0]-Kstate[0])*100;  u[1]=(Kreference[1]-Kstate[1])*100;  u[2]=(Kreference[2]-Kstate[2])*100;  u[3]=(Kreference[3]-Kstate[3])*100;  Serial.println("u[:]");  Serial.println(u[0]);  Serial.println(u[1]);  Serial.println(u[2]);  Serial.println(u[3]);  math.MatrixMult((float*)Rotation,(float*)u, 4, 4, 1,(float*)Input);  PwmDirection();  analogWrite(PWMA, torquePWM[0]);  digitalWrite(DIRA, Direction[0]);  analogWrite(PWMB, torquePWM[1]);  digitalWrite(DIRB, Direction[1]);  analogWrite(PWMC, torquePWM[2]);  digitalWrite(DIRC, Direction[2]);  analogWrite(PWMD, torquePWM[3]);  digitalWrite(DIRD, Direction[3]);  Speed();  delay(400);}`

the log:
Code: [Select]
`Press one button to start movingstate[:]0.000.000.000.000.000.00Kstate[:]0.000.000.000.00Kreference[:]0.00-0.570.000.57Kreference[:]-Kstate[:]0.00-0.570.000.57u[:]0.00-56.570.0056.57Press one button to start movingstate[:]0.000.000.000.000.000.00Kstate[:]0.000.000.000.00Kreference[:]0.00-0.570.000.57Kreference[:]-Kstate[:]0.000.000.000.00u[:]0.000.000.000.00`

#### pylon

#1
##### Jun 05, 2012, 10:39 pm
Show us the complete code. If the vectors are defined as float arrays why do you have to cast them to (float *)? You see, we have to see all the code to help you.

#### Udo Klein

#2
##### Jun 05, 2012, 10:40 pm
Also float arrays will consume a lot of memory. Maybe you are already out of memory.

#### ned112

#3
##### Jun 05, 2012, 10:55 pm
How can I check if I'm out of memory? The compiled code is 12.702 bytes.

Here is the complete code:
Code: [Select]
`#include <MatrixMath.h>#include <superSerial.h>#include <Wire.h>#include <digitalWriteFast.h>#define NO_PORTB_PINCHANGES //to indicate that port b will not be used for pin change interrupts#include <PinChangeInt.h>   //using version 1.6betaMatrixMath math; //Define pin#define PINA1 A0#define PINA2 A1#define DIRA 13#define PWMA 11#define PINB1 A2#define PINB2 A3#define DIRB 12#define PWMB 10#define PINC1 2#define PINC2 3#define DIRC 8#define PWMC 9#define PIND1 4#define PIND2 5#define DIRD 7#define PWMD 6////LQR controller//////Global variabledouble Rotation[4][4];double InputLimit=0.5; float beta;float state[6]={0};float Kstate[4];float reference[6]={0.8,0,0,0,0,0};float Kreference[4];float u[4];float Input[4];//LQR control vectorint torquePWM[4];int Direction[4];//Kinematic Dynamic vectorfloat vlocal[3]={0,0,0}; //[u,v,theta_dot]float Vglobal[3]={0,0,0};float dX;float dY;float dth;unsigned long startTime, lastTime, deltaT;//Encoder Positionsdouble countA = 0;double countB = 0;double countC = 0;double countD = 0;//Reference Velocityfloat Vref=1; //m/s//Wheels speeddouble speedwheel[4];//Conditionsint NewPath=1;int Step=0;//coming from MatLab LQR toolbox, precalculated we can even have various K for different type of navigation i.e: with different weight on Q and R//int CoeffA;int CoeffB;int CoeffC;int CoeffD;float K[4][6]={{0, 0.7071, 0.2236, 0, 0.8468, 0.2493},  {-0.7071, 0, 0.2236, -0.8468, 0, 0.2493},  {0, -0.7071, 0.2236, 0, -0.8468, 0.2493},  {0.7071, 0.0000, 0.2236, 0.8468, 0, 0.2493}};float qTOv[3][4]={{     0,   -0.5000,         0,    0.5000},                  {0.5000,   -0.0000,   -0.5000,    0.0000},                  {1.6129,    1.6129,    1.6129,    1.6129}};float vTOV[3][3]={{1,0,0},{0,1,0},{0,0,1}};//PIN A                     void funcA1(){  PCintPort::pinState!=digitalReadFast(PINA2)?countA++:countA--;}void funcA2(){  PCintPort::pinState!=digitalReadFast(PINA1)?countA--:countA++;}//PIN Bvoid funcB1(){  PCintPort::pinState!=digitalReadFast(PINB2)?countB++:countB--;}void funcB2(){  PCintPort::pinState!=digitalReadFast(PINB1)?countB--:countB++;}//PIN Cvoid funcC1(){  PCintPort::pinState!=digitalReadFast(PINC2)?countC++:countC--;}void funcC2(){  PCintPort::pinState!=digitalReadFast(PINC1)?countC--:countC++;}//PIN Dvoid funcD1(){  PCintPort::pinState!=digitalReadFast(PIND2)?countD++:countD--;}void funcD2(){  PCintPort::pinState!=digitalReadFast(PIND1)?countD--:countD++;}                     void setup(){Serial.begin(115200);/*WHAT DOES HIGH LOW INPUT MEAN??*/pinMode(PINA1, INPUT); digitalWrite(PINA1, HIGH);PCintPort::attachInterrupt(PINA1, &funcA1, CHANGE);  pinMode(PINA2, INPUT); digitalWrite(PINA2, HIGH);PCintPort::attachInterrupt(PINA2, &funcA2, CHANGE);pinMode(DIRA,OUTPUT); digitalWrite(DIRA,LOW);pinMode(PWMA,OUTPUT); digitalWrite(PWMA,LOW);  pinMode(PINB1, INPUT); digitalWrite(PINB1, HIGH);PCintPort::attachInterrupt(PINB1, &funcB1, CHANGE);  pinMode(PINB2, INPUT); digitalWrite(PINB2, HIGH);PCintPort::attachInterrupt(PINB2, &funcB2, CHANGE);pinMode(DIRB,OUTPUT); digitalWrite(DIRB,LOW);pinMode(PWMB,OUTPUT); digitalWrite(PWMB,LOW);  pinMode(PINC1, INPUT); digitalWrite(PINC1, HIGH);PCintPort::attachInterrupt(PINC1, &funcC1, CHANGE);  pinMode(PINC2, INPUT); digitalWrite(PINC2, HIGH);PCintPort::attachInterrupt(PINC2, &funcC2, CHANGE);pinMode(DIRC,OUTPUT); digitalWrite(DIRC,LOW);pinMode(PWMC,OUTPUT); digitalWrite(PWMC,LOW);  pinMode(PIND1, INPUT); digitalWrite(PIND1, HIGH);PCintPort::attachInterrupt(PIND1, &funcD1, CHANGE);  pinMode(PIND2, INPUT); digitalWrite(PIND2, HIGH);PCintPort::attachInterrupt(PIND2, &funcD2, CHANGE);pinMode(DIRD,OUTPUT); digitalWrite(DIRD,LOW);pinMode(PWMD,OUTPUT); digitalWrite(PWMD,LOW);//used to compute speed//startTime = millis();lastTime = millis();}void loop(){  Serial.println("Press one button to start moving");    beta = state[2];//maybe unuseful    rotationmatrix(beta);  math.MatrixMult((float*)K,(float*) state, 4, 6, 1,(float*) Kstate);//why was not declared?? It's a function!  Serial.println("state[:]");   Serial.println(state[0]);  Serial.println(state[1]);  Serial.println(state[2]);  Serial.println(state[3]);  Serial.println(state[4]);  Serial.println(state[5]);  Serial.println("Kstate[:]");  Serial.println(Kstate[0]);  Serial.println(Kstate[1]);  Serial.println(Kstate[2]);  Serial.println(Kstate[3]);  math.MatrixMult((float*)K,(float*) reference, 4, 6, 1,(float*) Kreference);  Serial.println("Kreference[:]");    Serial.println(Kreference[0]);  Serial.println(Kreference[1]);  Serial.println(Kreference[2]);  Serial.println(Kreference[3]);  Serial.println("Kreference[:]-Kstate[:]");    Serial.println(Kreference[0]-Kstate[0]);  Serial.println(Kreference[1]-Kstate[1]);  Serial.println(Kreference[2]-Kstate[2]);  Serial.println(Kreference[3]-Kstate[3]);  u[0]=(Kreference[0]-Kstate[0])*100;  u[1]=(Kreference[1]-Kstate[1])*100;  u[2]=(Kreference[2]-Kstate[2])*100;  u[3]=(Kreference[3]-Kstate[3])*100;  Serial.println("u[:]");   Serial.println(u[0]);  Serial.println(u[1]);  Serial.println(u[2]);  Serial.println(u[3]);  math.MatrixMult((float*)Rotation,(float*)u, 4, 4, 1,(float*)Input);  PwmDirection();  analogWrite(PWMA, torquePWM[0]);   digitalWrite(DIRA, Direction[0]);  analogWrite(PWMB, torquePWM[1]);  digitalWrite(DIRB, Direction[1]);  analogWrite(PWMC, torquePWM[2]);  digitalWrite(DIRC, Direction[2]);  analogWrite(PWMD, torquePWM[3]);  digitalWrite(DIRD, Direction[3]);  Speed();  delay(400);}void rotationmatrix(float angle){double coth,sith;coth=cos(angle);sith=sin(angle);Rotation[0][0]=(pow(coth,2)/2 + coth/2 + pow(sith,2)/2)/(pow(coth,2) + pow(sith,2));Rotation[0][1]=sith/(2*(pow(coth,2) + pow(sith,2)));Rotation[0][2]=(pow(coth,2)/2 - coth/2 + pow(sith,2)/2)/(pow(coth,2) + pow(sith,2));Rotation[0][3]=-sith/(2*(pow(coth,2) + pow(sith,2)));Rotation[1][0]=Rotation[0][3];Rotation[1][1]=Rotation[0][0];Rotation[1][2]=Rotation[0][1];Rotation[1][3]=Rotation[0][2];Rotation[2][0]=Rotation[0][2];Rotation[2][1]=Rotation[0][3];Rotation[2][2]=Rotation[0][0];Rotation[2][3]=Rotation[0][1];Rotation[3][0]=Rotation[0][1];Rotation[3][1]=Rotation[0][2];Rotation[3][2]=Rotation[0][3];Rotation[3][3]=Rotation[0][0];}void PwmDirection(){  int i;  for(i=0;i<=3;i=i++){     if(abs(Input[i])>InputLimit){     Input[i]=InputLimit;     //Serial.println("PwmDirection ifabs");     }     if(Input[i]>0){     Direction[1]=HIGH;}     else{//ma si puĂ˛ fare questa struttura if if else??     Direction[i]=LOW;}  torquePWM[i]=abs((Input[i]/InputLimit)*255);}}void Speed(){startTime=millis();deltaT=(startTime-lastTime)/1000;//SHOULD BE CONVERTED IN SEC//CoeffA=10000;CoeffB=10000;CoeffC=10000;CoeffD=10000;speedwheel[0]=countA/(deltaT*CoeffA);//m/s in theoryspeedwheel[1]=countB/(deltaT*CoeffB);//m/s in theoryspeedwheel[2]=countC/(deltaT*CoeffC);//m/s in theoryspeedwheel[3]=countD/(deltaT*CoeffD);//m/s in theorycountA = 0;countB = 0;countC = 0;countD = 0;lastTime=millis();math.MatrixMult((float*)qTOv,(float*)speedwheel, 3, 4, 1,(float*)vlocal);RotationMatrix();math.MatrixMult((float*)vTOV,(float*)vlocal, 3, 3, 1,(float*)Vglobal); //consider using a 2x2 matrix to save computational timedX=((Vglobal[0]+state[3])/2)*deltaT; //RK2 integration method//dY=((Vglobal[1]+state[4])/2)*deltaT; //RK2 integration method//dth=((Vglobal[2]+state[5])/2)*deltaT;//RK2 integration method//state[0]=state[0]+dX;state[1]=state[1]+dY;state[2]=state[2]+dth;state[3]=Vglobal[0];state[4]=Vglobal[1];state[5]=Vglobal[2];}void RotationMatrix(){vTOV[0][0]=cos(state[2]);vTOV[0][1]=-sin(state[2]);vTOV[1][0]=-vTOV[0][1];vTOV[1][1]=vTOV[0][0];}`

#### ned112

#4
##### Jun 05, 2012, 11:00 pm

Show us the complete code. If the vectors are defined as float arrays why do you have to cast them to (float *)? You see, we have to see all the code to help you.

Cause otherwise It doesn't compile. The mathMatrixMult function are part of a library I didn't write.
Since I'm using only MatrixMult should I add the function along the code insted of adding the whole library??

#### lloyddean

#5
##### Jun 05, 2012, 11:56 pm
No the Linker will strip what the program doesn't use.

#### marco_c

#6
##### Jun 05, 2012, 11:58 pm
Quote
The compiled code is 12.702 bytes

The code and the data space are very different. The code sits in flash RAM but the data sits in 'normal' (static) RAM. There is a lot less static RAM that there is flash RAM - how much depends on your AVR processor. You can find out in the datasheets for the processor.

The code at http://arduino.cc/playground/Code/AvailableMemory may also help.
Arduino Libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com
Arduino++ blog https://arduinoplusplus.wordpress.com

#### ned112

#7
##### Jun 06, 2012, 12:01 am

Quote
The compiled code is 12.702 bytes

The code and the data space are very different. The code sits in flash RAM but the data sits in 'normal' (static) RAM. There is a lot less static RAM that there is flash RAM - how much depends on your AVR processor. You can find out in the datasheets for the processor.

The code at http://arduino.cc/playground/Code/AvailableMemory may also help.

Ok, so is there a way to check if I'm running out of memory?
I know malloc should do something similar but there's nothing for Arduino I think...
any clue?

#### marco_c

#8
##### Jun 06, 2012, 12:04 am
Yes. Have you looked at the code in the link?

Generally using functions like malloc() on embedded processors is a bad idea. Use static arrays and manage you memory usage really closely.
Arduino Libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com
Arduino++ blog https://arduinoplusplus.wordpress.com

#### ned112

#9
##### Jun 06, 2012, 12:16 am

Yes. Have you looked at the code in the link?

Generally using functions like malloc() on embedded processors is a bad idea. Use static arrays and manage you memory usage really closely.

Ok, I run this function   Serial.println(freeMemory()); and I got always the same value: 957. I ran it just before and after the crytical part giving me error. Is it ok to have always the same result?
I have some variables that are constant and won't be changed should I move them to the flash memory using PROGMEM?

#### James C4S

#10
##### Jun 06, 2012, 12:29 am

Ok, so is there a way to check if I'm running out of memory?
I know malloc should do something similar but there's nothing for Arduino I think...
any clue?

In an embedded system with no memory controller, the only absolute method is to keep track of memory usage yourself.  You can start by counting up how many bytes your global variables use.  In your case, you're at about 477 bytes.  So 25% of the RAM is just from global variables.

A couple of things to realize:
1.  There's no difference between a float and double on the arduino.
2.  All floating point math is done in software and is very slow.
3.  There is a difference between the constants "0" and "0.0".  The first is an integer, the second is a float.
e.g. this line:
u[0]=(Kreference[0]-Kstate[0])*100;
would be better stated:
u[0]=(Kreference[0]-Kstate[0])*100.0;

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

#### ned112

#11
##### Jun 06, 2012, 12:36 am

Ok, so is there a way to check if I'm running out of memory?
I know malloc should do something similar but there's nothing for Arduino I think...
any clue?

In an embedded system with no memory controller, the only absolute method is to keep track of memory usage yourself.  You can start by counting up how many bytes your global variables use.  In your case, you're at about 477 bytes.  So 25% of the RAM is just from global variables.

A couple of things to realize:
1.  There's no difference between a float and double on the arduino.
2.  All floating point math is done in software and is very slow.
3.  There is a difference between the constants "0" and "0.0".  The first is an integer, the second is a float.
e.g. this line:
u[0]=(Kreference[0]-Kstate[0])*100;
would be better stated:
u[0]=(Kreference[0]-Kstate[0])*100.0;

Ok, thanks, for double and float I know there are no differencies, but the code has been changed and rewritten a lot of time so some of these are just survived the cleaning.
Thanks for point 3, in any case that 100 will disappear I put it there just to check the 0 value that was appering wasn't simply a value to small to be displayed.

For point 2 I know it's slow but how can I solve it?

#### ned112

#12
##### Jun 06, 2012, 12:57 am
Ok, I run the code without the Speed() function, and It works, the freememory function report something more the 1100bytes.
But it's so strange... and even very problematic cause I'll need more space than the one I'm using now (I'm supposed to run even a bezier curve function with this... so at leat other two float [21] and 1 float [21][4]!

#### ned112

#13
##### Jun 06, 2012, 01:54 am
And even stranger, if I run the code, every time i close and open again the SerialMonitor i got a shot of right calculation. Then all the others coming are wrong. If i close serial monitor and open it again I got another right calcultaion and then again all the other go wrong.

#### PeterH

#14
##### Jun 06, 2012, 02:03 am

Show us the complete code.

This.
I only provide help via the forum - please do not contact me for private consultancy.

Go Up

Please enter a valid email to subscribe