Skip to content

Commit

Permalink
Hobbs meter
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcourt authored and tomcourt committed Jul 2, 2017
1 parent f098779 commit 6a04c74
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 57 deletions.
40 changes: 20 additions & 20 deletions enguino/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ const char *red = "red";
// The MX macro converts a floating point factor for m into an integer factor. The gauge pointers vary from 0 to 1000.
// Use GB() and GMX to set the graphs b and m values based on lowest input and input range (hi-low) respectively.
//
const Sensor opS = { st_r240to33, 0, MX(0.1), 0, MX(1.0)}; // 0 - 100
const Sensor otS = { st_thermistorF, 0, MX(.1), GB(50*10), GMX(200*10)}; // 50 - 250
const Sensor vtS = { st_volts, 0, MX(ADCtoV10), GB(100*V10toADC), GMX(60*V10toADC)}; // 100 - 160 (10 - 16)
const Sensor fpS = { st_r240to33, 0, MX(0.1), 0, MX(1.0)}; // 0 - 100 (0 - 10)
const Sensor flS = { st_r240to33, 0, MX(0.16), 0, MX(1.0)}; // 0 - 160 (0 - 16)
const Sensor taS = { st_tachometer, 0, 12000, 0, 8008 }; // 0 - 3000
const Sensor maS = { st_volts, 100, 2000, 0, 8008}; // 100 - 350 (10 - 35)
const Sensor chS = { st_k_type_tcF, 0, MX(.25), GB(100*4), GMX(400*4)}; // 100 - 500, input is .25 deg. F
const Sensor egS = { st_k_type_tcF, 0, MX(.25), GB(1000*4), GMX(600*4)}; // 1000 - 1600,input is .25 deg. F
const Sensor opS = { st_r240to33, 0, MX(0.1), 0, MX(1.0), 1}; // 0 - 100
const Sensor otS = { st_thermistorF, 0, MX(.1), GB(50*10), GMX(200*10), 2}; // 50 - 250
const Sensor vtS = { st_volts, 0, MX(ADCtoV10), GB(100*V10toADC), GMX(60*V10toADC), 0}; // 100 - 160 (10 - 16)
const Sensor fpS = { st_r240to33, 0, MX(0.1), 0, MX(1.0), 3}; // 0 - 100 (0 - 10)
const Sensor flS = { st_r240to33, 0, MX(0.16), 0, MX(1.0), 4}; // 0 - 160 (0 - 16)
const Sensor taS = { st_tachometer, 0, 12000, 0, 8008, -1}; // 0 - 3000
const Sensor maS = { st_volts, 100, 2000, 0, 8008, -1}; // 100 - 350 (10 - 35)
const Sensor chS = { st_k_type_tcF, 0, MX(.25), GB(100*4), GMX(400*4), 16}; // 100 - 500, input is .25 deg. F
const Sensor egS = { st_k_type_tcF, 0, MX(.25), GB(1000*4), GMX(600*4), 20}; // 1000 - 1600,input is .25 deg. F

