[SOLVED] Fitting a quadratic curve with Arduino. Possible?

Hello folks,

I made a setup to measure gravity's acceleration. I drop a ruler with 53 stripes that interrupts a IR beam and therefore I end up with 53 positions of the ruler over time. If I export the data (to excel for example) and fit the a quadratic curve to the 53 datapoints, I can easily see the acceleration of gravity.

My question is: Is it possible to do the fit using the arduino itself?

edit: Solution on answer #4.

Cheers and thanks in advance Mauricio

It would be pretty cool to have your Arduino pop up the value of g on an LCD and if you find a suitable numerical method, why not?

Here's a complete explanation that gets right down to solving for a, b and c; you would have to code that up of course. I see lots of for loops in your future ;)

Wouldn't surprise me if there's a few complete C programs lurking around though, and no doubt someone will provide you a link or two.

Thank you for the answer! The least square method is very clearly explained in the link and I will try for sure.

Do you have experience with any other method that might be better considering the 2KB of RAM in the UNO (or 8KB in the MEGA) and the 53 datapoints?

Should I check if the memory is enough before trying it out or do you think I don't need to care about it and simply try it? :D

Rivello: Do you have experience with any other method that might be better considering the 2KB of RAM in the UNO (or 8KB in the MEGA) and the 53 datapoints?

Should I check if the memory is enough before trying it out or do you think I don't need to care about it and simply try it? :D

Sorry, I can't advise on that at all.

Hello,

I used the Least Square Regression method described on the link posted by manor_royal to fit the curve and find the “a” term of the equation (y = ax² + bx + c) and calculate gravity correctly. You can find the function I wrote below.

Note1: It will not compile for the Atmega (UNO/Mega) unless you set the compiler optimization to “O2” for the Fitting function. It is not necessary for the ARM (DUE).

Note2: In the Atmegas, as it only deals with floating numbers up to 32bits, you’re gonna have an error due to the big numbers you get in the calculations. I did not write down the number, but is was something aroung 0.1%. It does not happen when using the DUE.

I hope it helps somebody else. Here is the code:

// USAGE:  double g = fit_G( sizeof(x)/sizeof(double), t, x);

// should be declared like that to optimize for the 8bits microcontroller core.
double fit_G(int N_points, double px[], double py[]) __attribute__((__optimize__("O2"))); //Remove this one if you're using DUE.
double fit_G( int N_points, double px[], double py[] ) {

  int i;
  double S00, S10, S20, S30, S40, S01, S11, S21;
  double denom, x, y, a, b, c;
  S00=S10=S20=S30=S40=S01=S11=S21=0;
  
  for (i=0; i<N_points; i++) {  
    x = px[i];
    y = py[i];
    //S00 += 1; // x^0+y^0
    S10 += x;
    S20 += x * x;
    S30 += x * x * x;
    S40 += x * x * x * x;
    S01 += y;
    S11 += x * y;
    S21 += x * x * y;
  }
  S00 = N_points;
  
  denom =   S00*(S20*S40 - S30*S30) - S10*(S10*S40 - S20*S30) + S20*(S10*S30 - S20*S20);

/* c = (S01*(S20*S40-S30*S30)-S11*(S10*S40-S20*S30)+S21*(S10*S30-S20*S20))/denom;
   b = (S00*(S11*S40-S30*S21)-S10*(S01*S40-S21*S20)+S20*(S01*S30-S11*S20))/denom;*/
   a = (  S00*(S20*S21 - S11*S30) - S10*(S10*S21 - S01*S30) + S20*(S10*S11 - S01*S20) )/denom;
            
  double g = a*2;
  return g;
}

Rivello: I used the Least Square Regression method described on the link

Well done...