#include <openGLCD.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Time.h>
//openGLCD stuff
#define BARMAXVAL 50
#define TXTROW1 49
#define TXTROW2 57
//SD card reader
// MOSI - pin 11
// MISO - pin 12
// CLK - pin 13
const int sdCS = 10;
int logging = false;
SdFat sd;
SdFile logFile;
char logFileName[13];
char loadCellReading[] = {' ','0','0','0','0','0'};
int loadCellReadingInt = 0;
int maxPeakForce = -999;
const int arrayForceSize = 150;
int arrayForce[arrayForceSize] = {-998};
int arrayForceIndex = 0;
int currentPeakForce = -998;
const int array2minSize = 60;
int array2minPeakForce[array2minSize] = {0};
int array2minIndex = 0;
int avg2minPeakForce = 0;
const int array2hrSize = 60;
int array2hrPeakForce[array2hrSize] = {0};
int array2hrIndex = 0;
int avg2hrPeakForce = 0;
int avgPeakForce = 0;
int peaksCounted = 0;
const int onPin = 14;
const int modePin = 15;
const int calibratePin = 6;
void updatePeaks(char newLoadCellReading[]) {
loadCellReadingInt = atoi(newLoadCellReading);
// -- save force value --
arrayForce[arrayForceIndex] = loadCellReadingInt;
arrayForceIndex++;
int newPeak = arrayForceIndex == arrayForceSize; // need to catch array being full
if(arrayForceIndex==arrayForceSize) {
arrayForceIndex=0;
}
char loadCellString[7];
sprintf(loadCellString,"%6s", newLoadCellReading);
GLCD.CursorToXY(92, TXTROW2);
GLCD.print(loadCellString);
// -- see if it's time to calculate new peak force --
if ( newPeak==1 ) {
currentPeakForce = -998;
for (int i=0; i<arrayForceSize; i++) {
if(arrayForce[i] > currentPeakForce) {
currentPeakForce = arrayForce[i];
}
arrayForce[i] = -998;
}
peaksCounted++;
GLCD.CursorToXY(32, TXTROW1);
GLCD.print(peaksCounted);
GLCD.CursorToXY(102, TXTROW1);
GLCD.print(currentPeakForce);
// -- update max and avgPeaks --
if (currentPeakForce > maxPeakForce) {
maxPeakForce = currentPeakForce;
char maxPeakForceString[5];
sprintf(maxPeakForceString,"%4d", maxPeakForce);
GLCD.CursorToXY(0, TXTROW2);
GLCD.print(maxPeakForceString);
}
avgPeakForce = (avgPeakForce*(peaksCounted-1) + currentPeakForce) / peaksCounted;
char avgPeakForceString[5];
sprintf(avgPeakForceString,"%4d", avgPeakForce);
GLCD.CursorToXY(24, TXTROW2);
GLCD.print(avgPeakForceString);
// -- save peak value --
array2minPeakForce[array2minIndex] = currentPeakForce;
// -- redraw short term graph --
GLCD.FillRect(66, 0, 60, BARMAXVAL, PIXEL_OFF);
int rightGraphPos = 66;
int i = array2minIndex + 1;
if (i==array2minSize) { i=0; }
while( i!=array2minIndex ) {
int temp = array2minPeakForce[i]/20;
if(temp < 0) { temp=0; }
GLCD.DrawVLine(rightGraphPos++, BARMAXVAL-temp, temp);
i++;
if (i==array2minSize) { i=0; }
}
array2minIndex++;
//see if it's time to calculate new short term peak avg
if (array2minIndex==array2minSize) {
array2minIndex=0;
int nonZero = 0;
avg2minPeakForce = 0;
for (int i=0; i<array2minSize; i++) {
if(array2minPeakForce[i] > 0) {
nonZero++;
avg2minPeakForce += array2minPeakForce[i];
}
}
avg2minPeakForce /= nonZero;
char avg2minPeakForceString[9];
sprintf(avg2minPeakForceString,"%4d", avg2minPeakForce);
GLCD.CursorToXY(72, TXTROW1);
GLCD.print(avg2minPeakForceString);
// -- save short term peak avg --
array2hrPeakForce[array2hrIndex] = avg2minPeakForce;
array2hrIndex++;
// -- redraw long term graph --
GLCD.FillRect(1, 0, 60, BARMAXVAL, PIXEL_OFF);
int leftGraphPos = 1;
int i = array2hrIndex + 1;
if (i==array2hrSize) { i=0; }
while( i!=array2hrIndex ) {
int temp = array2hrPeakForce[i]/20;
if(temp < 0) { temp=0; }
GLCD.DrawVLine(leftGraphPos++, BARMAXVAL-temp, temp);
i++;
if (i==array2hrSize) { i=0; }
}
//see if it's time to calculate new long term peak avg
if (array2hrIndex==array2hrSize) {
array2hrIndex = 0;
}
nonZero = 0;
avg2hrPeakForce = 0;
for (int i=0; i<array2hrSize; i++) {
if(array2hrPeakForce[i] > 0) {
nonZero++;
avg2hrPeakForce += array2hrPeakForce[i];
}
}
avg2hrPeakForce /= nonZero;
char avg2hrPeakForceString[9];
sprintf(avg2hrPeakForceString,"%4d", avg2hrPeakForce);
GLCD.CursorToXY(6, TXTROW1);
GLCD.print(avg2hrPeakForceString);
}
Serial.print("RAM: ");
Serial.println(FreeRam());
GLCD.CursorToXY(10, 40);
GLCD.print("RAM: ");
GLCD.print(FreeRam());
}
}
void logOutput(){
char logString[128];
sprintf(logString, "%d, %d, %d, %d, %d, %d, %d", millis(), peaksCounted, loadCellReadingInt, maxPeakForce, avg2minPeakForce, avg2hrPeakForce, avgPeakForce);
if (logging==true) {
logFile.open(logFileName, O_CREAT | O_APPEND | O_WRITE);
logFile.println(logString);
logFile.close();
}
Serial.println(logString);
}
void calibrate() {
Serial.println("calibrate...");
GLCD.CursorToXY(54, TXTROW2);
GLCD.print(" cal ");
maxPeakForce = -999;
arrayForce[arrayForceSize] = {-998};
arrayForceIndex = 0;
currentPeakForce = -998;
array2minPeakForce[array2minSize] = {0};
array2minIndex = 0;
avg2minPeakForce = 0;
array2hrPeakForce[array2hrSize] = {0};
array2hrIndex = 0;
avg2hrPeakForce = 0;
avgPeakForce = 0;
peaksCounted = 0;
loadCellReadingInt = 0;
delay(500);
}
void startLogging() {
//filename limited by SDFat library to 8 chars name and 3 chars extension
sprintf(logFileName, "%02d%02d%02d%02d.csv", day(), hour(), minute(), second());
Serial.print(F("starting new logfile called "));
Serial.println(logFileName);
if( !logFile.open(logFileName, O_CREAT | O_APPEND | O_WRITE) ){
GLCD.CursorToXY(5, 30);
GLCD.print(F("log error"));
Serial.println(F("log file error"));
}
else {
logging = true;
GLCD.CursorToXY(10, 30);
GLCD.print(F("log on "));
logFile.close();
}
}
void stopLogging() {
logging = false;
GLCD.CursorToXY(10, 30);
GLCD.print(F("log off"));
}
time_t getTeensy3Time() { return Teensy3Clock.get(); }
// User provided date time callback function
void dateTime(uint16_t* date, uint16_t* time) {
time_t now();
*date = FAT_DATE(year(), month(), day());
*time = FAT_TIME(hour(), minute(), second());
}
//-----------------------------------------------------------------------------
void setup() {
// initialize the digital pin as an output.
pinMode(onPin, INPUT_PULLUP);
pinMode(modePin, INPUT_PULLUP);
pinMode(calibratePin, INPUT_PULLUP);
//setup teensy clock
setSyncProvider(getTeensy3Time);
//serial console
Serial.begin(9600);
GLCD.Init();
GLCD.ClearScreen();
delay(1000); //startup pause so i can see on the screen that the teensy has rebooted
GLCD.SelectFont(System5x7);
SdFile::dateTimeCallback(dateTime);
pinMode(sdCS, OUTPUT);
while (!sd.begin(sdCS, SPI_FULL_SPEED)) {
GLCD.CursorToXY(5, 30);
GLCD.print(F("Insert microSD card"));
}
GLCD.ClearScreen();
//graph side bars
GLCD.DrawVLine(0, 0, BARMAXVAL);
GLCD.DrawVLine(61, 0, BARMAXVAL);
GLCD.DrawVLine(65, 0, BARMAXVAL);
GLCD.DrawVLine(126, 0, BARMAXVAL);
//empty graph
GLCD.DrawLine(0, 1, 61, BARMAXVAL-1);
GLCD.DrawLine(0, BARMAXVAL-1, 61, 0);
srand(atoi(""+year()+month()+day()+hour()+minute()+second()));
} //end setup()
void loop() {
if ( digitalRead(calibratePin)==LOW ) {
calibrate();
}
loadCellReading[(rand() % 5 +1) ] = (rand() % 10);
updatePeaks(loadCellReading);
//not using interrupts because i don't want to chop off half a log entry
if ( digitalRead(onPin)==LOW ) {
if (logging==false) {
startLogging();
}
logOutput();
}
else {
if (logging==true) {
stopLogging();
}
}
} //end loop()