Created
July 12, 2016 02:04
-
-
Save charlespax/01fd08e663a10f8f09fd88f74eabb572 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/t400/buttons.h b/t400/buttons.h | |
index 14c4827..744e55f 100644 | |
--- a/t400/buttons.h | |
+++ b/t400/buttons.h | |
@@ -3,9 +3,8 @@ | |
#include <Arduino.h> | |
-namespace Buttons { | |
- // Button names | |
- enum Button { | |
+// Button names | |
+enum Button { | |
BUTTON_A, | |
BUTTON_B, | |
BUTTON_C, | |
@@ -13,7 +12,9 @@ namespace Buttons { | |
BUTTON_E, | |
BUTTON_POWER, | |
BUTTON_COUNT | |
- }; | |
+}; | |
+ | |
+namespace Buttons { | |
void setup(); | |
bool pending(); | |
diff --git a/t400/functions.cpp b/t400/functions.cpp | |
index c340613..7237ef4 100644 | |
--- a/t400/functions.cpp | |
+++ b/t400/functions.cpp | |
@@ -1,4 +1,5 @@ | |
#define __STDC_LIMIT_MACROS | |
+ | |
#include <stdint.h> | |
#include <avr/io.h> | |
@@ -10,21 +11,35 @@ | |
namespace Display { | |
+#define TEMP_MAX_VALUE_F (3276.0) | |
+#define TEMP_MAX_VALUE_I (32760) | |
+#define TEMP_MIN_VALUE_F (-3276.0) | |
+#define TEMP_MIN_VALUE_I (-32760) | |
+ | |
+#define LINE_COUNT 4 | |
+ | |
+const uint8_t lines[LINE_COUNT][4] = { | |
+ { 0, 7, 132, 7}, // hline between temperatures and status bar | |
+ {31, 0, 31, 7}, // vline between TC1 and TC2 | |
+ {65, 0, 65, 7}, // vline between TC2 and TC3 | |
+ {99, 0, 99, 7}, // vline between TC3 and TC4 | |
+}; | |
+ | |
// Graphical LCD | |
U8GLIB_PI13264 u8g(LCD_CS, LCD_A0, LCD_RST); // Use HW-SPI | |
-//// Graph data | |
-int8_t graph[SENSOR_COUNT][MAXIMUM_GRAPH_POINTS]={}; // Array to hold graph data, in pixels | |
+// Graph data | |
+int16_t graph[SENSOR_COUNT][MAXIMUM_GRAPH_POINTS]={}; // Array to hold graph data, in temperature values | |
+ | |
uint8_t graphCurrentPoint; // Index of latest point added to the graph (0,MAXIMUM_GRAPH_POINTS] | |
uint8_t graphPoints; // Number of valid points to graph | |
-double graphMin; // Value of the minimum tick mark, in degrees | |
uint32_t graphScale; // Number of degrees per pixel in the graph[] array. | |
-uint8_t axisDigits; // Number of digits to display in the axis labels (ex: '80' -> 2, '1000' -> 4, '-999' -> 4) | |
+uint8_t axisDigits; // Number of digits to display in the axis labels (ex: '80' -> 2, '1000' -> 4, '-999' -> 4) | |
-double maxTemp = -99999; // highest temperature ever seen (for setting the scale) | |
-double minTemp = 99999; // lowest temperature ever seen (for setting the scale) | |
+float maxTemp = TEMP_MIN_VALUE_F; | |
+float minTemp = TEMP_MAX_VALUE_F; | |
// Get a reference to the graph point at the specified | |
// uint8_t& graphPoint(uint8_t sensor, uint8_t point) | |
@@ -41,111 +56,124 @@ double minTemp = 99999; // lowest temperature ever seen (for setting the scale | |
// @param min Minimum temperature value, in temperature | |
// @return representation of the temperature in graph space | |
#define temperatureToGraphPoint(temperature, scale, min) (DISPLAY_HEIGHT - 3 - (temperature-min)/scale*10) | |
-#define graphPointToTemperature(point, scale, min) (((double)(DISPLAY_HEIGHT - 3 - point))*scale/10.0 + min) | |
//#define rescaleGraphPoint(point, originalScale, originalMin, newScale, newMin) ((point - )) | |
+// Helper macros to go between int and float | |
+#define float_to_int(D) ((int16_t)((D)*10)) | |
+#define int_to_float(D) (((float)(D))/10.0) | |
-void resetGraph() { | |
+ | |
+void resetGraph() | |
+{ | |
graphCurrentPoint = 0; | |
graphPoints = 0; | |
- graphMin = 25; // TODO: sliding scale? | |
- graphScale = 1; // in 10ths | |
- | |
- maxTemp = 29; | |
- minTemp = 25; | |
-} | |
- | |
-void updateGraph(double* temperatures) { | |
- | |
- // Increment the current graph point (it wraps around) | |
- if(graphCurrentPoint == 0) { | |
- graphCurrentPoint = MAXIMUM_GRAPH_POINTS - 1; | |
- } | |
- else { | |
- graphCurrentPoint -= 1; | |
- } | |
- | |
- // Increment the number of stored graph points | |
- if(graphPoints < MAXIMUM_GRAPH_POINTS) { | |
- graphPoints++; | |
+ graphScale = 1; | |
+ | |
+ // Blank the array | |
+ for(uint8_t x = 0; x < SENSOR_COUNT; x++) | |
+ { | |
+ for(uint8_t y=0; y < MAXIMUM_GRAPH_POINTS; y++) | |
+ { | |
+ graph[x][y] = OUT_OF_RANGE_INT; | |
+ } | |
} | |
- // Test if any of the new temperatures are out of range, and adjust the graph appropriately. | |
+ return; | |
+} | |
- for(uint8_t sensor = 0; sensor < SENSOR_COUNT; sensor++) { | |
- if(temperatures[sensor] == OUT_OF_RANGE) { | |
- continue; | |
+// Update the graph using temperatures[NUM_SENSORS] | |
+void updateGraphData(float* temperatures) | |
+{ | |
+ int16_t temp_int; | |
+ | |
+ // Increment the current graph point (it wraps around) | |
+ if(graphCurrentPoint == 0) | |
+ { | |
+ graphCurrentPoint = MAXIMUM_GRAPH_POINTS - 1; | |
+ }else{ | |
+ graphCurrentPoint -= 1; | |
} | |
- if(temperatures[sensor] > maxTemp) { | |
- maxTemp = temperatures[sensor]; | |
+ // Increment the number of stored graph points | |
+ if(graphPoints < MAXIMUM_GRAPH_POINTS) { | |
+ graphPoints++; | |
} | |
- | |
- if(temperatures[sensor] < minTemp) { | |
- minTemp = temperatures[sensor]; | |
+ | |
+ // Stick the new temperature in the array | |
+ // This converts the temperature to a int16_t which is in 1/10ths of | |
+ // a degree | |
+ for(uint8_t sensor = 0; sensor < SENSOR_COUNT; sensor++) | |
+ { | |
+ temp_int = float_to_int(temperatures[sensor]); | |
+ graph[sensor][(graphCurrentPoint%MAXIMUM_GRAPH_POINTS)] = temp_int; | |
} | |
- } | |
- double graphMinLast = graphMin; | |
- uint32_t graphScaleLast = graphScale; | |
+ return; | |
+} | |
- // Shift the minimum value based on the lowest reading | |
- if(minTemp < graphMin) { | |
- graphMin = minTemp; | |
+void updateGraphScaling() | |
+{ | |
+ uint16_t delta; | |
+ int16_t max=TEMP_MIN_VALUE_I; | |
+ int16_t min=TEMP_MAX_VALUE_I; | |
+ int16_t * ptr; | |
+ int16_t p; | |
+ | |
+ // Itterate over all the data and get the max & min | |
+ for(uint8_t x = 0; x < SENSOR_COUNT; x++) | |
+ { | |
+ ptr = (int16_t*)&graph[x][0]; | |
+ for(uint8_t y=0; y < MAXIMUM_GRAPH_POINTS; y++) | |
+ { | |
+ p = *ptr; | |
+ if(p!=OUT_OF_RANGE_INT) | |
+ { | |
+ if(p>max) max = p; | |
+ if(p<min) min = p; | |
+ } | |
+ ptr++; | |
+ } | |
} | |
- // Expand the graph scale based on the current measurements | |
- if(maxTemp - graphMin > graphScale * 4) { | |
- graphScale = (maxTemp - graphMin + 3.999) / 4; // TODO: better rounding strategy | |
- } | |
+ if(max==TEMP_MIN_VALUE_I) max=0; | |
+ if(min==TEMP_MAX_VALUE_I) min=0; | |
- // TODO: Contract these later | |
- | |
- // If we need to scale or shift the graph, modify the existing readings first | |
- // TODO: Fix me! | |
- if(graphMinLast != graphMin || graphScaleLast != graphScale) { | |
- for(uint8_t sensor = 0; sensor < SENSOR_COUNT; sensor++) { | |
- for(uint8_t point = 0; point < MAXIMUM_GRAPH_POINTS; point++) { | |
- if(graph[sensor][point] != GRAPH_INVALID) { | |
- graph[sensor][point] = temperatureToGraphPoint( | |
- graphPointToTemperature(graph[sensor][point],graphScaleLast,graphMinLast), | |
- graphScale, | |
- graphMin); | |
- } | |
- } | |
- } | |
- } | |
+ minTemp = int_to_float(min); | |
+ maxTemp = int_to_float(max); | |
+ delta = max - min; | |
+ if(delta<4) maxTemp=minTemp+4.0; | |
- // Record the current readings in the graph | |
- for(uint8_t sensor = 0; sensor < SENSOR_COUNT; sensor++) { | |
- graphPoint(sensor, 0) = (temperatures[sensor] == | |
- OUT_OF_RANGE) ? GRAPH_INVALID : temperatureToGraphPoint(temperatures[sensor],graphScale,graphMin); | |
- } | |
+ graphScale = (uint32_t)((delta + 39) / 40); // TODO: better rounding strategy | |
+ if(graphScale<=0) graphScale = 1; | |
+ | |
+ // graphScale is an int multiplier. Normally we display 4 temperatures. | |
+ // maxTemp is the highest temp in the dataset | |
+ // minTemp is the lowest temp in the dataset | |
// Calculate the number of axes digits to display | |
- if(graphMin + graphScale*4 > 999 || graphMin < -99) { | |
+ axisDigits = 2; | |
+ if((min + (graphScale*4)) > 9999 || min < -999) { | |
axisDigits = 4; | |
} | |
- else if(graphMin + graphScale*4 > 99 || graphMin < -9) { | |
+ else if((min + (graphScale*4)) > 999 || min < -99) { | |
axisDigits = 3; | |
} | |
- else { | |
- axisDigits = 2; | |
- } | |
+ | |
+ return; | |
} | |
-void setup() { | |
+void setup() | |
+{ | |
u8g.setContrast(LCD_CONTRAST); // Set contrast level | |
- | |
u8g.setRot180(); // Rotate screen | |
u8g.setColorIndex(1); // Set color mode to binary | |
u8g.setFont(u8g_font_5x8r); // Select font. See https://code.google.com/p/u8glib/wiki/fontsize | |
} | |
+ | |
void draw( | |
- double* temperatures, | |
-// double ambient, | |
+ float* temperatures, | |
uint8_t graphChannel, | |
uint8_t temperatureUnit, | |
char* fileName, | |
@@ -155,93 +183,107 @@ void draw( | |
) { | |
// Graphic commands to redraw the complete screen should be placed here | |
- static char buf[8]; | |
- | |
+ char buf[8]; | |
uint8_t page = 0; | |
- u8g.firstPage(); // Update the screen | |
+ uint8_t x; | |
+ uint8_t lastPoint; | |
+ uint8_t battX = 128; | |
+ uint8_t battY = 9; | |
+ | |
+ // Update the screen | |
+ u8g.firstPage(); | |
do { | |
- //// Draw temperature graph | |
- if (page < 6) { | |
- if(page == 5) { | |
+ | |
+ // Draw temperature graph | |
+ switch(page){ | |
+ case 5: | |
u8g.drawLine( 0, 16, 132, 16); // hline between status bar and graph | |
- } | |
+ // no break | |
+ default: | |
// Draw the separator line between axes labels and legend | |
u8g.drawLine(CHARACTER_SPACING*axisDigits + 2, DISPLAY_HEIGHT, | |
CHARACTER_SPACING*axisDigits + 2, 18); | |
// Draw axis labels and marks | |
- for(uint8_t interval = 0; interval < GRAPH_INTERVALS; interval++) { | |
+ for(uint8_t interval = 0; interval < GRAPH_INTERVALS; interval++) | |
+ { | |
u8g.drawPixel(CHARACTER_SPACING*axisDigits + 1, 61 - interval*10); | |
- u8g.drawStr(0, DISPLAY_HEIGHT - interval*10, dtostrf(graphMin + graphScale*interval,axisDigits,0,buf)); | |
+ u8g.drawStr(0, DISPLAY_HEIGHT - interval*10, dtostrf(minTemp + graphScale*interval,axisDigits,0,buf)); | |
} | |
- | |
- // Draw labels on the right side of graph | |
- // TODO:scale these correctly? | |
- for(uint8_t sensor=0; sensor<4; sensor++){ | |
- if(temperatures[sensor] == OUT_OF_RANGE || sensor != graphChannel && graphChannel < 4) { | |
- continue; | |
- } | |
- u8g.drawStr(113+5*sensor, 3 + graphPoint(sensor, 0), dtostrf(sensor+1,1,0,buf)); | |
- }; | |
// Calculate how many graph points to display. | |
- uint8_t lastPoint = graphPoints; | |
+ lastPoint = graphPoints; | |
// If the axis indicies are >2 character length, scale back the graph. | |
- if(lastPoint > MAXIMUM_GRAPH_POINTS - (axisDigits - 2)*5) { | |
- lastPoint = MAXIMUM_GRAPH_POINTS - (axisDigits - 2)*5; | |
- } | |
+ x = MAXIMUM_GRAPH_POINTS - (axisDigits - 2)*5; | |
+ if(lastPoint > x) lastPoint = x; | |
// Draw the temperature graph for each sensor | |
- for(uint8_t sensor = 0; sensor < 4; sensor++) { | |
+ for(uint8_t sensor = 0; sensor < 4; sensor++) | |
+ { | |
+ int8_t p; | |
+ float p_float; | |
+ int16_t* starting_point; | |
+ int16_t* wrap_point; | |
+ | |
// if the sensor is out of range, don't show it | |
- if(temperatures[sensor] == OUT_OF_RANGE || sensor != graphChannel && graphChannel < 4) { | |
+ if(temperatures[sensor] == OUT_OF_RANGE || (sensor != graphChannel && graphChannel < 4) ) | |
continue; | |
- } | |
- | |
- int8_t* starting_point = &graph[sensor][graphCurrentPoint]; // Starting address of the graph data | |
- int8_t* wrap_point = &graph[sensor][MAXIMUM_GRAPH_POINTS]; // If the address pointer reaches this, reset it to graph[sensor][0] | |
- for(uint8_t point = 0; point < lastPoint; point++) { | |
- | |
- u8g.drawPixel(MAXIMUM_GRAPH_POINTS+12-point, | |
- *(starting_point++)); | |
- | |
+ // Get the latest point from the array | |
+ p_float = ((float)(graphPoint(sensor, 0)))/10.0; | |
+ p = temperatureToGraphPoint(p_float,graphScale,minTemp); | |
+ // Draw a string the the latest point | |
+ u8g.drawStr(113+5*sensor, 3 + p, dtostrf(sensor+1,1,0,buf)); | |
+ | |
+ // Now, draw all the points | |
+ starting_point = &graph[sensor][graphCurrentPoint]; // Starting address of the graph data | |
+ wrap_point = &graph[sensor][MAXIMUM_GRAPH_POINTS]; // If the address pointer reaches this, reset it to graph[sensor][0] | |
+ for(uint8_t point = 0; point < lastPoint; point++) | |
+ { | |
+ p_float = ((float)(*(starting_point++)))/10.0; | |
+ p = temperatureToGraphPoint(p_float,graphScale,minTemp); | |
+ u8g.drawPixel(MAXIMUM_GRAPH_POINTS+12-point,p); | |
if(starting_point == wrap_point) { | |
starting_point = &graph[sensor][0]; | |
} | |
- } | |
- } | |
- } | |
+ } // end for point | |
+ | |
+ }// end for sensor | |
+ | |
- //// Draw status bar | |
- else if(page == 6) { | |
+ break; | |
+ | |
+ case 6: | |
+ // Draw status bar | |
//u8g.drawStr(0, 15, dtostrf(ambient,5,1,buf)); // Ambient temperature | |
u8g.drawStr(0, 15, "TypK"); | |
- | |
u8g.drawStr(25, 13, "o"); | |
- if(temperatureUnit == TEMPERATURE_UNITS_C) { | |
+ switch(temperatureUnit){ | |
+ case TEMPERATURE_UNITS_C: | |
u8g.drawStr(30, 15, "C"); | |
- } | |
- else if(temperatureUnit == TEMPERATURE_UNITS_F) { | |
+ break; | |
+ case TEMPERATURE_UNITS_F: | |
u8g.drawStr(30, 15, "F"); | |
- } | |
- else { | |
+ break; | |
+ default: | |
u8g.drawStr(30, 15, "K"); | |
+ break; | |
} | |
- u8g.drawStr(40, 15,fileName); // File name | |
- | |
+ if(fileName==NULL) | |
+ u8g.drawStr(40, 15,"Not logging"); | |
+ else | |
+ u8g.drawStr(40, 15,fileName); | |
u8g.drawStr( 100, 15, dtostrf(logInterval,2,0,buf)); // Interval | |
u8g.drawStr(110, 15, "s"); | |
- | |
+ | |
// Draw battery | |
- const uint8_t battX = 128; | |
- const uint8_t battY = 9; | |
- if(bStatus == ChargeStatus::DISCHARGING) { | |
+ switch(bStatus){ | |
+ case ChargeStatus::DISCHARGING: | |
u8g.drawLine(battX, 14, battX+3, 14); | |
u8g.drawLine(battX, 14, battX, 10); | |
u8g.drawLine(battX+3, 14, battX+3, 10); | |
@@ -251,15 +293,15 @@ void draw( | |
for(uint8_t i = 0; i < batteryLevel; i++) { | |
u8g.drawLine(battX, 13-i, battX+3, 13-i); | |
} | |
- } | |
- else if(bStatus == ChargeStatus::NO_BATTERY) { | |
+ break; | |
+ case ChargeStatus::NO_BATTERY: | |
u8g.drawLine(battX, battY, battX, battY+5); | |
u8g.drawLine(battX, battY, battX+3, battY); | |
u8g.drawLine(battX, battY+2, battX+2, battY+2); | |
u8g.drawLine(battX, battY+5, battX+3, battY+5); | |
- } | |
- else if(bStatus == ChargeStatus::CHARGING) { | |
+ break; | |
+ case ChargeStatus::CHARGING: | |
u8g.drawLine(battX, 14, battX+3, 14); | |
u8g.drawLine(battX, 14, battX, 10); | |
u8g.drawLine(battX+3, 14, battX+3, 10); | |
@@ -270,31 +312,27 @@ void draw( | |
for(uint8_t i = 0; i < batteryState; i++) { | |
u8g.drawLine(battX, 13-i, battX+3, 13-i); | |
} | |
- } | |
- else { // CHARGED | |
+ break; | |
+ default: | |
+ // CHARGED | |
u8g.drawLine(battX, battY+1, battX, battY+5); | |
u8g.drawLine(battX+1, battY, battX+1, battY+5); | |
u8g.drawLine(battX+2, battY, battX+2, battY+5); | |
u8g.drawLine(battX+3, battY+1, battX+3, battY+5); | |
+ break; | |
} | |
- } | |
- | |
- //// Draw thermocouple readings | |
- else if (page == 7) { | |
- #define LINE_COUNT 4 | |
- const uint8_t lines[LINE_COUNT][4] = { | |
- { 0, 7, 132, 7}, // hline between temperatures and status bar | |
- {31, 0, 31, 7}, // vline between TC1 and TC2 | |
- {65, 0, 65, 7}, // vline between TC2 and TC3 | |
- {99, 0, 99, 7}, // vline between TC3 and TC4 | |
- }; | |
- | |
- for (uint8_t i = 0; i < LINE_COUNT; i++) { | |
+ break; | |
+ | |
+ case 7: | |
+ // Draw thermocouple readings | |
+ for (uint8_t i = 0; i < LINE_COUNT; i++) | |
+ { | |
const uint8_t* pos = lines[i]; | |
u8g.drawLine(pos[0], pos[1], pos[2], pos[3]); | |
} | |
// Display temperature readings | |
+ #if 1 | |
for(uint8_t sensor = 0; sensor < SENSOR_COUNT; sensor++) { | |
if(temperatures[sensor] == OUT_OF_RANGE) { | |
u8g.drawStr(sensor*34, 6, " ----"); | |
@@ -303,24 +341,43 @@ void draw( | |
u8g.drawStr(sensor*34, 6, dtostrf(temperatures[sensor], 5, 1, buf)); | |
} | |
} | |
- } | |
+ #elif 0 | |
+ // DEBUG: Write variable values to the spaces rather than the current temp | |
+ u8g.drawStr(0*34, 6, dtostrf(temperatures[0], 5, 1, buf)); | |
+ u8g.drawStr(1*34, 6, dtostrf(temperatures[1], 5, 1, buf)); | |
+ u8g.drawStr(2*34, 6, dtostrf(temperatures[2], 5, 1, buf)); | |
+ u8g.drawStr(3*34, 6, dtostrf(temperatures[3], 5, 1, buf)); | |
+ #else | |
+ // DEBUG: Write variable values to the spaces rather than the current temp | |
+ u8g.drawStr(0*34, 6, dtostrf(maxTemp, 5, 1, buf)); | |
+ u8g.drawStr(1*34, 6, dtostrf(minTemp, 5, 1, buf)); | |
+ u8g.drawStr(2*34, 6, dtostrf(graphScale, 5, 1, buf)); | |
+ u8g.drawStr(3*34, 6, " ----"); | |
+ #endif | |
+ break; | |
+ | |
+ } // End of select(page) | |
+ // Go to next page | |
page++; | |
- } | |
+ | |
+ }while( u8g.nextPage() ); | |
- while( u8g.nextPage() ); | |
+ return; | |
} | |
void clear() { | |
// Clear the screen | |
u8g.firstPage(); | |
- do { | |
- } while( u8g.nextPage() ); | |
+ while( u8g.nextPage() ); | |
} | |
-} | |
+} // End namespace Display | |
+ | |
-int32_t GetJunctionVoltage(double* jTemp) { | |
+// TODO: What namespace is this then? | |
+int32_t GetJunctionVoltage(double* jTemp) | |
+{ | |
int32_t jVoltage = 0; | |
uint8_t i = 0; | |
@@ -336,27 +393,33 @@ int32_t GetJunctionVoltage(double* jTemp) { | |
return jVoltage; | |
} | |
-double GetTypKTemp(int32_t microVolts) { | |
+float GetTypKTemp(int32_t microVolts) | |
+{ | |
+ float LookedupValue; | |
+ | |
// Input the junction temperature compensated voltage such that the junction | |
// temperature is compensated to 0°C | |
microVolts += TK_OFFSET; //Add an offset for the adjusted lookup table. | |
// Check if it's in range | |
- if(microVolts > TEMP_TYPE_K_MAX_CONVERSION || microVolts < TEMP_TYPE_K_MIN_CONVERSION){ | |
+ if(microVolts > TEMP_TYPE_K_MAX_CONVERSION || microVolts < TEMP_TYPE_K_MIN_CONVERSION) | |
+ { | |
return OUT_OF_RANGE; | |
} | |
- double LookedupValue; | |
- | |
// TODO: Binary search here to decrease lookup time | |
- for(uint16_t i = 0; i<TEMP_TYPE_K_LENGTH; i++){ | |
+ for(uint16_t i = 0; i<TEMP_TYPE_K_LENGTH; i++) | |
+ { | |
uint16_t valueLow = lookupThermocouleData(i); | |
uint16_t valueHigh = lookupThermocouleData(i + 1); | |
- if(microVolts >= valueLow && microVolts <= valueHigh){ | |
- LookedupValue = ((double)-270 + (i)*10) + ((10 *(double)(microVolts - valueLow)) / ((double)(valueHigh - valueLow))); | |
+ if(microVolts >= valueLow && microVolts <= valueHigh) | |
+ { | |
+ LookedupValue = ((float)-270 + (i)*10) + ((10 *(float)(microVolts - valueLow)) / ((float)(valueHigh - valueLow))); | |
break; | |
} | |
+ | |
} | |
+ | |
return LookedupValue; | |
} | |
diff --git a/t400/functions.h b/t400/functions.h | |
index 6ac63a7..489a7cb 100644 | |
--- a/t400/functions.h | |
+++ b/t400/functions.h | |
@@ -47,12 +47,13 @@ namespace Backlight { | |
namespace Display { | |
void resetGraph(); | |
- void updateGraph(double* temperatures); | |
+ void updateGraphData(float* temperatures); | |
+ void updateGraphScaling(); | |
void setup(); | |
void draw( | |
- double* temperatures, | |
+ float* temperatures, | |
// double ambient, | |
uint8_t graphChannel, | |
uint8_t temperatureUnit, | |
@@ -73,7 +74,7 @@ int32_t GetJunctionVoltage(double* jTemp); | |
// Converts the thermocouple µV reading into some usable °C | |
// @param microVolt reading from the ADC | |
// @return Temperature, in ??? | |
-double GetTypKTemp(int32_t microVolts); | |
+float GetTypKTemp(int32_t microVolts); | |
#endif | |
diff --git a/t400/t400.h b/t400/t400.h | |
index 46ea0ef..33f9db2 100644 | |
--- a/t400/t400.h | |
+++ b/t400/t400.h | |
@@ -1,41 +1,42 @@ | |
// Hardware definitions for the t400 | |
-#define __AVR_ATmega32U4__ 1 | |
+#define __AVR_ATmega32U4__ 1 | |
// Feature settings | |
-#define SD_LOGGING_ENABLED 1 // Enable/disable all SD card functionality. Saves 8,696 bytes | |
-#define SERIAL_OUTPUT_ENABLED 1 // Enable/disable serial output functionality. Saves 192 bytes | |
+#define SD_LOGGING_ENABLED 1 // Enable/disable all SD card functionality. Saves 8,696 bytes | |
+#define SERIAL_OUTPUT_ENABLED 1 // Enable/disable serial output functionality. Saves 192 bytes | |
// Calibration values | |
-#define MCP3424_CALIBRATION_MULTIPLY 1.00713 | |
-#define MCP3424_CALIBRATION_ADD 5.826 | |
-#define LCD_CONTRAST 0x018*7 // Sets the LCD contrast | |
+#define MCP3424_CALIBRATION_MULTIPLY 1.00713 | |
+#define MCP3424_CALIBRATION_ADD 5.826 | |
+#define LCD_CONTRAST 0x018*7 // Sets the LCD contrast | |
// Debugging | |
-#define DEBUG_JUNCTION_TEMPERATURE 0 | |
+#define DEBUG_JUNCTION_TEMPERATURE 0 | |
// Compile-time settings. Some of these should be set by the user during operation. | |
-#define SYNC_INTERVAL 1000 // millis between calls to sync() | |
-#define SENSOR_COUNT 4 // Number of sensors on the board (fixed) | |
-#define OUT_OF_RANGE 99999.9 // Double value representing an invalid temp. measurement | |
-#define GRAPH_INVALID -127 // Invalid graph point | |
+#define SYNC_INTERVAL 1000 // millis between calls to sync() | |
+#define SENSOR_COUNT 4 // Number of sensors on the board (fixed) | |
+#define OUT_OF_RANGE_INT 9999 // Int value representing an invalid temp. measurement | |
+#define OUT_OF_RANGE 999.9 // Double value representing an invalid temp. measurement | |
// Graph display settings | |
#define MAXIMUM_GRAPH_POINTS 100 | |
-#define DISPLAY_HEIGHT 64 // Height of the display | |
-#define CHARACTER_SPACING 5 // Width of a character+space to next character | |
+#define DISPLAY_HEIGHT 64 // Height of the display | |
+#define CHARACTER_SPACING 5 // Width of a character+space to next character | |
-#define TEMPERATURE_UNITS_C 0 | |
-#define TEMPERATURE_UNITS_F 1 | |
-#define TEMPERATURE_UNITS_K 2 | |
+#define TEMPERATURE_UNITS_C 0 | |
+#define TEMPERATURE_UNITS_F 1 | |
+#define TEMPERATURE_UNITS_K 2 | |
#define TEMPERATURE_UNITS_COUNT 3 | |
-#define GRAPH_CHANNELS_COUNT 5 | |
+ | |
+#define GRAPH_CHANNELS_COUNT 5 | |
/// I2C addresses | |
-#define MCP3424_ADDR 0x69 | |
+#define MCP3424_ADDR 0x69 | |
// Pin definitions for Electronics version 0.13 | |
-#define pcbVersion ".13" // Electronics version 0.12 milestone. | |
-#define FIRMWARE_VERSION "0.15" | |
+#define pcbVersion ".13" // Electronics version 0.12 milestone. | |
+#define FIRMWARE_VERSION "0.15" | |
// Pin definitions | |
#define BUTTON_B_PIN 1 // 0.12-mod 7, 0.13 1 | |
diff --git a/t400/t400.ino b/t400/t400.ino | |
index 3b19fd2..039a5ea 100644 | |
--- a/t400/t400.ino | |
+++ b/t400/t400.ino | |
@@ -24,49 +24,56 @@ Firmware for the Pax Instruments T400 temperature datalogger | |
// Import libraries | |
#include "t400.h" // Board definitions | |
-#include <Wire.h> // i2c | |
+#include <Wire.h> // I2C | |
#include <SPI.h> | |
-#include "PaxInstruments-U8glib.h" // LCD | |
-#include <MCP3424.h> // ADC | |
-#include <MCP980X.h> // Ambient/junction temperature sensor | |
-#include <ds3231.h> // RTC | |
- | |
+#include "PaxInstruments-U8glib.h" // LCD | |
+#include <MCP3424.h> // ADC | |
+#include <MCP980X.h> // Ambient/junction temperature sensor | |
+#include <ds3231.h> // RTC | |
#include "power.h" // Manage board power | |
#include "buttons.h" // User buttons | |
#include "typek_constant.h" // Thermocouple calibration table | |
#include "functions.h" // Misc. functions | |
#include "sd_log.h" // SD card utilities | |
+ | |
#define BUFF_MAX 80 // Size of the character buffer | |
char fileName[] = "LD0001.CSV"; | |
// MCP3424 for thermocouple measurements | |
-MCP3424 thermocoupleAdc(MCP3424_ADDR, MCP342X_GAIN_X8, MCP342X_16_BIT); // address, gain, resolution | |
+MCP3424 thermocoupleAdc(MCP3424_ADDR, MCP342X_GAIN_X8, MCP342X_16_BIT); // address, gain, resolution | |
MCP980X ambientSensor(0); // Ambient temperature sensor | |
+// Map of ADC inputs to thermocouple channels | |
+const uint8_t temperatureChannels[SENSOR_COUNT] = {1, 0, 3, 2}; | |
-const uint8_t temperatureChannels[SENSOR_COUNT] = {1, 0, 3, 2}; // Map of ADC inputs to thermocouple channels | |
-double temperatures[SENSOR_COUNT]; // Current temperature of each thermocouple input | |
-double ambient = 0; // Ambient temperature | |
+// Current temperature of each thermocouple input | |
+float temperatures[SENSOR_COUNT] = {OUT_OF_RANGE,OUT_OF_RANGE,OUT_OF_RANGE,OUT_OF_RANGE}; | |
+ | |
+// Ambient temperature | |
+double ambient = 0; | |
boolean backlightEnabled = true; | |
+// Available log intervals, in seconds | |
#define LOG_INTERVAL_COUNT 6 | |
-const uint8_t logIntervals[LOG_INTERVAL_COUNT] = {1, 2, 5, 10, 30, 60}; // Available log intervals, in seconds | |
-uint8_t logInterval = 0; // currently selected log interval | |
-boolean logging = false; // True if we are currently logging to a file | |
+const uint8_t logIntervals[LOG_INTERVAL_COUNT] = {1, 2, 5, 10, 30, 60}; | |
+ | |
+uint8_t logInterval = 0; // currently selected log interval | |
+boolean logging = false; // True if we are currently logging to a file | |
-bool timeToSample = false; // If true, the display should be redrawn | |
-uint8_t isrTick = 0; // Number of 1-second tics that have elapsed since the last sample | |
-uint8_t lastIsrTick = 0; // Last tick that we redrew the screen | |
-uint32_t logTimeSeconds; // Number of seconds that have elapsed since logging began | |
-struct ts rtcTime; // Buffer to read RTC time into | |
+bool timeToSample = false; // If true, the display should be redrawn | |
+uint8_t isrTick = 0; // Number of 1-second tics that have elapsed since the last sample | |
+uint8_t lastIsrTick = 0; // Last tick that we redrew the screen | |
+uint32_t logTimeSeconds; // Number of seconds that have elapsed since logging began | |
-uint8_t temperatureUnit; // Measurement unit for temperature | |
+struct ts rtcTime; // Buffer to read RTC time into | |
+ | |
+uint8_t temperatureUnit; // Measurement unit for temperature | |
uint8_t graphChannel = 4; | |
@@ -96,6 +103,8 @@ double convertTemperature(double Celcius) { | |
// This function runs once. Use it for setting up the program state. | |
void setup(void) { | |
+ uint8_t x; | |
+ | |
Power::setup(); | |
ChargeStatus::setup(); | |
#if SERIAL_OUTPUT_ENABLED | |
@@ -110,6 +119,10 @@ void setup(void) { | |
Display::setup(); | |
Display::resetGraph(); | |
+ // Clear the temperature array | |
+ //for(x=0;x<SENSOR_COUNT;x++) | |
+ // temperatures[x] = OUT_OF_RANGE; | |
+ | |
thermocoupleAdc.begin(); | |
ambientSensor.begin(); | |
@@ -153,7 +166,9 @@ static void readTemperatures() { | |
ambient = ambientSensor.readTempC16(AMBIENT) / 16.0; // Read ambient temperature in C | |
// ADC read loop: Start a measurement, wait until it is finished, then record it | |
- for(uint8_t channel = 0; channel < SENSOR_COUNT; channel++) { | |
+ for(uint8_t channel = 0; channel < SENSOR_COUNT; channel++) | |
+ { | |
+ | |
thermocoupleAdc.startMeasurement(temperatureChannels[channel]); | |
do { | |
// Delay a while. At 16-bit resolution, the ADC can do a speed of 1/15 = .066seconds/cycle | |
@@ -161,24 +176,41 @@ static void readTemperatures() { | |
delay(70); | |
} while(!thermocoupleAdc.measurementReady()); | |
+ | |
+ // This gets a float value. We do a y = mx+b for calibration | |
measuredVoltageUv = thermocoupleAdc.getMeasurementUv() * MCP3424_CALIBRATION_MULTIPLY + MCP3424_CALIBRATION_ADD; // Calibration value: MCP3424_OFFSET_CALIBRATION | |
compensatedVoltage = measuredVoltageUv + GetJunctionVoltage(&ambient); | |
temperature = GetTypKTemp(compensatedVoltage); | |
+ #if 0 | |
+ // TODO: Get the real value in a float, then convert it to a fixed point int, that | |
+ // way we can get rid of floating point math | |
+ temperature_int = float_to_int(temperature); | |
+ #endif | |
if(temperature == OUT_OF_RANGE) { | |
temperatures[channel] = OUT_OF_RANGE; | |
} | |
else { | |
- // temperatures[channel] = convertTemperature(temperature + ambient); | |
+ //temperatures[channel] = convertTemperature(temperature + ambient); | |
temperatures[channel] = convertTemperature(temperature); | |
} | |
-// This is some debugging code. Use it to display various values to the LCD. | |
-#if DEBUG_JUNCTION_TEMPERATURE | |
+ // DEBUG: Fake some data | |
+ #if 0 | |
+ temperatures[0] = 22.0; | |
+ temperatures[1] = OUT_OF_RANGE; | |
+ temperatures[2] = OUT_OF_RANGE; | |
+ temperatures[3] = OUT_OF_RANGE; | |
+ #endif | |
+ | |
+ | |
+ // This is some debugging code. Use it to display various values to the LCD. | |
+ #if DEBUG_JUNCTION_TEMPERATURE | |
if(channel == 2 ){// != OUT_OF_RANGE){ | |
temperatures[channel] = (double)measuredVoltageUv; // Display measured voltage across thermocouple. Everything looks good here. | |
} | |
-#endif | |
+ #endif | |
+ | |
} | |
} | |
@@ -224,25 +256,30 @@ void loop() { | |
readTemperatures(); | |
-// DS3231_get(&rtcTime); | |
+ //DS3231_get(&rtcTime); | |
writeOutputs(); | |
- Display::updateGraph(temperatures); | |
+ Display::updateGraphData(temperatures); | |
+ Display::updateGraphScaling(); | |
needsRefresh = true; | |
} | |
+ // Check for button presses | |
if(Buttons::pending()) { | |
uint8_t button = Buttons::getPending(); | |
- if(button == Buttons::BUTTON_POWER) { // Disable power | |
+ switch(button){ | |
+ case BUTTON_POWER: | |
+ // Disable power | |
if(!logging) { | |
Display::clear(); | |
Backlight::set(0); | |
Power::shutdown(); | |
} | |
- } | |
- else if(button == Buttons::BUTTON_A) { // Start/stop logging | |
+ break; | |
+ case BUTTON_A: | |
+ // Start/stop logging | |
#if SD_LOGGING_ENABLED | |
if(!logging) { | |
startLogging(); | |
@@ -253,8 +290,9 @@ void loop() { | |
resetTicks(); | |
needsRefresh = true; | |
#endif | |
- } | |
- else if(button == Buttons::BUTTON_B) { // Cycle log interval | |
+ break; | |
+ case BUTTON_B: | |
+ // Cycle log interval | |
if(!logging) { | |
logInterval = (logInterval + 1) % LOG_INTERVAL_COUNT; | |
resetTicks(); | |
@@ -263,26 +301,33 @@ void loop() { | |
resetTicks(); | |
needsRefresh = true; | |
} | |
- } | |
- else if(button == Buttons::BUTTON_C) { // Cycle temperature units | |
+ break; | |
+ case BUTTON_C: | |
+ // Cycle temperature units | |
if(!logging) { | |
rotateTemperatureUnit(); | |
resetTicks(); | |
needsRefresh = true; | |
} | |
- } | |
- else if(button == Buttons::BUTTON_D) { // Sensor display mode | |
+ break; | |
+ case BUTTON_D: | |
+ // Sensor display mode | |
graphChannel = (graphChannel + 1) % GRAPH_CHANNELS_COUNT; | |
while(graphChannel < 4 & temperatures[graphChannel] == OUT_OF_RANGE) { | |
graphChannel = (graphChannel + 1) % GRAPH_CHANNELS_COUNT; | |
} | |
needsRefresh = true; | |
- } | |
- else if(button == Buttons::BUTTON_E) { // Toggle backlight | |
+ break; | |
+ case BUTTON_E: | |
+ // Toggle backlight | |
backlightEnabled = !backlightEnabled; | |
Backlight::set(backlightEnabled); | |
- } | |
- } | |
+ break; | |
+ | |
+ default: break; | |
+ } // end button select | |
+ | |
+ } // end if button pending | |
// If we are charging, refresh the display every second to make the charging animation | |
if(ChargeStatus::get() == ChargeStatus::CHARGING) { | |
@@ -292,31 +337,22 @@ void loop() { | |
} | |
} | |
- if(needsRefresh) { | |
- if(logging) { | |
- Display::draw( | |
- temperatures, | |
- // ambient, | |
- graphChannel, | |
- temperatureUnit, | |
- fileName, | |
- logIntervals[logInterval], | |
- ChargeStatus::get(), | |
- ChargeStatus::getBatteryLevel() | |
- ); | |
- } | |
- else { | |
- Display::draw( | |
- temperatures, | |
- // ambient, | |
- graphChannel, | |
- temperatureUnit, | |
- "Not logging", | |
- logIntervals[logInterval], | |
- ChargeStatus::get(), | |
- ChargeStatus::getBatteryLevel() | |
- ); | |
- } | |
+ // Draw the display | |
+ if(needsRefresh) | |
+ { | |
+ char * ptr = NULL; | |
+ if(logging) ptr = fileName; | |
+ | |
+ Display::draw( | |
+ temperatures, | |
+ graphChannel, | |
+ temperatureUnit, | |
+ ptr, | |
+ logIntervals[logInterval], | |
+ ChargeStatus::get(), | |
+ ChargeStatus::getBatteryLevel() | |
+ ); | |
+ | |
} | |
// Sleep if we are on battery power | |
@@ -324,6 +360,8 @@ void loop() { | |
if(ChargeStatus::get() == ChargeStatus::DISCHARGING) { | |
Power::sleep(); | |
} | |
+ | |
+ return; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment