Compare commits

...

2 commits

Author SHA1 Message Date
257e0247c6
Delete old stuff 2022-01-15 21:16:30 -06:00
f79df9410b
Move new code to main.ino 2022-01-15 21:16:14 -06:00
22 changed files with 57 additions and 831 deletions

Binary file not shown.

View file

@ -1,6 +0,0 @@
{
"sketch": "Detector_Building.ino",
"port": "COM3",
"board": "arduino:avr:uno",
"programmer": "AVRISP mkII"
}

View file

@ -1,21 +0,0 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"C:\\Program Files (x86)\\Arduino\\tools\\**",
"C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\**",
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.2\\**",
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\**"
],
"forcedInclude": [
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.2\\cores\\arduino\\Arduino.h"
],
"intelliSenseMode": "msvc-x64",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.23.28105/bin/Hostx64/x64/cl.exe",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}

View file

@ -1,195 +0,0 @@
/*
* Detector Building
* Code by Anthony Wang
* Ladue High School Science Olympiad
*/
/*
* DON'T USE: The calibration method is known to be highly inaccurate
*/
// Constants
const bool CALIB = false; // Calibration mode
const int LED_R = 4, LED_G = 3, LED_B = 2, THERM = 0; // Device component pins
const double R_k = 10000, V_in = 5, analog_max = 1023; // Device constants
// Calibration data
const int n = 6, m = n / 3; // Number of data points, MUST be multiple of 3
double V[n] = { 2.81, 3.31, 3.36, 3.81, 4.03, 4.21 }; // Voltage measurements
double T[n] = { 18.5, 29.1, 33.1, 48.0, 59.0, 70.0 }; // Temperature measurements
double V_mid[m]; // Stores each piecewise segment for binary search
double A[m], B[m], C[m]; // Coefficients for each piecewise component
// Temperature conversions
inline double f2c(double f) { return (f - 32) * 5 / 9; } // Fahrenheit to Celsius
inline double c2f(double c) { return c * 9 / 5 + 32; } // Celsius to Fahrenheit
inline double k2c(double k) { return k - 273.15; } // Kelvin to Celsius
inline double c2k(double c) { return c + 273.15; } // Celsius to Kelvin
inline double f2k(double f) { return c2k(f2c(f)); } // Fahrenheit to Kelvin
inline double k2f(double k) { return c2f(k2c(k)); } // Kelvin to Fahrenheit
// Analog to digital conversion
inline double a2d(int a) { return V_in * a / analog_max; }
inline int d2a(double d) { return d * analog_max / V_in; }
// Utility functions
// No C++ standard library :(
void sort(double a[], int n) {
// Bubble sort
// Slow but n < 30 so OK
// Too lazy to implement a fast sort
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (a[j] > a[j + 1]) {
double tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
}
// Calculations
// Steinhart-hart stuff
void calculate() {
sort(V, n);
sort(T, n);
double R[n], L[n], Y[n], G[n];
for (int i = 0; i < n; i++) R[i] = R_k * (V_in / V[i] - 1);
for (int i = 0; i < n; i++) L[i] = log(R[i]);
for (int i = 0; i < n; i++) Y[i] = 1 / c2k(T[i]);
for (int i = 0; i < n; i += 3) {
G[i + 1] = (Y[i + 1] - Y[i]) / (L[i + 1] - L[i]);
G[i + 2] = (Y[i + 2] - Y[i]) / (L[i + 2] - L[i]);
}
for (int i = 0; i < n; i += 3) { // Don't ask how this works
C[i / 3] = (G[i + 2] - G[i + 1]) / (L[i + 2] - L[i + 1]) / (L[i] + L[i + 1] + L[i + 2]);
B[i / 3] = G[i + 1] - C[i / 3] * (L[i] * L[i] + L[i] * L[i + 1] + L[i + 1] * L[i + 1]);
A[i / 3] = Y[i] - L[i] * (B[i / 3] + L[i] * L[i] * C[i / 3]);
}
for (int i = 0; i < n; i += 3) V_mid[i / 3] = (i ? (V[i - 1] + V[i]) / 2 : 0);
}
// Arduino stuff
void blink(int pin) {
digitalWrite(pin, HIGH);
delay(1000);
digitalWrite(pin, LOW);
}
// More Arduino stuff
void setup() {
Serial.begin(9600);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
// blink(LED_R);
// blink(LED_G);
// blink(LED_B);
calculate();
// Debug stuff
/*for (int i = 0; i < n; i++) {
Serial.print(V[i]);
Serial.print(" ");
Serial.print(T[i]);
Serial.print(" ");
}
Serial.println();
for (int i = 0; i < m; i++) {
Serial.print("Segment lower bound: ");
Serial.print(V_mid[i]);
Serial.print(" Segment upper bound: ");
Serial.print(V_mid[i + 1]);
Serial.print(" A: ");
Serial.print(A[i], 12);
Serial.print(" B: ");
Serial.print(B[i], 12);
Serial.print(" C: ");
Serial.print(C[i], 12);
Serial.println();
}*/
}
// Main loop
void loop() {
int V_raw = analogRead(THERM); // Read in raw analog value
double V_out = a2d(V_raw); // Convert analog to digital
double R_t = R_k * (V_in / V_out - 1); // Thermistor resistance
if (CALIB) {
// Calibration mode
Serial.print("Raw analog reading: ");
Serial.print(V_raw);
Serial.print(" Voltage (V): ");
Serial.print(V_out);
Serial.println();
delay(500);
return;
}
int s = 0;
while (s + 1 < m && V_out > V_mid[s + 1]) s++; // Find correct segment
double logR_t = log(R_t);
double K = 1.0 / (A[s] + B[s] * logR_t + C[s] * logR_t * logR_t * logR_t); // Steinhart-hart
double C = k2c(K);
double F = c2f(C);
// LED stuff
if (C <= 25) { // Cold
digitalWrite(LED_R, LOW);
digitalWrite(LED_G, LOW);
digitalWrite(LED_B, HIGH);
}
else if (C <= 50) { // Medium
digitalWrite(LED_R, LOW);
digitalWrite(LED_G, HIGH);
digitalWrite(LED_B, LOW);
}
else if (C <= 75) { // Hot
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, LOW);
digitalWrite(LED_B, LOW);
}
else { // Something seriously wrong
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, HIGH);
digitalWrite(LED_B, HIGH);
}
// Output voltage, temperature
Serial.print("Raw analog reading: ");
Serial.print(V_raw);
Serial.print(" Voltage (V): ");
Serial.print(V_out);
//Serial.print(" Resistance (Ohms): ");
//Serial.print(R_t);
Serial.print(" Temperature (°C): ");
Serial.print(C);
// For reference
//Serial.print(" Temperature (°F): ");
//Serial.print(F);
// Debug stuff
/*Serial.print(" Segment lower bound: ");
Serial.print(V_mid[s]);
Serial.print(" Segment upper bound: ");
Serial.print(V_mid[s + 1]);
Serial.println();*/
delay(500);
return;
}

