Jump to content
Sign in to follow this  
spirilis

Kitchen Roast! Thermocouple Monitor

Recommended Posts

This is my POTM for Nov-Dec 2013: http://forum.stellarisiti.com/topic/1773-open-43oh-stellarisiti-2013-nov-dec-project-of-the-month/?p=5545

 

This was a low-budget gift for my wife I put together in the last 3 days before christmas.  I chose the Stellaris LaunchPad simply because I had no firm plans for it, and I have two Tiva-C LaunchPads that succeed it.  The application itself would be much better fit for an MSP430 (and could be implemented with battery power too) but alas, it was a good test of my last-minute resourcefulness  :D

 

First, pics!

 

We start with the TI Stellaris LaunchPad.

post-163-1426460534398_thumb.jpg

 

Then home-etch a PCB using the laser toner-transfer process and ferric chloride, with some MG Liquid Tin for a nice tin protective coating:

post-163-14264605344246_thumb.jpg

post-163-14264605344503_thumb.jpg

 

This board features the MAX31855 Thermocouple Amplifier chipset along with a Nordic nRF24L01+ PA+LNA board with external antenna.  The latter is used to report temperatures to my Linux server, which posts them on a webpage every 30 seconds so my wife can view the state of her roast remotely with her iPad.

 

Then add @@bluehash 's first attempt at the Nokia 1202 BoosterPack, unfortunately the LCD on this board had its white backing removed (noob mistake I have not repeated since) so the LCD has a weird background effect to it-

post-163-14264605344753_thumb.jpg

 

Stack them all together:

post-163-14264605345011_thumb.jpg

 

I am not good with woodworking, but I made an exception here and worked hard with a circular saw and dremel out in my garage.  Used boiled linseed oil as a simple coating on the outside of the enclosure, milled out the holes with a drill & dremel...

post-163-14264605345264_thumb.jpg

 

It could definitely use some strain relief for the cord, I'll probably wrap it around the bottom female headers of the Stellaris LaunchPad at some point:

post-163-1426460534581_thumb.jpg

 

Anyway, my wife used it to make fudge and to make a rib roast for Christmas and it turned out perfectly!  This unit is expandable, meaning I can pop the top and replace/re-etch the boosterpacks as I see fit.  If she asks, I may implement more than one MAX31855 and possibly home-etch a Nokia 1202 boosterpack with pushbuttons with some implement to allow her to press them from the top wooden cover.

 

Board files for the custom MAX31855+nRF24L01+ PCB: Thermocouple_BPak40_draft1.zip (DipTrace)

Nokia 1202 boosterpack from 43oh: http://forum.43oh.com/topic/3724-43oh-nokia-1202-lcd-display-boosterpack/

 

Code:

 

Used Energia 11 for this one.  First off, 2 libraries:

Nokia1202 - https://github.com/spirilis/Nokia1202

Enrf24 - https://github.com/spirilis/Enrf24

 

Nokia1202 requires 9-bit SPI, while I have an alternative Energia SPI lib for MSP430, I didn't have one for Stellaris/Tiva-C.

It required one update.  Updated energia-0101E0011/hardware/lm4f/libraries/SPI/SPI.cpp and SPI.h files: SPI_lm4f_9bit.zip

 

Energia sketch:

#include <ste2007.h>
#include <Nokia1202.h>
#include <Enrf24.h>
#include <nRF24L01.h>
#include <SPI.h>


struct MAX31855_DATUM {
  uint32_t rawData;
  int16_t tcDecimalC;
  int16_t tcC;
  int16_t tcF;
  int16_t ambDecimalC;
  int16_t ambC;
  int16_t ambF;
  uint8_t faultBits;
};

void max31855_read(struct MAX31855_DATUM *);

#define TC_CS PA_3
#define nRF24_CE PC_7
#define nRF24_CSN PE_0
#define nRF24_IRQ PD_6
#define LCD_BL PA_4
#define LCD_CS PA_5
#define LCD_RST PA_6
#define RADIO_CHANNEL 10
#define RADIO_ID 20
// 30-seconds between polls
#define WAIT_TIME 30

const uint8_t radio_basestation[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01};

Nokia1202 lcd(LCD_CS);
Enrf24 radio(nRF24_CE, nRF24_CSN, nRF24_IRQ);

