July 2023

Feather Aircraft 6x Thermocouple Monitor


Functional Requirements

  • Read up to 6x K type thermocouples
  • Display temperature readings and indicate visually if any are lower or higher than normal.
  • Daylight readable display.
  • 12 VDC power input

 

 

Components

 

Custom FeatherWing

Mounts to the 2.9" Grayscale eInk / ePaper Display FeatherWing or the 2.9" tri-color eInk display and accepts the mounting of up to 8x of the Adafruit Analog Output K-Type Thermocouple Amplifier - AD8495 Breakout.  

Analog input connections A0 to A5 are routed to each of the thermocouple amplifiers, but each one has a pair of tabs with a thin trace that can be cut if the analog input assignments need to be changed.   The seventh optional thermocouple breakout connection is not used for this application.  

12 VDC input to the screw terminals provides 1A of 5V power to the Feather Vbus connection.   WARNING: Do not connect power to the Feather USB connector while this connection is powered as well.  

The PCB overall dimensions are 80 x 65 mm.   This PCB will mount directly behind the 2.9" eInk display (centered), with the height of this PCB larger than the display in order to accommodate mounting of the thermocouple breakouts on the top and bottom.  

 

Firmware


/*
  proj_aircraft_6x_thermocouple_monitor.ino
  
  Feather Aircraft 6x Thermocouple Monitor
  
  Adafruit M0 Basic (SMD21) microcontroller
  
  Adafruit Analog Output K-Type Thermocouple Amplifier - AD8495 Breakout 
  Adafruit PN 1778
  Adafruit tutorial: https://learn.adafruit.com/ad8495-thermocouple-amplifier?view=all


  Custom FeatherWing by Mechatronic Solutions LLC
  https://savvymicrocontrollersolutions.info/feather.php?article=feather-holding-tank-level-monitor
  
*/

// In Arduino IDE, select 'Tools','Board','Adafruit Boards','Adafruit Feather M0 SMD21...'

/////////////////////////////////////////////////////////////////////////
// Show serial messages when DEBUG = true, otherwise minimize them.
#define DEBUG false

/////////////////////////////////////////////////////////////////////////
// M0/M4 Express built-in hardware

const uint8_t pinBuiltInLED = 13;  

const byte pinLiPoly = A6;

/////////////////////////////////////////////////////////////////////////
// ThinkInk 290 Grayscale4 T5 Display
//
// Adafruit PN 4777
// Adafruit 2.9" Grayscale eInk / ePaper Display FeatherWing - 4 Level Grayscale
// Adafruit tutorial: https://learn.adafruit.com/adafruit-eink-display-breakouts?view=all#grayscale-29-overview
// 2.9" grayscale display with 296x128 pixels
// MicroSD socket

#include "Adafruit_ThinkInk.h"

// Below configured for M0/M4
#define EPD_DC      10 // can be any pin, but required!
#define EPD_CS      9  // can be any pin, but required!
#define EPD_BUSY    -1  // can set to -1 to not use a pin (will wait a fixed delay)
#define SRAM_CS     6  // can set to -1 to not use a pin (uses a lot of RAM!)
#define EPD_RESET   -1  // can set to -1 and share with chip Reset (can't deep sleep)

// 2.9" Grayscale Featherwing or Breakout:
ThinkInk_290_Grayscale4_T5 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY);

#define COLOR1 EPD_BLACK
#define COLOR2 EPD_LIGHT
#define COLOR3 EPD_DARK

// Each pixel can be white, light gray, dark gray or black.
// Update time is only about 1 second (other displays take 15 sec). 

//////////////////////////////////////////////////////////////////////////////
// Adafruit Analog Output K-Type Thermocouple Amplifier - AD8495 Breakout 

float getTcTempF(uint8_t adc_pin) {
  uint16_t raw_adc = analogRead(adc_pin);
  // AREF = 3.3 V   ADC resolution = 10 bit
  float voltage = raw_adc * (3.3 / (pow(2, 10)-1));
  // T (deg C) = (Vo - 1.5) / 5 mV
  // Vo = T * 5 mV + 1.25 V
  // the output sensitivity is 0.005 volts per degree Celsius
  float temp_c = (voltage - 1.25) / 0.005;
  float temp_f = temp_c * 9.0/5.0+32;
  #if DEBUG
  Serial.println();
  Serial.print("raw_adc: "); Serial.println(raw_adc);
  Serial.print("voltage: "); Serial.println(voltage);
  Serial.print("temp_c: "); Serial.println(temp_c);
  Serial.print("temp_f: "); Serial.println(temp_f);
  #endif
  return temp_f;
} // getTcTempF()

/////////////////////////////////////////////////////////////////////////

