Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
Moved Aux display to standard i2c pints
  • Loading branch information
tomcourt authored and tomcourt committed Jul 29, 2017
1 parent 21bcaf0 commit 2404091
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 212 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,22 @@ The supply is rated for 1000 ma. The Leonardo uses 82 mA (confirmed by testing).

| Arduino | 32U4 | Use |IRQ|Analog|Counter| Assign |
|---------|-------|-------------|---|------|-------|---------|
| D0 | PD2 | Serial RX | * | | | Aux-Sw |
| D0 | PD2 | Serial RX | * | | | Tach |
| D1 | PD3 | Serial TX | * | | | Fuel-F |
| D2 | PD1 | SDA | * | | | Tach |
| D2 | PD1 | SDA | * | | | Aux-SDA |
| D3 | PD0 | SCL/PWM | * | | | Aux-SCL |
| D4 | PD4 | TC Mux A0 | | * | * | |
| D4 | PD4 | TC Mux A0 | | A6 | * | |
| D5 | PC6 | TC Mux A1 | | | | |
| D6 | PD7 | TC Mux A2 | | * | * | |
| D6 | PD7 | TC Mux A2 | | A7 | * | |
| D7 | PE6 | TC Mux EN | * | | | |
| D8 | PB4 | TC CS | | * | | |
| D9 | PB5 | Analog 9 | | * | | |
| D10 | PB6 | Ether CS | | * | | |
| D11 | PB7 | PWM | | | | Aux-SDA |
| D12 | PD6 | TC MISO | | * | | |
| D8 | PB4 | Analog 8 | | A8 | | MAP |
| D9 | PB5 | TC CS | | A9 | | |
| D10 | PB6 | Ether CS | | A10 | | |
| D11 | PB7 | PWM | | | | Aux-Sw |
| D12 | PD6 | TC MISO | | A11 | | |
| D13 | PC7 | TC SCLK/LED | | | | ||

The SD card on the Leonardo can not be used with the thermocouple board attached as they both use pin D4. The thermocouple board also interferes with 4 of the analog inputs. The Leonardo also interferes with one of the analog inputs.
The SD card on the Leonardo can not be used with the thermocouple board attached as they both use pin D4. The thermocouple board also interferes with 4 of the analog inputs. The Leonardo itself also interferes with one of the analog inputs.

The D6 and D12 pins support counters which would be useful for the tach and fuel flow. But the thermocouple board also conflicts with this. Interrupt pins will be used instead. With the tach, assume 2 pulses per revolution at 2700 RPM the tach will max out at 90/cps so as long as IRQ disable time is <11ms no error should be expected. For the fuel flow with a k-factor of 68,000 and 13GPH it will max out at 250/cps so IRQ disable time must be <4ms.

