If you need to easily fit a curve to a given set of data on an Arduino, or other embedded device running C, there seems to be no obvious choice in libraries, so I developed my own simple library to do it.

Fitting a curve to a set of data is extremely useful if you’re interested in applying machine learning to time series data. This is where arduinoCurveFitting comes in!

https://github.com/Rotario/arduinoCurveFitting

This small library can be imported into your Arduino IDE and used to fit polynomial curves to a set of points with a max order of 20. Let’s have a quick recap on polynomial curves.

## Polynomial Curves

These curves are defined by a mathematical function where y is a function of x. For example:

Second order polynomial: y = x²

Third order polynomial: y = x³ + 2x² +3

The largest power of x (the small numbers above each x)denotes the function’s *order*, the higher the order, generally the more complex the curve. This also means the higher the order, the better your curve fits your data.

The number next to an x is called its *coefficient, *for example in y = 2x² the x² coefficient is 2. For the purpose of using these curves in machine learning and other applications, all that’s needed are the coefficients in the curve.

#### Curve fitting on a microcontroller

The Arduino curve fitting library can be downloaded from the Github link at the top of this page. Once you’ve installed it into the Arduino IDE using the “import library” function, you can start using it to fit curves to your data!

#### 1 – Include necessary header

`#include <curveFitting.h>`

#### 2 – Initialise data and choose order of polynomial

We have our data in an array of 50 points called `x.`

This is the array you should fill with your sensor data. In this example we’re going to generate some data in the program.

`double x[50]; //fill this with your sensor data`

To use curveFitting, we need to create an array that will be populated with the coefficients from the curve fitting process. This array needs to be big enough to hold all the coefficients generated, which is the order of the curve you want plus one extra. Let’s use a simple 2nd order.

#### 3 – Fit Curve

```
int order = 2;
double coeffs[order + 1];
double t[sizeof(x)/sizeof(double)];for (int i = 0; i < sizeof(x)/sizeof(double); i++){
t[i] = i;
x[i] = power(i, 2);
//should generate function y = x^2}int ret = fitCurve(order, sizeof(x)/sizeof(double), t, x, sizeof(coeffs)/sizeof(double), coeffs);
```

Here fitCurve returns a number, where 0 means it ran correctly so we print out the coefficients.

#### 4 – Print out coefficients

```
if (ret == 0){ //Returned value is 0 if no error
uint8_t c = 'a';
Serial.println("Coefficients are:");
for (int i = 0; i < sizeof(coeffs)/sizeof(double); i++){
Serial.printf("%c=%ft ",c++, coeffs[i]);
}
}
```

Since our data was a perfect curve, the Serial data printed out is:

```
Coefficients are:
a = 1.000
b = 0.000
c = 0.000
```

Putting these coefficients into:

y = ax² + bx + c

We get:

y = x²

Which is the function we used to populate the data before, our curve fitting algorithm works!

Next week we’ll be looking at machine learning applications for this library!

Email me info@workyourtech.com with your questions!

Hello, to which variable should we assign the coordinates of the points on the curve?

For example: A (0; 3) B (2; 1) C (4; 3)

whose returned result would be: a = 0.5 b = -2 c = 3 or f (x) = 0.5 * x² -2 * x +3

Thank you beforehand.

cordially

Bonjour, a quelle variable faut-il attribuer les coordonnées des points de la courbe ?

Par exemple : A(0;3) B(2;1) C(4;3)

dont le résultat retourné serait : a=0.5 b=-2 c=3 soit f(x)= 0.5*x² -2*x +3

En vous remerciant d’avance.

Cordialement

Hi Kos,

You have to allocate two arrays for your x and y values, in the case of fitting a curve to 3 points

int order = 2;

double coeffs[order + 1];

float x = {0, 2, 4};

float y = {3, 1, 3};

int ret = fitCurve(order, sizeof(x)/sizeof(float), x, y, sizeof(coeffs)/sizeof(double), coeffs);

Should give you the coefficients you’re looking for in the coeffs array!

Any more questions don’t hesitate to ask!

Hi, awesome library! Thanks for sharing. Could you point out in your code where I could add the option to fix the “Y” intercept point to some value, or zero in most cases. I believe it is a matter of fixing the last coefficient to the desired value.

Best Regards!

No problem, unfortunately right now there’s no option for coercing the intercept to zero I’m afraid as it’s a different least squares method. (https://stats.stackexchange.com/questions/219679/analytical-solution-of-a-simple-regression-with-fixed-intercept)

I’ve been looking at implementing it and I’m just doing some research.

Hello,

Thanks for this library. I would like to know if it could easily be modified to fit a decaying Sin function: a+b.exp(-c.t).sin(d.t+e) ? Or do one needs a different algorithm. Thanks a lot.

Best regards.

Hi Nicolas, I’ve had a look at this and it’s pretty nontrivial. Is this something to do with control theory?

Sorry for the late reply. No it is for analyzing physics data generated by a mechanical oscilator. Thank you for looking at it.

Hi Tregix,

No problem. I’ll have a look at trying to implement some Non-linear least squares regression using this algo (http://people.duke.edu/~hpgavin/ce281/lm.pdf).

I’m pretty busy with uni work right now, but should be free come May. I’ll let you know how it goes! If it works, then it should allow any non-linear function to be used.

Rowan

Hi Tregix, I’ve got a working algorithm in Julia, for my own learning, it seems to work fairly well given good guesses for first parameters, can you confirm if you can make a good guess at the sine wave parameters before you fit the data to it?