View file

@ -1,6 +0,0 @@
{
"sketch": "Detector_Building_v2.ino",
"port": "COM3",
"board": "arduino:avr:uno",
"programmer": "AVRISP mkII"
}

View file

@ -1,21 +0,0 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"C:\\Program Files (x86)\\Arduino\\tools\\**",
"C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\**",
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.2\\**",
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\**"
],
"forcedInclude": [
"C:\\Users\\shengyue\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.2\\cores\\arduino\\Arduino.h"
],
"intelliSenseMode": "msvc-x64",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.23.28105/bin/Hostx64/x64/cl.exe",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}

View file

@ -1,137 +0,0 @@
/*
______ _______ _______ _______ _______ _______ _____ ______
| \ |______ | |______ | | | | |_____/
|_____/ |______ | |______ |_____ | |_____| | \_
______ _ _ _____ ______ _____ __ _ ______ _ _ _______
|_____] | | | | \ | | \ | | ____ \ / ______|
|_____] |_____| __|__ |_____/ __|__ | \_| |_____| \/ |______
Ladue Horton Watkins High School Science Olympiad
*/
/*
TODO
- Numerical precision
*/
#include <curveFitting.h>
#include <detectorBuilding.h>
const bool DEBUG = 0; // Debug mode
const int n = 5; // Number of data points
const int m = 1; // Number of segments
const int deg = 3; // Regression degree
ld data[2 * n] = {
// V T
2.25, 20.4,
3.66, 48.0,
2.95, 32.7,
3.91, 49.4,
4.22, 66.9
}; // Number of data points is (last line number - 30)
ld coeff[m][deg + 1], V[n], T[n];
void setup() {
Serial.begin(9600);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
for (int i = 0; i < n; i++) {
V[i] = data[2 * i];
T[i] = data[2 * i + 1];
}
sort(V, n);
sort(T, n);
ld x[n], y[n];
for (int i = 0; i < n; i++) x[i] = log(v2r(V[i])) - 7;
for (int i = 0; i < n; i++) y[i] = 1000 / c2k(T[i]);
if (DEBUG) {
for (int i = 0; i < n; i++) {
Serial.print("{");
Serial.print((double)x[i], 12);
Serial.print(", ");
Serial.print((double)y[i], 12);
Serial.print("},");
Serial.println();
}
}
for (int i = 0; i < m; i++) {
int ret = fitCurve(deg, n/m, x+i*n/m, y+i*n/m, deg + 1, coeff[i]);
if (DEBUG && ret == 0) { // Returned value is 0 if no error
char c = 'A';
Serial.println("Coefficients are:");
for (int j = 0; j <= deg; j++){
Serial.print(c++);
Serial.print(": ");
Serial.print((double)coeff[i][j], 12);
Serial.println();
}
}
}
}
void loop() {
int V_raw = analogRead(THERM); // Read in raw analog value
ld V_out = a2d(V_raw);
int s = 0; // Find correct segment
while (s + 1 < m && V_out < (V[s*n/m-1] + V[s*n/m]) / 2) s++;
ld logR = log(v2r(V_out)) - 7;
ld sum = 0, prod = 1;
for (int i = 0; i <= deg; i++) {
sum += coeff[s][deg - i] * prod;
prod *= logR;
}
ld K = 1000 / sum;
ld C = k2c(K);
ld F = c2f(C);
// LED stuff
if (C <= 30) { // Cold
digitalWrite(LED_R, LOW);
digitalWrite(LED_G, LOW);
digitalWrite(LED_B, HIGH);
}
else if (C <= 50) { // Medium
digitalWrite(LED_R, LOW);
digitalWrite(LED_G, HIGH);
digitalWrite(LED_B, LOW);
}
else if (C <= 75) { // Hot
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, LOW);
digitalWrite(LED_B, LOW);
}
else { // Something seriously wrong
digitalWrite(LED_R, HIGH);
digitalWrite(LED_G, HIGH);
digitalWrite(LED_B, HIGH);
}
// Output voltage, temperature
Serial.print("Raw analog reading: ");
Serial.print((double)V_raw);
Serial.print(" Voltage (V): ");
Serial.print((double)V_out);
Serial.print(" Temperature (°C): ");
Serial.print((double)C);
//Serial.print(" logR: ");
//Serial.print(logR);
Serial.println();
delay(500);
return;
}

View file

@ -1,11 +0,0 @@
void setup() {
Serial.begin(9600);
}
void loop() {
int x = analogRead(0);
Serial.println(x);
// String a = Serial.readString();
// Serial.println(a);
}

View file

@ -1,2 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto

View file

@ -1,21 +0,0 @@
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.

View file

@ -1,7 +0,0 @@
# 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

View file

@ -1,37 +0,0 @@
#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(){
}

View file

@ -1 +0,0 @@
fitCurve KEYWORD2

View file

@ -1,10 +0,0 @@
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=*

View file

@ -1,195 +0,0 @@
/*
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, ld*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, ld **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(ld *src, ld*dest, int n){
for (int i = 0; i < n*n; i++){
dest[i] = src[i];
}
}
void subCol(ld *mat, ld* 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(ld **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;
ld *tmp = m[i];
m[i] = m[max], m[max] = tmp;
}
if (!m[i][i]) return 0;
for (int row = i + 1; row < n; row++) {
ld 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;
}
ld det(ld *in, int n, uint8_t prnt)
{
ld *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);
ld p = 1;
for (int i = 0; i < n; i++)
p *= m[i][i];
return p * sign;
}
/*End of Determinant algorithm*/
//Raise x to power
ld curveFitPower(ld base, int exponent){
if (exponent == 0){
return 1;
} else {
ld val = base;
for (int i = 1; i < exponent; i++){
val = val * base;
}
return val;
}
}
int fitCurve (int order, int nPoints, ld py[], int nCoeffs, ld *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;
ld T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation
ld S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation
ld denom; //denominator for Cramer's rule, determinant of LHS linear equation
ld x, y;
ld 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...
}
}
ld 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];
}
}
ld 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, ld px[], ld py[], int nCoeffs, ld *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;
ld T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation
ld S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation
ld denom; //denominator for Cramer's rule, determinant of LHS linear equation
ld 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...
}
}
ld 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];
}
}
ld 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;
}

View file

@ -1,42 +0,0 @@
/*
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
typedef long double ld;
#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, ld*m, int n);
void showmat(const char *s, ld **m, int n);
void cpyArray(ld *src, ld*dest, int n);
void subCol(ld *mat, ld* sub, uint8_t coln, uint8_t n);
ld curveFitPower(ld base, int exponent);
/* Determinant matrix functions */
int trianglize(ld **m, int n);
ld det(ld *in, int n, uint8_t prnt);
/* Curve fitting functions */
int fitCurve (int order, int nPoints, ld py[], int nCoeffs, ld *coeffs);
int fitCurve (int order, int nPoints, ld px[], ld py[], int nCoeffs, ld *coeffs);
#endif