Expand Down Expand Up @@ -184,8 +184,8 @@ Once an alert has been acknowledged the display will no longer switch to it auto
### Future stuff
* Record engine data by having the Engiuno pipe text to a port on the Stratux. The startup script on the stratux starts netcat (nc) in the background to record the text to a file. The script would also truncate the file at on powerup to limit its growth.
* It may be possible to support 2 (or maybe more) thermocouples without the thermocouple multiplexer shield by using the differential mode ADC, 40x gain and a CJC sensor(Analog TMP36). Only 8 bits are usable with 40x, the noisy lower bits help with oversampling though. 488 uV per count works out to 21.5 deg. F resolution with a K type thermocouple. The 2.56 volt internal reference would double the resolution and oversampling could probably quadruple it (16x oversample). ADC0 and ADC1 are the negative side, any other ADC pin may be positive. With a filtering cap (10nF) several thermocouples could share a pin. The internal ATMEGA temperature sensor needs both offset and gain calibration, a 10 deg-C rise is typical as well, 2 point calibration may be much to expect for users. **TBD** - move the voltage divider sensor to ADC5 to allow future use of thermocouples.
* A custom shield might be helpful particularly if it were populated. Jumpers would select resistors and maybe filter caps. This would eliminate most to all of the soldering involved. A 4 bit shift register on the thermocouple mux would free up 4 more analog pins on the Leanardo.
* A custom aux display board would also help. A single LED drive chip could be used as one chip can support 8 LED digits, one display on the high 8 rows, the second on the low 8 on rows, even numbered columns. A bright master caution/warning LED would be easy using the empty rows. And a smaller 7 segment LED modules could be used to allow fitting the display in a 2.25" hole. The switch could be a long post pushbutton on the board that would go through a small hole on the display.
* A custom shield might be helpful for the typical user who isn't proficient with a soldering iron, particularly if it were populated. Jumpers would select resistors and maybe filter caps. A thermocouple board that didn't interfere with the ADC would add 4 more analog inputs (perhaps a latch for the mux or an I2C thermocouple/mux like Linear's LTC2495CUHF#PBF). An ammeter feature will be desired by some, TI's INA170 High Side Current Shunt Monitor is probably a good part to implement this. Support 12 thermocouples for 6 cylinder? Support for 24 volt electrical system?
* A custom aux display board would also help. A single LED drive chip could be used as one chip can support 8 LED digits. A smaller 7 segment LED modules could be used to allow fitting the display in a 2.25" hole. The switch could be of the long posted tactile pushbutton style mounted to the board that would go through a small hole on the display (similar to a digikey EG4356TR-ND). The switch wire could be eliminated from the harness if 2 or 3 separate switches are attached to the chip (only presses are detected, holds aren't).
* The Arduino Yun would support airplanes lacking a Stratux. The code would need to use the 'bridge' objects instead of the ethernet objects. Use #ifdef AVR_YUN to flex the code.
* Themes - a dark theme could be created easily enough by adjusting the styles. A larger text theme for the gauges would involve more defines and stringizing them for the SVG.
* Warning lights instead of auxiliary display? A board with 4 caution/warning LEDs (red/green common cathode [bicolor LED]). Turning red and green on produces yellow. Alternatively use a module like the [BOB-13884] to provide 3 RGB LED's.
Expand Down
33 changes: 19 additions & 14 deletions enguino/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

#define TACH_DIVIDER 4

#define DEFAULT_K_FACTOR (68000L / 40) // for fuel flow transducer

// Exceed any of these and engine will be considered 'running'. Hobbs time will accumulate and engine alerts will appear. A 0 value will cause that sensor to be ignored.
#define RUN_VOLT 130
#define RUN_OILP 10
#define RUN_OILP 30
#define RUN_TACH 200

// Sensor defintions and scaling
Expand All @@ -28,19 +30,21 @@
// st_j_type_tcC 0 - 4000 0-1000 degrees C. in quarters
// st_k_type_tcF 0 - 4000 32-1832 degrees F. in quarters
// st_j_type_tcF 0 - 4000 32-1832 degrees F. in quarters
// st_tachometer
// st_fuel_flow
// st_unit unit values, RPM, fuel flow, hobbs

// sensor-type, pin, decimal, voffset, vfactor, goffset, gfactor,lowWarning,lowCaution,highCaution,highWarning
const Sensor oilpS = { st_v240to33, 1, 0, 0, SCALE(.100), 0, SCALE(1.), 25, 55, 9999, 95 };
const Sensor oiltS = { st_thermistorF, 2, 0, 0, SCALE(.100), GMIN(50*10), GRNG(200*10), -1, 140, 9999, 250 };
const Sensor voltS = { st_volts, 0, 1, 0, SCALE(.200), GMIN(100*fromV), GRNG(60*fromV), 110, 130, 9999, 160 };
const Sensor fuelpS = { st_v240to33, 3, 1, 0, SCALE(.150), 0, SCALE(150./100.), 5, 20, 60, 80 };
const Sensor fuellS = { st_v240to33, DUAL(4), 1, 0, SCALE(.160), 0, SCALE(1.), 25, 50, 9999, 999 };
const Sensor tachS = { st_tachometer, 15, 0, 0, SCALE(1.), GMIN(0), GRNG(3000), -1, 500, 9999, 2700 };
const Sensor mapS = { st_volts, 9, 1, 102, SCALE(.32811), GMIN(210),GRNG(1000*25/32.811), -1, -1, 9999, 9999 };
const Sensor fuellS = { st_v240to33, DUAL(4), 1, 0, SCALE(.160), 0, SCALE(1.), 25, 50, 9999, 999 };
const Sensor tachS = { st_unit, TACH_SENSOR, 0, 0, SCALE(1.), GMIN(0), GRNG(3000), -1, 500, 9999, 2700 };
const Sensor mapS = { st_volts, 8, 1, 102, SCALE(.32811), GMIN(210),GRNG(1000*25/32.811), -1, -1, 9999, 9999 };
const Sensor chtS = { st_k_type_tcF, 16, 0, 0, SCALE(.25), GMIN(100*4), GRNG(400*4), -1, 150, 400, 500 };
const Sensor egtS = { st_k_type_tcF, 20, 0, 0, SCALE(.25), GMIN(1000*4), GRNG(600*4), -1, -1, 9999, 9999 };
const Sensor fuelfS = { st_unit, FUELF_SENSOR, 1, 0, SCALE(1.), GMIN(0), GRNG(150), -1, -1, 9999, 9999 };
const Sensor fuelrS = { st_unit, FUELR_SENSOR, 1, 0, SCALE(1.), GMIN(0), GRNG(400), -1, -1, 9999, 9999 };
const Sensor hobbsS = { st_unit, HOBBS_SENSOR, 1, 0, SCALE(1.), GMIN(0), GRNG(1000), -1, -1, 9999, 9999 };

// Label and gradations
// --------------------
Expand Down Expand Up @@ -95,22 +99,23 @@ const Gauge gauges[] = {
{100, 0, gs_round, "TACH", "", "rpm", 0, 0, 0, tachRC, tachRP, N(tachRC), &tachS},
{100, 3200, gs_round, "MP", "", "in-hg", 0, 0, 0, mapRC, mapRP, N(mapRC), &mapS},
{2950, 6150, gs_horiz, "CHT", "", "", chtLV, chtLP, N(chtLV), chtRC, chtRP, N(chtRC), &chtS},
{2950, 6150, gs_aux, "EGT", "", "", egtLV, egtLP, N(egtLV), 0, 0, 0, &egtS},
{2950, 6150, gs_egt, "EGT", "", "", egtLV, egtLP, N(egtLV), 0, 0, 0, &egtS},
{800, 6650, gs_infobox,"", "", "", 0, 0, 0, 0, 0, 0, 0}
};

// Guage layout for aux display
// ----------------------------
// Layout is text, top-sensor, bottom-sensor. Sensor value is displayed in the top line if text is blank, otherwise top sensor is used to show warning/caution and low/high on top line
AuxDisplay auxDisplay[] = {
AUX(b,A,t, , voltS, voltS),
AUX( , , , , tachS, fuellS),
AUX(O,P, , , oilpS, oilpS),
AUX(O,t, , , oiltS, oiltS),
AUX(F,P, , , fuelpS, fuelpS),
AUX(A,L,t, , voltS, voltS),
AUX(H,o,b,b, 0, &hobbsS),
AUX(b,A,t, , &voltS, &voltS),
AUX( , , , , &tachS, &fuellS),
AUX(O,P, , , &oilpS, &oilpS),
AUX(O,t, , , &oiltS, &oiltS),
AUX(F,P, , , &fuelpS, &fuelpS),
AUX(A,L,t, , &voltS, &voltS),
};

// number of pages shown on startup
#define AUX_STARTUP_PAGES 1
#define AUX_STARTUP_PAGES 2

34 changes: 31 additions & 3 deletions enguino/egTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,37 @@

typedef const char * string;

// for persist.h
// -------------
// both of these must be exactly 8 bytes in size
typedef struct {
word fullFuel;
word kFactor; // counts per 1/40 gallon
word filler1;
word filler2;
} EESettings;

typedef struct {
byte sequence;
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;

// for sensor.h
// ------------
typedef struct {
int start;
byte n;
const byte *log2diff;
const int *result;
} InterpolateTable;

enum SensorType {st_r240to33, st_v240to33, st_thermistorF, st_thermistorC, st_volts, st_k_type_tcF, st_j_type_tcF, st_k_type_tcC, st_j_type_tcC, st_tachometer, st_fuel_flow};
enum SensorType {st_r240to33, st_v240to33, st_thermistorF, st_thermistorC, st_volts, st_k_type_tcF, st_j_type_tcF, st_k_type_tcC, st_j_type_tcC, st_unit};

typedef struct {
SensorType type;
Expand All @@ -29,7 +52,7 @@ typedef struct {
int highWarning;
} Sensor;

enum GaugeStyle { gs_vert, gs_pair, gs_round, gs_horiz, gs_aux, gs_infobox };
enum GaugeStyle { gs_vert, gs_pair, gs_round, gs_horiz, gs_egt, gs_infobox };

typedef struct {
int x;
Expand All @@ -53,6 +76,11 @@ typedef struct {

enum GaugeColor { gc_green, gc_yellow, gc_red };

#define TACH_SENSOR 15
#define FUELF_SENSOR 14
#define FUELR_SENSOR 13
#define HOBBS_SENSOR 12

// alert states
#define WARNING_LOW 1
#define WARNING_HIGH 2
Expand Down Expand Up @@ -82,7 +110,7 @@ typedef struct {
#define VSEG(x) (.5+4000*(x))
#define HSEG(x) (.5+8000*(x))

#define AUX(a,b,c,d,top,bottom) {{LED_TEXT(a,b,c,d)},{&top,&bottom}}
#define AUX(a,b,c,d,top,bottom) {{LED_TEXT(a,b,c,d)},{top,bottom}}

const char *green = "green";
const char *yellow = "yellow";
Expand Down
132 changes: 57 additions & 75 deletions enguino/enguino.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,44 @@
#include <string.h>
#include <avr/pgmspace.h> // storing strings in Flash to save RAM

// Temporary chang this your local network's IP range for testing
IPAddress ip(192, 168, 0, 111); // http:https://192.168.0.111 is link to Enguino

// fictitious MAC address. Only real critera is the first byte's 2 lsb must be 1 (for local) and 0 (for unicast).
byte mac[] = { 0xDE, 0x15, 0x24, 0x33, 0x42, 0x51 };

EthernetServer server(80); // Port 80 is HTTP
EthernetClient client;

// #define DEBUG // checks RAM usage
// #define SIMULATE_SENSORS 3 // number of simulated sensor 'states', use serial to advace state

// sketches don't like typdef's so they are in in this header file instead
#include "egTypes.h"

#include "utility.h"

#include "persist.h"

// Digital pin assignments
#define AUX_SWITCH 0
#define TACH_SIGNAL 2

#define HOBBS_COUNT_INTERVAL (3600/40) // update hobbs 40 times an hour
bool leanMode;
int peakEGT[4];
byte hobbsCount = 3600/40; // update hobbs 40 times an hour
bool eeUpdateDirty;
byte hobbsCount = HOBBS_COUNT_INTERVAL/2; // in order to prevent cumulative hobbs error assume half a hobbs count of engine run time was lost on last shutdown
bool engineRunning;

volatile unsigned long lastTachTime;
volatile bool tachDidPulse;
volatile int rpm[8];
volatile byte rpmInx;

#define SIMULATE_SENSORS 1
#include "sensors.h"

// printLED functions for the auxiliary display
#include "printLED.h"

// configuration of sensors and layout of the gauges
#include "config.h"

#include "sensors.h"

// load and save persistant EEPROM data
#include "persist.h"

// Performance 'print' functions to ethernet 'client' (includes flush)
#include "printEthernet.h"

Expand All @@ -41,21 +49,16 @@ volatile byte rpmInx;
#include "printGauges.h"
#include "printWeb.h"

// Measure thermocouple tempertaures in the background
// Measure thermocouple tempertures in the background
#include "tcTemp.h"

bool dimAux;
bool didHoldKey;
bool didChangeDim;
byte auxPage = AUX_STARTUP_PAGES; // next page is info page
byte auxPage = 0;
signed char blinkAux[2];

void tachIRQ() {
unsigned long newTachTime = micros();
rpm[rpmInx++ & 7] = (60000000L/TACH_DIVIDER) / (newTachTime - lastTachTime);
lastTachTime = newTachTime;
tachDidPulse = true;
}


void updateAlerts() {
for (byte i=AUX_STARTUP_PAGES; i<N(auxDisplay); i++) {
Expand Down Expand Up @@ -153,18 +156,18 @@ void setup() {
// while (!Serial)
// ; // wait for serial port to connect. Stops here until Serial Monitor is started. Good for debugging setup

pinMode(AUX_SWITCH, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(TACH_SIGNAL),tachIRQ,RISING);
sensorSetup();

delay(1); // delay to allow LED display chip to startup
eeInit();

eeInit();

tcTempSetup();
printLEDSetup();
printLED(0,LED_TEXT(h,o,b,b));
printLED(1,ee_status.hobbs>>2,1);
delay(1000);
showAuxPage(0);
delay(1000);
for (auxPage=0; auxPage<AUX_STARTUP_PAGES; auxPage++) {
showAuxPage(auxPage);
delay(2000);
}
switchPress = 0;

// start the Ethernet connection and the server:
Expand Down Expand Up @@ -204,27 +207,20 @@ void loop() {
didHoldKey = false;
}
else if (switchDown >= 8 && !didHoldKey) {
// Hold (acknowedge all, reshow all)
// ---------------------------------
if (blinkAux[0] > 0 || blinkAux[1] > 0 || auxDisplay[auxPage].caution > 0 || auxDisplay[auxPage].warning > 0) {
ackBlink();
for (byte i=AUX_STARTUP_PAGES; i<N(auxDisplay); i++)
ackAlert(i);
}
else {
// un-ack all and reshow alerts
blinkAux[0] = blinkAux[1] = 0;
for (byte i=AUX_STARTUP_PAGES; i<N(auxDisplay); i++)
auxDisplay[i].warning = auxDisplay[i].caution = 0;
}
// Hold (reshow all)
// -----------------
// un-ack all and reshow alerts
blinkAux[0] = blinkAux[1] = 0;
for (byte i=AUX_STARTUP_PAGES; i<N(auxDisplay); i++)
auxDisplay[i].warning = auxDisplay[i].caution = 0;
auxPage = AUX_STARTUP_PAGES;
didHoldKey = true;
}

#if SIMULATE_SENSORS
if (Serial.read() >= 0) {
if (++simState > 3)
simState = 1;
if (++simState >= SIMULATE_SENSORS)
simState = 0;
}
#endif

Expand All @@ -233,41 +229,27 @@ void loop() {
if (eighthSecondTick) {
eighthSecondTick = false;
updateADC();

if (eighthSecondCount == 4)
goto halfSecond;
if (eighthSecondCount >= 8) {
if (tachDidPulse)
tachDidPulse = false;
else
memset(rpm, 0, sizeof(rpm));

engineRunning = true
#if RUN_VOLT
|| scaleValue(&voltS, readSensor(&voltS)) > RUN_VOLT
#endif
#if RUN_OILP
|| scaleValue(&oilpS, readSensor(&oilpS)) > RUN_OILP
#endif
#if RUN_TACH
|| scaleValue(&tachS, readSensor(&tachS)) > RUN_TACH

if (eighthSecondCount == 4 || eighthSecondCount >= 8) {
if (eighthSecondCount >= 8) { // every second
#if DEBUG
logValue(minFreeRam,"minFreeRam");
#endif
;

updateTach();

engineRunning = isEngineRunning();

if (engineRunning) {
if (--hobbsCount == 0) {
if (++(ee_status.hobbs) > 39999) {
ee_status.hobbs = 0;
ee_status.hobbs1k++;
}
if (engineRunning)
updateHobbs();

if (eeUpdateDirty) {
eeUpdateStatus();
hobbsCount = 90;
}
eeUpdateDirty = false;
}
eighthSecondCount -= 8;
}

eighthSecondCount -= 8;

halfSecond:
// every half second
if (engineRunning) {
alertStatus = STATUS_NORMAL;
updateAlerts();
Expand All @@ -276,7 +258,7 @@ halfSecond:
}
else
alertStatus = STATUS_WARNING;
showAuxPage(auxPage);
showAuxPage(auxPage);
}
}
}
Loading

0 comments on commit 2404091

Please sign in to comment.