// Labels
// ------
Expand Down Expand Up @@ -78,16 +78,16 @@ int chRP[] = { 1000, 6000, 7940, 8000 };
// -----------------------
#define bank 3500 // bank of misc vertical gauges
const Gauge gauges[] = {
// x, y, style, decimal, label1, label2, units, labVal, labPt,num, regClr, regPt, num, sensor, pin
{bank+0, 0, gs_vert, 0, "OIL", "PRES", "psi", opLV, opLP, N(opLV), opRC, opRP, N(opRC), &opS, 1},
{bank+1750, 0, gs_vert, 0, "OIL", "TEMP", "°F", otLV, otLP, N(otLV), otRC, otRP, N(otRC), &otS, 2},
{bank+3500, 0, gs_vert, 1, "", "VOLT", "volt", vtLV, vtLP, N(vtLV), vtRC, vtRP, N(vtRC), &vtS, 0},
{bank+5250, 0, gs_vert, 1, "FUEL", "PRES", "psi", fpLV, fpLP, N(fpLV), fpRC, fpRP, N(fpRC), &fpS, 3},
{bank+7000, 0, gs_pair, 1, "FUEL", "", "gal", flLV, flLP, N(flLV), flRC, flRP, N(flRC), &flS, 4}, // pins 4 and 5
{100, 0, gs_round, 0, "TACH", "", "rpm", 0, 0, 0, taRC, taRP, N(taRC), &taS, -1},
{100, 3200, gs_round, 1, "MP", "", "in-hg", 0, 0, 0, maRC, maRP, N(maRC), &maS, -1},
{2950, 6150, gs_horiz, 0, "CHT", "", "", chLV, chLP, N(chLV), chRC, chRP, N(chRC), &chS, 16},
{2950, 6150, gs_aux, 0, "EGT", "", "", egLV, egLP, N(egLV), 0, 0, 0, &egS, 20},
{700, 6500, gs_infobox,0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0}
// x, y, style, decimal, label1, label2, units, labVal, labPt,num, regClr, regPt, num, sensor
{bank+0, 0, gs_vert, 0, "OIL", "PRES", "psi", opLV, opLP, N(opLV), opRC, opRP, N(opRC), &opS},
{bank+1750, 0, gs_vert, 0, "OIL", "TEMP", "°F", otLV, otLP, N(otLV), otRC, otRP, N(otRC), &otS},
{bank+3500, 0, gs_vert, 1, "", "VOLT", "volt", vtLV, vtLP, N(vtLV), vtRC, vtRP, N(vtRC), &vtS},
{bank+5250, 0, gs_vert, 1, "FUEL", "PRES", "psi", fpLV, fpLP, N(fpLV), fpRC, fpRP, N(fpRC), &fpS},
{bank+7000, 0, gs_pair, 1, "FUEL", "", "gal", flLV, flLP, N(flLV), flRC, flRP, N(flRC), &flS},
{100, 0, gs_round, 0, "TACH", "", "rpm", 0, 0, 0, taRC, taRP, N(taRC), &taS},
{100, 3200, gs_round, 1, "MP", "", "in-hg", 0, 0, 0, maRC, maRP, N(maRC), &maS},
{2950, 6150, gs_horiz, 0, "CHT", "", "", chLV, chLP, N(chLV), chRC, chRP, N(chRC), &chS},
{2950, 6150, gs_aux, 0, "EGT", "", "", egLV, egLP, N(egLV), 0, 0, 0, &egS},
{300, 6150, gs_infobox,0, "", "", "", 0, 0, 0, 0, 0, 0, 0}
};

3 changes: 1 addition & 2 deletions enguino/egTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef struct {
int vfactor; // int_reading = multiply * sensor >> divisor + offset
int moffset; // used to calculate marker position
int mfactor; // 0-4000 vertical gauge, 0-8000 horizontal gauge, 0-2400 round gauge
signed char pin;
} Sensor;

enum GaugeStyle { gs_vert, gs_pair, gs_round, gs_horiz, gs_aux, gs_infobox };
Expand All @@ -57,8 +58,6 @@ typedef struct {
byte n_regions;

const Sensor *sensor;

signed char pin; // first pin if multiple sensors (cht/egt, fuel)
} Gauge;

enum GaugeColor { gc_green, gc_yellow, gc_red };
Expand Down
36 changes: 27 additions & 9 deletions enguino/enguino.ino
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ IPAddress ip(192, 168, 0, 111);
EthernetServer server(80);
EthernetClient client;

int readGauge(const Gauge *g, byte n = 0);
bool leanMode = false;
int readSensor(const Sensor *s, byte n = 0);
bool leanMode;
int peakEGT[4];
byte hobbsCount = 90;

// Performance 'print' functions to ethernet 'client' (includes flush)
#include "printEthernet.h"
Expand Down Expand Up @@ -75,8 +76,8 @@ InterpolateTable r240to33 = {
},
};