View file

@ -1,10 +0,0 @@
f2c KEYWORD2
c2f KEYWORD2
k2c KEYWORD2
c2k KEYWORD2
f2k KEYWORD2
k2f KEYWORD2
a2d KEYWORD2
d2a KEYWORD2
v2r KEYWORD2
sort KEYWORD2

View file

@ -1,10 +0,0 @@
name=DetectorBuilding
version=1.0
author=unixkcd <unixkcd@gmail.com>
maintainer=unixkcd <unixkcd@gmail.com>
sentence=Detector building utility code
paragraph=Some detector building utility code
url=https://github.com/Ta180m/Detector-Building
includes=detectorBuilding.h
category=Data Processing
architectures=*

View file

@ -1,66 +0,0 @@
/*
detectorBuilding.cpp - Library for Detector Building utility functions
Created by Anthony Wang, February 21, 2020.
Released into the public domain.
*/
#include "Arduino.h"
#include "detectorBuilding.h"
// Temperature conversions
ld f2c(ld f) { return (f - 32) * 5 / 9; } // Fahrenheit to Celsius
ld c2f(ld c) { return c * 9 / 5 + 32; } // Celsius to Fahrenheit
ld k2c(ld k) { return k - 273.15; } // Kelvin to Celsius
ld c2k(ld c) { return c + 273.15; } // Celsius to Kelvin
ld f2k(ld f) { return c2k(f2c(f)); } // Fahrenheit to Kelvin
ld k2f(ld k) { return c2f(k2c(k)); } // Kelvin to Fahrenheit
// 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); }
// Utility functions
// No C++ standard library :(
void sort(ld a[], int n) {
// Bubble sort
// Slow but n < 30 so OK
// Too lazy to implement a fast sort
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (a[j] < a[j + 1]) {
ld tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
}
// Calculations: Steinhart-hart stuff
// Probably unused but can include anyways
/*void calculate() {
sort(V, n);
sort(T, n);
ld R[n], L[n], Y[n], G[n];
for (int i = 0; i < n; i++) R[i] = R_k * (V_in / V[i] - 1);
for (int i = 0; i < n; i++) L[i] = log(R[i]);
for (int i = 0; i < n; i++) Y[i] = 1 / c2k(T[i]);
for (int i = 0; i < n; i += 3) {
G[i + 1] = (Y[i + 1] - Y[i]) / (L[i + 1] - L[i]);
G[i + 2] = (Y[i + 2] - Y[i]) / (L[i + 2] - L[i]);
}
for (int i = 0; i < n; i += 3) { // Don't ask how this works
C[i / 3] = (G[i + 2] - G[i + 1]) / (L[i + 2] - L[i + 1]) / (L[i] + L[i + 1] + L[i + 2]);
B[i / 3] = G[i + 1] - C[i / 3] * (L[i] * L[i] + L[i] * L[i + 1] + L[i + 1] * L[i + 1]);
A[i / 3] = Y[i] - L[i] * (B[i / 3] + L[i] * L[i] * C[i / 3]);
}
for (int i = 0; i < n; i += 3) V_mid[i / 3] = (i ? (V[i - 1] + V[i]) / 2 : V[i]);
}*/

View file

@ -1,32 +0,0 @@
/*
detectorBuilding.h - Library for Detector Building utility functions
Created by Anthony Wang, February 21, 2020.
Released into the public domain.
*/
#ifndef detectorBuilding_h
#define detectorBuilding_h
#include "Arduino.h"
typedef long double ld;
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
ld f2c(ld f);
ld c2f(ld c);
ld k2c(ld k);
ld c2k(ld c);
ld f2k(ld f);
ld k2f(ld k);
ld a2d(int a);
int d2a(ld d);
ld v2r(ld V_out);
void sort(ld a[], int n);
//void calculate();
#endif

View file

@ -1 +0,0 @@
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries

57
main.ino Normal file
View file

@ -0,0 +1,57 @@
/*
____ __________________________________ ____
/ __ \/ ____/_ __/ ____/ ____/_ __/ __ \/ __ \
/ / / / __/ / / / __/ / / / / / / / / /_/ /
/ /_/ / /___ / / / /___/ /___ / / / /_/ / _, _/
/___________/ __________/\____/ _____\__________|
/ __ )/ / / / _/ / / __ \/ _/ | / / ____/
/ __ / / / // // / / / / // // |/ / / __
/ /_/ / /_/ // // /___/ /_/ // // /| / /_/ /
/_____/\____/___/_____/_____/___/_/ |_/\____/
Ladue Horton Watkins High School Science Olympiad
Licensed under the Parity Public License
*/
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];
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;
}
}
void loop() {
}