void setup()
{
  // put your setup code here, to run once:
  //Serial.setBufferSize(512, 64);
  Serial.begin(115200);

  Serial.println("Init TC CS, SPI-");  
  pinMode(TC_CS, OUTPUT); digitalWrite(TC_CS, HIGH);
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(1);
 
  radio.begin(250000, RADIO_CHANNEL);
  radio.setCRC(true, true);
  radio.setTXaddress(radio_basestation);
  radio.autoAck(false);

  // Manually reset LCD
  Serial.println("Resetting LCD-");
  pinMode(LCD_BL, OUTPUT); digitalWrite(LCD_BL, HIGH);
  pinMode(LCD_RST, OUTPUT); digitalWrite(LCD_RST, LOW);
  delay(250);
  digitalWrite(LCD_RST, HIGH);
  Serial.println("Init LCD-");
  lcd.begin();  // Cursor enabled, contrast at medium, tabstop=4
  lcd.clear();
  Serial.println("Writing splash screen-");
  lcd.print("Kitchen Roast!\nTemp Reporter\n\n");
  lcd.print("From Eric with\nLove \n\n");
  lcd.print("Web address:\nsisko.lan/roast");
  delay(2500);
  Serial.println("LCD splash screen delay complete-");
}

void loop()
{
  uint8_t nrfmsg[32], cursor = 0;
  struct MAX31855_DATUM tc;
  uint32_t lastupdate;

  Serial.println("max31855_read()-");
  max31855_read(&tc);
  // Update display
  Serial.println("LCD update-");
  lcd.clear();
  lcd.println("Kitchen Roast!");
  lcd.setCursor(0,2);
  lcd.print("Temp: "); lcd.print(tc.tcF); lcd.print('\x7f'); lcd.println("F");
  lcd.print("     ("); lcd.print(tc.tcC); lcd.print('\x7f'); lcd.println("C)");

  if (tc.faultBits) {
    lcd.setCursor(0, 7);
    if (tc.faultBits & 0x01)
      lcd.print("DISCON ");
    if (tc.faultBits & 0x06)
      lcd.print("SHORT ");
  }
  lcd.setCursor(0, 6);
  lcd.print("sisko.lan/roast");

  Serial.println("nRF24 radio transmit-");
  nrfmsg[0] = 0x10;  // PROTO = THERMOCOUPLE UPDATE
  nrfmsg[1] = 0x06;
  nrfmsg[2] = RADIO_ID;
  nrfmsg[3] = tc.tcC & 0x00FF;
  nrfmsg[4] = tc.tcC >> 8;
  nrfmsg[5] = tc.ambC & 0x00FF;
  nrfmsg[6] = tc.ambC >> 8;
  nrfmsg[7] = tc.faultBits;
  radio.write(nrfmsg, 8);
  radio.flush();
  
  Serial.print("Waiting "); Serial.print(WAIT_TIME); Serial.println(" seconds before next update-");
  lastupdate = millis();
  while ( (millis() - lastupdate) < 1000*WAIT_TIME ) {
    delay(1000);
    lcd.setCursor(15, cursor);
    cursor ^= 1;
  }
  
}

void max31855_read(struct MAX31855_DATUM *datum)
{
  uint32_t tcread;
  int16_t tmp;
  
  digitalWrite(TC_CS, LOW);
  tcread = SPI.transfer(0) << 24;
  tcread |= SPI.transfer(0) << 16;
  tcread |= SPI.transfer(0) << 8;
  tcread |= SPI.transfer(0);
  digitalWrite(TC_CS, HIGH);
  
  datum->rawData = tcread;
  
  // Thermocouple temp, degrees C and F
  tmp = (tcread & 0xFFFC0000) >> 18;
  if (tmp & 0x2000)
    tmp |= 0xC000;  // sign-extend
  // tmp = TC deg C decimal
  datum->tcDecimalC = tmp;
  datum->tcC = tmp / 4;
  datum->tcF = ((tmp * 9) / 5 + (32*4)) / 4;
  
  // Ambient temp, degrees C and F
  tmp = (tcread & 0x0000FFF0) >> 4;
  if (tmp & 0x0800)
    tmp |= 0xF000;  // sign-extend
  // tmp = Amb deg C decimal
  datum->ambDecimalC = tmp;
  datum->ambC = tmp / 16;
  datum->ambF = ((tmp * 9) / 5 + (32*16)) / 16;
  
  // Fault information
  datum->faultBits = tcread & 0x00000007;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×