void updateDisplay() {
  digitalWrite(pinBuiltInLED, HIGH);

  /*
  float cht1 = 156.1 + static_cast<float>(random(1,200));
  float cht2 = 156.2 + static_cast<float>(random(1,200));
  float cht3 = 156.3 + static_cast<float>(random(1,200));
  float cht4 = 156.4 + static_cast<float>(random(1,200));
  float egt1 = 1000.1 + static_cast<float>(random(50,330));
  float egt2 = 1000.2 + static_cast<float>(random(50,330));
  */

  float cht1 = getTcTempF(A0);
  float cht2 = getTcTempF(A1);
  float cht3 = getTcTempF(A2);
  float cht4 = getTcTempF(A3);
  float egt1 = getTcTempF(A4);
  float egt2 = getTcTempF(A5);
  
  display.clearBuffer();

  // With .setTextSize(2), you get 7 rows of 23 characters/line
  // Characters are 12 px wide x 14 px tall
  // With spacing between rows and frame, start text at:
  //  (4,6), (4,23), (4,40), (4,56), (4,74), (4,91), (4,108)
  display.setTextSize(2);    
  display.setTextColor(EPD_BLACK);
  
  if (cht1 > 356.0) {
    // max continuous cyl head temp is 356 F
    display.print("*");
  }
  // (6,0),(6,14),(6,28),(6,42),(6,56),(6,70),(6,84),(6,96)
  display.setCursor(12,20);
  //     .print("012345678901234567890123");  // .setTextSize(2);
  display.print("CHT 1 ");
  display.print(cht1, 0);

  if (cht2 > 356.0) {
    // max continuous cyl head temp is 356 F
    display.print("*");
  }
  display.setCursor(12,45);
  display.print("CHT 2 ");
  display.print(cht2, 0);

  if (cht3 > 356.0) {
    // max continuous cyl head temp is 356 F
    display.print("*");
  }
  display.setCursor(12,70);
  display.print("CHT 3 ");
  display.print(cht3, 0);

  if (cht4 > 356.0) {
    // max continuous cyl head temp is 356 F
    display.print("*");
  }
  display.setCursor(12,95);
  display.print("CHT 4 ");
  display.print(cht4, 0);

  if (egt1 < 1112 || egt1 > 1292.0) {
    // EGT min (above 50% power) = 1112 F
    // EGT max (above 70% power) = 1292 F
    display.print("*");
  }
  
  display.setCursor(160,20);  
  display.print("EGT 1 ");
  display.print(egt1, 0);

  if (egt1 < 1112 || egt1 > 1292.0) {
    // EGT min (above 50% power) = 1112 F
    // EGT max (above 70% power) = 1292 F
    display.print("*");
  }
  display.setCursor(160,45);  
  display.print("EGT 2 ");
  display.print(egt2, 0);
      
  display.display();
  digitalWrite(pinBuiltInLED, LOW);
  yield();
  
} // updateDisplay()

/////////////////////////////////////////////////////////////////////////
// TimerA

const uint32_t TIMER_A_INTERVAL_MS = 30000;  
uint32_t timer_a_lap_ms = 0;  // timer


void timerA() {
  //  Timer A

  if (timer_a_lap_ms > millis())  timer_a_lap_ms = millis();
  if (millis() - timer_a_lap_ms > TIMER_A_INTERVAL_MS) { 
    updateDisplay();
    timer_a_lap_ms = millis(); // reset the timer
  }
} // timerA()

/////////////////////////////////////////////////////////////////////////


void setup() {

  pinMode(pinBuiltInLED, OUTPUT);

  #if DEBUG
  Serial.begin(115200);
  while (!Serial) {
    delay(1);
  }
  Serial.println("\nSerial ready");
  #endif

  // ThinkInk 290 Grayscale4 T5 Display
  // Adafruit EPD full update test in mono & grayscale
  // 296x128 pixels
  // See also:  Adafruit Graphics Primatives:  https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives
  //            Adafruit GFX Graphics Library: https://learn.adafruit.com/adafruit-gfx-graphics-library?view=all
  display.begin(THINKINK_GRAYSCALE4); // grayscale mode
  
  // Adafruit Analog Output K-Type Thermocouple Amplifier - AD8495 Breakout
  
  
  updateDisplay();

  #if DEBUG
  Serial.println("Setup finished");
  #endif
  
} // setup()


void loop() {
  
  timerA();

} // loop()

 


Do you need help developing or customizing a IoT product for your needs?   Send me an email requesting a free one hour phone / web share consultation.  

 

The information presented on this website is for the author's use only.   Use of this information by anyone other than the author is offered as guidelines and non-professional advice only.   No liability is assumed by the author or this web site.