int readGauge(const Gauge *g, byte n = 0) {
int p = g->pin + n;
int readSensor(const Sensor *s, byte n = 0) {
int p = s->pin + n;

#ifdef RANDOM_SENSORS
if (p < 16)
Expand All @@ -92,7 +93,7 @@ int readGauge(const Gauge *g, byte n = 0) {
if (p < 0)
return FAULT;

int t = g->sensor->type;
int t = s->type;
int toF = 0;
if (p < 16) {
v = analogRead(p);
Expand Down Expand Up @@ -143,11 +144,11 @@ void serveUpWebPage(char url) {


void setup() {
Serial.begin(9600);
// while (!Serial)
// ; // wait for serial port to connect. Stops here until Serial Monitor is started. Good for debugging setup
// Serial.begin(9600);
// while (!Serial)
// ; // wait for serial port to connect. Stops here until Serial Monitor is started. Good for debugging setup

eeInit();
eeInit();
tcTempSetup();
printLEDSetup();
printLED(0,LED_TEXT(h,o,b,b));
Expand Down Expand Up @@ -207,4 +208,21 @@ void loop() {
// close the connection:
client.stop();
}

if (eighthSecondCount >= 8) {
bool running = scaleValue(&vtS, readSensor(&vtS)) > 130; // greater than 13.0 volts means engine is running

if (running) {
if (--hobbsCount == 0) {
if (++(ee_status.hobbs) > 39999) {
ee_status.hobbs = 0;
ee_status.hobbs1k++;
}
eeUpdateStatus();
hobbsCount = 90;
}
}

eighthSecondCount -= 8;
}
}
20 changes: 13 additions & 7 deletions enguino/persist.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,29 @@ typedef struct {

typedef struct {
byte sequence;
byte filler;
byte hobbs1k; // thousands of an hour rollover
word hobbs; // hobbs in 1/40 of an hour 0-999.975 (0-39,999)
word fuel; // fuel remaining in 1/40 of a gallon (10 GPH, changes every 9 seconds)
word filler;
} EEStatus;

EESettings ee_settings;
EEStatus ee_status;

static byte nextSlot = 1;
static byte nextSlot;

// slot 0 is for settings, slots 1 through 63 is for status, status' storage slot is distributed for 'wear-leveling'
// each slot has the data written twice, the second time is inverted
// if the first half doesn't match the inverted second half than return false (no valid data)
static bool eeRead(byte slot, void *buffer) {
int address = slot << 4;

byte *cp = buffer;
for (byte i=8; i; i--)
*cp++ = EEPROM.read(address++);
cp = buffer;
for (byte i=8; i; i--)
if (*cp++ != EEPROM.read(address++) ^ 0xFF)
if (*cp++ != (EEPROM.read(address++) ^ 0xFF))
return false;
return true;
}
Expand Down Expand Up @@ -61,15 +62,20 @@ void eeInit() {
// search all the slots for the highest sequence number
bool found = false;
EEStatus temp;
while (nextSlot++ < 64) {
if (!eeRead(nextSlot, &temp))
for (byte i=1; i<64; i++) {
if (!eeRead(i, &temp))
continue;
// handle rollover math for sequence number
if (found && (signed char)(temp.sequence - ee_status.sequence) <= 0)
continue;
ee_status = temp;
nextSlot = i + 1;
if (nextSlot > 63)
nextSlot = 1;
found = true;
}
if (found)
return;
nextSlot = 2;
// ee_status.ALL = 0; zeroed in initialization
eeWrite(1, (void *)&ee_status);
Expand All @@ -84,8 +90,8 @@ void eeUpdateSettings() {
// 15,000+ hour eeprom lifetime (at 10GPH) with updates whenever hobbs or gallons changes
void eeUpdateStatus() {
ee_status.sequence++;
eeWrite(0, &ee_status);
if (++nextSlot == 0)
eeWrite(nextSlot, &ee_status);
if (++nextSlot > 63)
nextSlot = 1;
}

33 changes: 19 additions & 14 deletions enguino/printGauges.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ int scaleValue(const Sensor *s, int val) {
// vertical gauge is
// 1200 wide except extra room on right needed for labels (centered at 600)
// 5950 high
void printVertical(const Gauge *g, bool showLabels) {
void printVertical(const Gauge *g, bool showLabels=true, byte pinOffset=0) {
#ifdef BOUNDING_BOX
print_P(F("<rect x='0' y='0' width='1200' height='5950' fill='none' stroke='orange'/>\n"));
#endif
// starts at 1100, 4000 high
print_P(F("<rect x='400' y='1000' width='400' height='4000' class='rectgauge'/>\n"));

int val = readGauge(g);
int val = readSensor(g->sensor, pinOffset);
int mark = scaleMark(g->sensor, val) << 2;

const char *color = 0;
Expand Down Expand Up @@ -106,7 +106,7 @@ void printHorizontal(const Gauge *g, int count) {
print(600+offset);
print_P(F("' width='8000' height='400' class='rectgauge'/>\n"));

int val = readGauge(g, n);
int val = readSensor(g->sensor, n);
int mark = scaleMark(g->sensor, val) << 3;

const char *color = 0;
Expand Down Expand Up @@ -184,7 +184,7 @@ void printAuxHoriz(const Gauge *g, int count) {
#endif
int offset = 0;
for (int n=0; n<count; n++) {
int val = readGauge(g, n);
int val = readSensor(g->sensor, n);
int mark = scaleMark(g->sensor, val) << 3;

if (val == FAULT) {
Expand All @@ -197,7 +197,7 @@ void printAuxHoriz(const Gauge *g, int count) {
logValue(peakEGT[n],"peak");
if (val > peakEGT[n])
peakEGT[n] = val;
if (val+11 < peakEGT[n])
if (val+12 < peakEGT[n]) // minimium of 5 deg. F drop before showing negative
val -= peakEGT[n];
}
print_P(F("<text x='9700' y='"));
Expand Down Expand Up @@ -243,13 +243,12 @@ void printVerticalPair(const Gauge *g) {
print_P(F("<text x='1350' y='400' class='label'>"));
print_text_close(g->label1);

Gauge t = *g;
t.label2 = "LEFT";
printVertical(&t, false);
t.label2 = "RGT";
t.pin++;
Gauge tg = *g;
tg.label2 = "LEFT";
printVertical(&tg, false, 0);
tg.label2 = "RGT";
print_P(F("<g transform='translate(1500 0)'>"));
printVertical(&t, false);
printVertical(&tg, false, 1);
print_g_close();
// add tick marks and labels
for (int i=0; i<g->n_labels; i++) {
Expand Down Expand Up @@ -303,7 +302,7 @@ void printRound(const Gauge *g) {
print_P(F("<text x='0' y='5900' 700='unit'>"));
print_text_close(g->units);

int val = readGauge(g);
int val = readSensor(g->sensor);
int mark = (scaleMark(g->sensor, val) * 24) / 10;

int scale = scaleValue(g->sensor, val);
Expand Down Expand Up @@ -345,13 +344,19 @@ void printInfoBox() {
print_P(F("<rect x='0' y='0' width='1600' height='600' fill='none' stroke='orange'/>\n"));
#endif

print_P(F("<g x='0' y='0' width='1600' height='600' onClick=\"javascript:ajax('?');\">\n"
print_P(F("<g width='1600' height='600' onClick=\"javascript:ajax('?');\">\n"
"<rect width='1600' height='600' rx='100' ry='100' class='abutton'/>\n"
"<text x='800' y='475' class='value'>"));
if (leanMode)
print_P(F("Cancel</text></g>\n"));
else
print_P(F("Lean</text></g>\n"));

print_P(F("<text x='800' y='1100' class='unit' fill='black'>Hobbs: "));
if (ee_status.hobbs1k)
print(ee_status.hobbs1k);
print(ee_status.hobbs >> 2, 1);
print_text_close();
}


Expand All @@ -363,7 +368,7 @@ void printGauge(const Gauge *g) {
print_P(F(")'>\n"));
switch(g->style) {
case gs_vert:
printVertical(g, true);
printVertical(g);
break;
case gs_pair:
printVerticalPair(g);
Expand Down
36 changes: 36 additions & 0 deletions enguino/printWeb.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,39 @@ void printHomePage() {
"</html>\n"
));
}

void printSetupPage() {
print_P(F(
"<!DOCTYPE html>\n"
"<html>\n"
"<style>\n"
"form {\n"
"border: solid gray;\n"
"border-radius: 1em;\n"
"padding: 1em;\n"
"position: absolute;\n"
"top: 50%;\n"
"left: 50%;\n"
"margin-right: -50%;\n"
"transform: translate(-50%, -50%);\n"
"}\n"
"input {\n"
"margin-right: 1em;\n"
"}\n"
"</style>\n"
"<form>\n"
"<input type='radio' name='x' value='a' checked/>Add fuel<br>\n"
"<input type='radio' name='x' value='f'/>Set fuel capacity<br>\n"
"<input type='radio' name='x' value='h'/>Set hobbs<br>\n"
"<input type='radio' name='x' value='k'/>Set fuel flow k<br>\n"
"<br>\n"
"<input type='number' name='n' pattern='[0-9]*'/>\n"
"<input type='submit'/><br>\n"
"<br>\n"
"<input type='submit' value='Tanks Filled' onClick=\"javascript:location.href = '/fill';\"/>\n"
"<input type='submit' value='Cancel' style='float:right;' onClick=\"javascript:location.href = '/';\"/\n"
"</form>\n"
"</html>\n"
));
}

9 changes: 6 additions & 3 deletions enguino/tcTemp.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

volatile int tcTemp[9]; // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

volatile byte eighthSecondCount = 0;

int readSPI() {
word v = 0;
for (byte i=16; i!=0; i--) {
Expand Down Expand Up @@ -43,7 +45,7 @@ void tcTempSetup() {
TIMSK0 |= _BV(OCIE0A);
}

// Interrupt is called every millisecond
// Interrupt is called every millisecond (a little slower, actually 976.5625 Hz)
SIGNAL(TIMER0_COMPA_vect)
{
static byte ms = 0;
Expand All @@ -56,12 +58,12 @@ SIGNAL(TIMER0_COMPA_vect)
digitalWrite(PINA2, ch&4);
// ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
}
else if (ms == 5) {
else if (ms == 21) {
// begin conversion
digitalWrite(PINCS, HIGH);
// ... wait 100 mS for conversion to complete
}
else if (ms == 105) {
else if (ms == 121) { // spec says 100mS, IRQ's are a bit slower, so this is >100mS
// stop conversion, start serial interface
digitalWrite(PINCS, LOW);
// 100nS min. delay implied
Expand All @@ -81,6 +83,7 @@ SIGNAL(TIMER0_COMPA_vect)
ch = 0;
}
ms = 255; // ++ will make this 0
eighthSecondCount++;
}
ms++;
}
Expand Down
Loading

0 comments on commit 6a04c74

Please sign in to comment.