Add all Arduino libraries
This commit is contained in:
parent
0f1a894cfb
commit
484a9fcbdb
21
libraries/CurveFitting/LICENSE
Normal file
21
libraries/CurveFitting/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Andrey Fedorov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
7
libraries/CurveFitting/README.md
Normal file
7
libraries/CurveFitting/README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# arduinoCurveFitting
|
||||||
|
Fit polynomial curves to given points using least squares regression. The max order of polynomial fitting is 20, this should be more than enough to fit most practical problems. All values are kept as double for precision, this works well on a Teensy due to its floating point unit and large (64 bit) double precision. the numbers required increase exponentially as the number of points or order increases.
|
||||||
|
|
||||||
|
This library solves the least squares problem using Cramer's rule and a small function to calculate the determinant of each matrix.
|
||||||
|
|
||||||
|
More explained in this article
|
||||||
|
https://medium.com/@rowaner111/fitting-curves-to-data-on-an-arduino-part-1-how-to-use-arduinocurvefitting-a3173c6dd4ef
|
37
libraries/CurveFitting/examples/fitCurve/fitCurve.ino
Normal file
37
libraries/CurveFitting/examples/fitCurve/fitCurve.ino
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <curveFitting.h>
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
while(!Serial);
|
||||||
|
Serial.println("Starting");
|
||||||
|
|
||||||
|
char buf[100];
|
||||||
|
int xpower = 3;
|
||||||
|
int order = 3;
|
||||||
|
snprintf(buf, 100, "Fitting curve of order %i to data of power %i...\n", order, xpower);
|
||||||
|
Serial.print(buf);
|
||||||
|
|
||||||
|
double x[26];
|
||||||
|
double t[26];
|
||||||
|
for (int i = 0; i < sizeof(x)/sizeof(double); i++){
|
||||||
|
t[i] = i;
|
||||||
|
x[i] = pow(i, xpower);
|
||||||
|
}
|
||||||
|
|
||||||
|
double coeffs[order+1];
|
||||||
|
int ret = fitCurve(order, sizeof(x)/sizeof(double), t, x, sizeof(coeffs)/sizeof(double), coeffs);
|
||||||
|
|
||||||
|
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++){
|
||||||
|
snprintf(buf, 100, "%c=",c++);
|
||||||
|
Serial.print(buf);
|
||||||
|
Serial.print(coeffs[i]);
|
||||||
|
Serial.print('\t');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
}
|
1
libraries/CurveFitting/keywords.txt
Normal file
1
libraries/CurveFitting/keywords.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
fitCurve KEYWORD2
|
10
libraries/CurveFitting/library.properties
Normal file
10
libraries/CurveFitting/library.properties
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
name=CurveFitting
|
||||||
|
version=1.0.6
|
||||||
|
author=Rotario <rotarioner@gmail.com>
|
||||||
|
maintainer=Rotario <rotarioner@gmail.com>
|
||||||
|
sentence=Fits polynomial curves to given datapoints
|
||||||
|
paragraph=Fit polynomial curves to given points using least squares regression. The max order of polynomial fitting is 20, this should be more than enough to fit most practical problems. All values are kept as double for precision, this works well on a Teensy due to its floating point unit and large (64 bit) double precision. the numbers required increase exponentially as the number of points or order increases.
|
||||||
|
url=https://github.com/Rotario/arduinoCurveFitting
|
||||||
|
includes=curveFitting.h
|
||||||
|
category=Data Processing
|
||||||
|
architectures=*
|
195
libraries/CurveFitting/src/curveFitting.cpp
Normal file
195
libraries/CurveFitting/src/curveFitting.cpp
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
curveFitting.h - Library for fitting curves to given
|
||||||
|
points using Least Squares method, with Cramer's rule
|
||||||
|
used to solve the linear equation. Max polynomial order 20.
|
||||||
|
Created by Rowan Easter-Robinson, August 23, 2018.
|
||||||
|
Released into the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "curveFitting.h"
|
||||||
|
|
||||||
|
void printMat(const char *s, double*m, int n){
|
||||||
|
Serial.println(s);
|
||||||
|
char buf[40];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
snprintf(buf, 40, "%30.4f\t", m[i*n+j]);
|
||||||
|
Serial.print(buf);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showmat(const char *s, double **m, int n){
|
||||||
|
Serial.println(s);
|
||||||
|
char buf[40];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < n; j++){
|
||||||
|
snprintf(buf, 40, "%30.4f\t", m[i][j]);
|
||||||
|
Serial.print(buf);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpyArray(double *src, double*dest, int n){
|
||||||
|
for (int i = 0; i < n*n; i++){
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subCol(double *mat, double* sub, uint8_t coln, uint8_t n){
|
||||||
|
if (coln >= n) return;
|
||||||
|
for (int i = 0; i < n; i++){
|
||||||
|
mat[(i*n)+coln] = sub[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Determinant algorithm taken from https://codeforwin.org/2015/08/c-program-to-find-determinant-of-matrix.html */
|
||||||
|
int trianglize(double **m, int n)
|
||||||
|
{
|
||||||
|
int sign = 1;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int max = 0;
|
||||||
|
for (int row = i; row < n; row++)
|
||||||
|
if (fabs(m[row][i]) > fabs(m[max][i]))
|
||||||
|
max = row;
|
||||||
|
if (max) {
|
||||||
|
sign = -sign;
|
||||||
|
double *tmp = m[i];
|
||||||
|
m[i] = m[max], m[max] = tmp;
|
||||||
|
}
|
||||||
|
if (!m[i][i]) return 0;
|
||||||
|
for (int row = i + 1; row < n; row++) {
|
||||||
|
double r = m[row][i] / m[i][i];
|
||||||
|
if (!r) continue;
|
||||||
|
for (int col = i; col < n; col ++)
|
||||||
|
m[row][col] -= m[i][col] * r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
double det(double *in, int n, uint8_t prnt)
|
||||||
|
{
|
||||||
|
double *m[n];
|
||||||
|
m[0] = in;
|
||||||
|
|
||||||
|
for (int i = 1; i < n; i++)
|
||||||
|
m[i] = m[i - 1] + n;
|
||||||
|
if(prnt) showmat("Matrix", m, n);
|
||||||
|
int sign = trianglize(m, n);
|
||||||
|
if (!sign)
|
||||||
|
return 0;
|
||||||
|
if(prnt) showmat("Upper triangle", m, n);
|
||||||
|
double p = 1;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
p *= m[i][i];
|
||||||
|
return p * sign;
|
||||||
|
}
|
||||||
|
/*End of Determinant algorithm*/
|
||||||
|
|
||||||
|
//Raise x to power
|
||||||
|
double curveFitPower(double base, int exponent){
|
||||||
|
if (exponent == 0){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
double val = base;
|
||||||
|
for (int i = 1; i < exponent; i++){
|
||||||
|
val = val * base;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fitCurve (int order, int nPoints, double py[], int nCoeffs, double *coeffs) {
|
||||||
|
uint8_t maxOrder = MAX_ORDER;
|
||||||
|
if (nCoeffs != order + 1) return ORDER_AND_NCOEFFS_DO_NOT_MATCH; // no of coefficients is one larger than the order of the equation
|
||||||
|
if (nCoeffs > maxOrder || nCoeffs < 2) return ORDER_INCORRECT; //matrix memory hard coded for max of 20 order, which is huge
|
||||||
|
if (nPoints < 1) return NPOINTS_INCORRECT; //Npoints needs to be positive and nonzero
|
||||||
|
int i, j;
|
||||||
|
double T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation
|
||||||
|
double S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation
|
||||||
|
double denom; //denominator for Cramer's rule, determinant of LHS linear equation
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
double px[nPoints]; //Generate X values, from 0 to n
|
||||||
|
for (i=0; i<nPoints; i++){
|
||||||
|
px[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<nPoints; i++) {//Generate matrix elements
|
||||||
|
x = px[i];
|
||||||
|
y = py[i];
|
||||||
|
for (j = 0; j < (nCoeffs*2)-1; j++){
|
||||||
|
S[j] += curveFitPower(x, j); // x^j iterated , S10 S20 S30 etc, x^0, x^1...
|
||||||
|
}
|
||||||
|
for (j = 0; j < nCoeffs; j++){
|
||||||
|
T[j] += y * curveFitPower(x, j); //y * x^j iterated, S01 S11 S21 etc, x^0*y, x^1*y, x^2*y...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double masterMat[nCoeffs*nCoeffs]; //Master matrix LHS of linear equation
|
||||||
|
for (i = 0; i < nCoeffs ;i++){//index by matrix row each time
|
||||||
|
for (j = 0; j < nCoeffs; j++){//index within each row
|
||||||
|
masterMat[i*nCoeffs+j] = S[i+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double mat[nCoeffs*nCoeffs]; //Temp matrix as det() method alters the matrix given
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
denom = det(mat, nCoeffs, CURVE_FIT_DEBUG);
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
|
||||||
|
//Generate cramers rule mats
|
||||||
|
for (i = 0; i < nCoeffs; i++){ //Temporary matrix to substitute RHS of linear equation as per Cramer's rule
|
||||||
|
subCol(mat, T, i, nCoeffs);
|
||||||
|
coeffs[nCoeffs-i-1] = det(mat, nCoeffs, CURVE_FIT_DEBUG)/denom; //Coefficients are det(M_i)/det(Master)
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fitCurve (int order, int nPoints, double px[], double py[], int nCoeffs, double *coeffs) {
|
||||||
|
uint8_t maxOrder = MAX_ORDER;
|
||||||
|
if (nCoeffs != order + 1) return ORDER_AND_NCOEFFS_DO_NOT_MATCH; //Number of coefficients is one larger than the order of the equation
|
||||||
|
if(nCoeffs > maxOrder || nCoeffs < 2) return ORDER_INCORRECT; //Matrix memory hard coded for max of 20 order, which is huge
|
||||||
|
if (nPoints < 1) return NPOINTS_INCORRECT; //Npoints needs to be positive and nonzero
|
||||||
|
int i, j;
|
||||||
|
double T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation
|
||||||
|
double S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation
|
||||||
|
double denom; //denominator for Cramer's rule, determinant of LHS linear equation
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
for (i=0; i<nPoints; i++) {//Generate matrix elements
|
||||||
|
x = px[i];
|
||||||
|
y = py[i];
|
||||||
|
for (j = 0; j < (nCoeffs*2)-1; j++){
|
||||||
|
S[j] += curveFitPower(x, j); // x^j iterated , S10 S20 S30 etc, x^0, x^1...
|
||||||
|
}
|
||||||
|
for (j = 0; j < nCoeffs; j++){
|
||||||
|
T[j] += y * curveFitPower(x, j); //y * x^j iterated, S01 S11 S21 etc, x^0*y, x^1*y, x^2*y...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double masterMat[nCoeffs*nCoeffs]; //Master matrix LHS of linear equation
|
||||||
|
for (i = 0; i < nCoeffs ;i++){//index by matrix row each time
|
||||||
|
for (j = 0; j < nCoeffs; j++){//index within each row
|
||||||
|
masterMat[i*nCoeffs+j] = S[i+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double mat[nCoeffs*nCoeffs]; //Temp matrix as det() method alters the matrix given
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
denom = det(mat, nCoeffs, CURVE_FIT_DEBUG);
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
|
||||||
|
//Generate cramers rule mats
|
||||||
|
for (i = 0; i < nCoeffs; i++){ //Temporary matrix to substitute RHS of linear equation as per Cramer's rule
|
||||||
|
subCol(mat, T, i, nCoeffs);
|
||||||
|
coeffs[nCoeffs-i-1] = det(mat, nCoeffs, CURVE_FIT_DEBUG)/denom; //Coefficients are det(M_i)/det(Master)
|
||||||
|
cpyArray(masterMat, mat, nCoeffs);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
40
libraries/CurveFitting/src/curveFitting.h
Normal file
40
libraries/CurveFitting/src/curveFitting.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
curveFitting.h - Library for fitting curves to given
|
||||||
|
points using Least Squares method, with Cramer's rule
|
||||||
|
used to solve the linear equation. Max polynomial order 20.
|
||||||
|
Created by Rowan Easter-Robinson, August 23, 2018.
|
||||||
|
Released into the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef curveFit_h
|
||||||
|
#define curveFit_h
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#define MAX_ORDER 20
|
||||||
|
|
||||||
|
#ifndef CURVE_FIT_DEBUG
|
||||||
|
#define CURVE_FIT_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enum for error messages */
|
||||||
|
enum curveFitERROR{
|
||||||
|
ORDER_AND_NCOEFFS_DO_NOT_MATCH = -1,
|
||||||
|
ORDER_INCORRECT = -2,
|
||||||
|
NPOINTS_INCORRECT = -3
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Matrix Helper Functions */
|
||||||
|
void printMat(const char *s, double*m, int n);
|
||||||
|
void showmat(const char *s, double **m, int n);
|
||||||
|
void cpyArray(double *src, double*dest, int n);
|
||||||
|
void subCol(double *mat, double* sub, uint8_t coln, uint8_t n);
|
||||||
|
double curveFitPower(double base, int exponent);
|
||||||
|
|
||||||
|
/* Determinant matrix functions */
|
||||||
|
int trianglize(double **m, int n);
|
||||||
|
double det(double *in, int n, uint8_t prnt);
|
||||||
|
|
||||||
|
/* Curve fitting functions */
|
||||||
|
int fitCurve (int order, int nPoints, double py[], int nCoeffs, double *coeffs);
|
||||||
|
int fitCurve (int order, int nPoints, double px[], double py[], int nCoeffs, double *coeffs);
|
||||||
|
#endif
|
1
libraries/readme.txt
Normal file
1
libraries/readme.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries
|
66
main.ino
66
main.ino
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
____ __________________________________ ____
|
|
||||||
/ __ \/ ____/_ __/ ____/ ____/_ __/ __ \/ __ \
|
|
||||||
/ / / / __/ / / / __/ / / / / / / / / /_/ /
|
|
||||||
/ /_/ / /___ / / / /___/ /___ / / / /_/ / _, _/
|
|
||||||
/___________/ __________/\____/ _____\__________|
|
|
||||||
/ __ )/ / / / _/ / / __ \/ _/ | / / ____/
|
|
||||||
/ __ / / / // // / / / / // // |/ / / __
|
|
||||||
/ /_/ / /_/ // // /___/ /_/ // // /| / /_/ /
|
|
||||||
/_____/\____/___/_____/_____/___/_/ |_/\____/
|
|
||||||
|
|
||||||
Ladue Horton Watkins High School Science Olympiad
|
|
||||||
|
|
||||||
Licensed under the Parity Public License
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <curveFitting.h>
|
|
||||||
|
|
||||||
|
|
||||||
using ld = long double;
|
|
||||||
|
|
||||||
|
|
||||||
const int LED_R = 8, LED_G = 10, LED_B = 12, THERM = 0; // Device component pins
|
|
||||||
const ld R_k = 10000, V_in = 5, analog_max = 1023; // Device constants
|
|
||||||
|
|
||||||
// Analog to digital conversion
|
|
||||||
ld a2d(int a) { return V_in * a / analog_max; }
|
|
||||||
int d2a(ld d) { return d * analog_max / V_in; }
|
|
||||||
|
|
||||||
// Voltage to resistance conversion
|
|
||||||
ld v2r(ld V_out) { return R_k * (V_in / V_out - 1); }
|
|
||||||
|
|
||||||
ld vol[100];
|
|
||||||
int con[100];
|
|
||||||
|
|
||||||
const int order = 2;
|
|
||||||
int coeff[order + 1];
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(9600);
|
|
||||||
Serial.println("Starting calibration")
|
|
||||||
Serial.println("Place sensor in water and enter the concentration into the console")
|
|
||||||
Serial.println("When you are finished, type c to continue")
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
while (1) {
|
|
||||||
String s = Serial.readString();
|
|
||||||
if (s == "c") break;
|
|
||||||
vol[n] = a2d(analogRead(THERM));
|
|
||||||
con[n] = toInt(s);
|
|
||||||
Serial.println(n);
|
|
||||||
Serial.println(vol[n]);
|
|
||||||
Serial.println(con[n]);
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
|
|
||||||
fitCurve(order, n, vol, con, coeff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
v = a2d(analogRead(THERM));
|
|
||||||
c = 0;
|
|
||||||
for (int i = order; i >= 0; --i) c = v*c + coeff[i];
|
|
||||||
Serial.println(c);
|
|
||||||
}
|
|
Loading…
Reference in a new issue