// sketch for ATLAS Upgrade Interlock II // Bart Hommels // University of Cambridge // Version history: // release v 1.0 dd 30/11/2012 // v1.01 05/12/2012 added proper timeout to sht readout. 28906B Sketch size // v1.02 12/12/2012 fixed garbled display bug //+-------------------------------------------------------+ // Libraries #include #include #include "Wire.h"// for driving SPI, I2C buses #include "LiquidCrystal.h"// for LCD on SPI #include // for using EEPROM #include "EEPROMAnything.h" // for writing multiple-byte objects to EEPROM #include // low memory useage NTC readout class #include "SHTxx.h" // for reading out SHT7x on I2C using namespace myardu; // for SHT7x on I2C //#define DEBUG // flag to enable debug information / code #define ENTER 13 // byte value of the Enter key (LF) //+-------------------------------------------------------+ #ifdef DEBUG // Memory Usage Monitoring extern unsigned int __heap_start; extern void *__brkval; /* * The free list structure as maintained by the * avr-libc memory allocation routines. */ struct __freelist { size_t sz; struct __freelist *nx; }; /* The head of the free list structure */ extern struct __freelist *__flp; #endif // +-------------------------------------------------------+ // Definitions const char fwVersion[5] = "1.02"; const char fwDate[11] = "12/12/2012"; const char dataRequestString[4] = "idr";// Interlock Unit Data Request const char settingsRequestString[4] = "irs";// Interlock Read Settings const char write2EepromString[4] = "wre";//Write to EEPROM const char enableRequestString[4] = "ena";// Enable request const char disableRequestString[4] = "dis";// Disable request const char* lookup_table[] = { "tl","th", "ne", "na", "rn", "tn", "bn", "rl", "rh"};// serial command decoder enum{ Tlow, Thigh, Nenable, nSamples, Rnom, Tnom, Bntc, RHlow, RHhigh, None };// serial command enumeration // enumerate menu states enum{ DefaultMenu, DeviceMenu, TLimitsMenu, SetTemperatureLimit, StoreTemperatureLimit, NTCMenu, SetHNEnable, SetUNEnable, StoreHNEnable, StoreUNEnable, NTCValuesMenu, SetNTCNSamples, StoreNTCNSamples, SetNTCRnom, StoreNTCRnom, SetNTCTnom, StoreNTCTnom, SetNTCB, StoreNTCB, SHTMenu, SetSHTEnable, SHTRHLimitsMenu, SetSHTRHLimit, StoreSHTRHLimit }; // +-------------------------------------------------------+ // pin assignments const byte hNTCMuxPin = A0; const byte uNTC09Pin = A1; const byte uNTC08Pin = A2; const byte menuPot = A3; const byte i2cData = A4; const byte i2cClk = A5; const byte d0_output = 0; const byte d1_output = 1; const byte muxCtrl2 = 2; const byte menuButton = 3; const byte lcdLatch = 4; const byte lcdClk = 5; const byte lcdData = 6; const byte duoLed = 7; const byte outputEnable = 8; const byte selectRseries = 9; const byte muxCtrl0 = 10; const byte muxCtrl1 = 11; const byte enablePbLED = 12; const byte pbEnable = 13; //+-------------------------------------------------------+ // variables // stuff to do with the serial interface char cmdbuf[4], intbuf[5]; byte nBytes = 0; int inSerial = 0; // High, low temperature limits for H0-7, U8-9 NTCs, SHT7x RH/T sensor. // values here are extremely conservative fallbacks. actual settings should be collected from EEPROM float h_NTC_T_Hi = 30.0; float h_NTC_T_Lo = 10.0; float u_NTC_T_Hi = 30.0; float u_NTC_T_Lo = 10.0; float SHT_T_Hi = 30.0; float SHT_T_Lo = 10.0; float SHT_RH_Hi = 60.0; float SHT_RH_Lo = 30.0; // NTC parameters to reconstruct temperature from ADC readings byte h_NTC_Rnom = 10;// H0-7 NTC resistance at nominal T, in kOhm. Hardware options are 1, 10kOhm byte h_NTC_Tnom = 25;// H0-7 NTC nominal temperature unsigned int h_NTC_B = 3435; // H0-7 NTC B factor // U8-9 NTC defaults (use GL23 for the moment: R(20 deg C) = 2kOhm, B=3125) byte u_NTC_Rnom = 2;// U8-9 NTC resistance at nominal T in kOhm: [1,2,3,5,10,20] const byte u_NTC_Rseries = 10;// assume 10kOhm series resistance. Hardware has 9k1 resistor + 2k trimpot for tuning Tnom/Rnom byte u_NTC_Tnom = 20;// should be 20 or 25 unsigned int u_NTC_B = 3125;// adjustable 3000-4000 K in 5 K steps // EEPROM addresses for non volatile parameters const unsigned int addr_h_NTC_T_Lo = 0;// float: 4B const unsigned int addr_h_NTC_T_Hi = 4;// float: 4B const unsigned int addr_h_NTC_N_enable = 8;// byte const unsigned int addr_h_NTC_nSamples = 12;//byte const unsigned int addr_h_NTC_Rnom = 16;// byte const unsigned int addr_h_NTC_Tnom = 20;// byte const unsigned int addr_h_NTC_B = 24;// u_int: 2B const unsigned int addr_u_NTC_T_Lo = 40;// float: 4B const unsigned int addr_u_NTC_T_Hi = 44;// float: 4B const unsigned int addr_u_NTC_N_enable = 48;// byte const unsigned int addr_u_NTC_nSamples = 52;//byte const unsigned int addr_u_NTC_Rnom = 56;// byte const unsigned int addr_u_NTC_Tnom = 60;// byte const unsigned int addr_u_NTC_B = 64;// u_int: 2B const unsigned int addr_Sht_T_Lo = 80;// float: 4B const unsigned int addr_Sht_T_Hi = 84;// float: 4B const unsigned int addr_Sht_RH_Lo = 88;// float: 4B const unsigned int addr_Sht_RH_Hi = 92;// float: 4B const unsigned int addr_Sht_Enable = 96;// byte // number of samples to use in averaging filter on NTC groups byte HnSamples = 2;// 2 should be a good fallback number byte UnSamples = 2; // enable masks for sensors byte h_NTC_N_enable = 1; byte u_NTC_N_enable = 0; byte sht_enable = 0; char dispTemp[5]; // menu pot limits and values const int menuPotLeftmost = 70; const int potClickLo = 470; const int potClickHi = 560; const int menuPotRightmost = 950; const char degC[] = { (char)223, 'C'}; const char kOhm[] = { 'k', (char)244 }; // readout interval for SHT7x. //Device should not be active more than 10% to limit self-heating to 0.1degC // with clock frequency of 80 kHz, readout sequence takes 302ms. const unsigned int userShtInterval = 3500UL;//3.5s const unsigned int readShtTimeOut = 1000UL;// 1s. Nominal readout time 300 ms // pushbutton flash interval const unsigned int flashInterval = 500UL;// 0.5s // menu timeout const unsigned int maxMenuInterval = 120000UL;// 2 minutes // menu state machine variables byte menuButtonRead = 0; byte prevMenuButtonRead = 0; byte menuState = DefaultMenu; byte nextMenuState = DefaultMenu; byte menuChoice = 0; byte menuDevice = 0; byte eepromWritten = 0; int setTemp = 0; byte enableLedState = LOW; byte outputState = LOW; byte prevOutputState = LOW; byte userEnable = LOW; byte serialEnable = LOW; byte serialDisable = LOW; byte mustPrintSensorValues = LOW; // timing control of refresh rates unsigned long flashTimerLast, userShtTime, menuWatchDog; byte commaReceived = LOW; //+-------------------------------------------------------+ // instantiations // SPI LCD interface through 74LS595 shift register, see: // http://learn.adafruit.com/i2c-spi-lcd-backpack // DATA (p14 on 74LS595), CLK (p11 on 74LS595), LATCH (p12 on 74LS595) LiquidCrystal lcd(6,5,4); // instantiate NTCs // NTC on A0 serving H0-7 on external 4051 analog 8x multiplexer NTCtemp h_NTC_Mux; byte h_T_notOK = 0x00; // NTC serving U8-908, U8-909 on A1, A2 respectively NTCtemp u_NTC_8; NTCtemp u_NTC_9; byte u_T_notOK = 0x00; // Sensirion SHT7x on I2C port SHTxx shtRHT(i2cData, i2cClk); byte sht_RHT_notOK = 0x00; // temperature variables float h_NTC_T[8];// keeping this fixed length is lots faster float u_NTC_8_T = 20.0; float u_NTC_9_T = 20.0; float sht_T = 20.0; float sht_RH = 50.0; //+-------------------------------------------------------+ void setup(){ // set up Serial communication (through USB) Serial.begin(115200); Serial.flush();// clear receive buffer memset(cmdbuf, '\0', 4);// clear command string memset(intbuf, '\0', 5);// clear integer string // use ADC analog reference from external precision supply analogReference(EXTERNAL); // set mode for all remaining pins pinMode(muxCtrl0, OUTPUT); pinMode(muxCtrl1, OUTPUT); pinMode(muxCtrl2, OUTPUT); pinMode(menuButton, INPUT); pinMode(duoLed, OUTPUT); pinMode(outputEnable, OUTPUT); pinMode(selectRseries, OUTPUT); pinMode(d0_output, OUTPUT); pinMode(d1_output, OUTPUT); pinMode(enablePbLED, OUTPUT); pinMode(pbEnable, INPUT); // write default outputs to pins digitalWrite(muxCtrl0, LOW); digitalWrite(muxCtrl1, LOW); digitalWrite(muxCtrl2, LOW); digitalWrite(selectRseries, HIGH); // set variables menuState = DefaultMenu; nextMenuState = DefaultMenu; menuDevice = 0; eepromWritten = 0; enableLedState = LOW; outputState = LOW; prevOutputState = LOW; serialEnable = LOW; serialDisable = LOW; mustPrintSensorValues = LOW; commaReceived = LOW; // initialise timers flashTimerLast = millis(); userShtTime = millis(); menuWatchDog = millis(); // retrieve variables from EEPROM // H0-7 NTCs EEPROM_readAnything(addr_h_NTC_T_Lo, h_NTC_T_Lo); EEPROM_readAnything(addr_h_NTC_T_Hi, h_NTC_T_Hi); EEPROM_readAnything(addr_h_NTC_N_enable, h_NTC_N_enable); EEPROM_readAnything(addr_h_NTC_nSamples, HnSamples); EEPROM_readAnything(addr_h_NTC_Rnom, h_NTC_Rnom); EEPROM_readAnything(addr_h_NTC_Tnom, h_NTC_Tnom); EEPROM_readAnything(addr_h_NTC_B, h_NTC_B); // U8-9 NTCs EEPROM_readAnything(addr_u_NTC_T_Lo, u_NTC_T_Lo); EEPROM_readAnything(addr_u_NTC_T_Hi, u_NTC_T_Hi); EEPROM_readAnything(addr_u_NTC_N_enable, u_NTC_N_enable); EEPROM_readAnything(addr_u_NTC_nSamples, UnSamples); EEPROM_readAnything(addr_u_NTC_Rnom, u_NTC_Rnom); EEPROM_readAnything(addr_u_NTC_Tnom, u_NTC_Tnom); EEPROM_readAnything(addr_u_NTC_B, u_NTC_B); // SHT 71 RH/T EEPROM_readAnything(addr_Sht_T_Lo, SHT_T_Lo); EEPROM_readAnything(addr_Sht_T_Hi, SHT_T_Hi); EEPROM_readAnything(addr_Sht_RH_Lo, SHT_RH_Lo); EEPROM_readAnything(addr_Sht_RH_Hi, SHT_RH_Hi); EEPROM_readAnything(addr_Sht_Enable, sht_enable); // initialise NTC instances h_NTC_Mux.setNTCup(hNTCMuxPin, HnSamples, h_NTC_Rnom);// Rnom is either 1 or 10 kOhm h_NTC_Mux.setNTCParameters(h_NTC_Rnom, h_NTC_Tnom, h_NTC_B); u_NTC_8.setNTCup(uNTC08Pin, UnSamples, u_NTC_Rseries); u_NTC_8.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); u_NTC_9.setNTCup(uNTC09Pin, UnSamples, u_NTC_Rseries); u_NTC_9.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); // setup lcd + print welcome message lcd.begin(40,2); lcd.setCursor(9,0); lcd.setBacklight(HIGH); lcd.print(F("Temperature Interlock"));// 21 chars lcd.setCursor(6,1); lcd.print(F("firmware: "));// 10 chars lcd.setCursor(16,1); lcd.print(fwVersion);// 4 chars lcd.setCursor(20,1); lcd.print(' ');// 1 char lcd.setCursor(21,1); lcd.print(fwDate);// 10 chars delay(500); lcd.setBacklight(LOW); delay(500); lcd.setBacklight(HIGH); lcd.clear(); // print welcome msg to serial Serial.println("Temperature Interlock Unit Ready"); } void loop(){ prevOutputState = outputState; // readout loop for H0-7 NTCs // set series R according to H0-7 type. // For 1 kOhm, drive selectRseries line low during mux'ed measurement only to avoid self-heating when idle if(h_NTC_Rnom == 1) digitalWrite(selectRseries, LOW); for(byte count=0; count < 8; count++){ if(count < h_NTC_N_enable){ digitalWrite(muxCtrl0, (bitRead(count,0) ) );// set external mux control lines digitalWrite(muxCtrl1, (bitRead(count,1) ) ); digitalWrite(muxCtrl2, (bitRead(count,2) ) ); h_NTC_T[count] = h_NTC_Mux.getDegC(); // read out temperature if(h_NTC_T[count] > h_NTC_T_Hi || h_NTC_T[count] < h_NTC_T_Lo){ // check T in range bitWrite(h_T_notOK, count, HIGH); //h_T_notOK = HIGH; } else{ bitWrite(h_T_notOK, count, LOW); //h_T_notOK = LOW; } } else{ bitWrite(h_T_notOK, count, LOW); //h_T_notOK = LOW; } } digitalWrite(selectRseries, HIGH); // read out U8-9 NTCs if enabled // check temperature readings against limits and set bits in u_T_notOK accordingly if(u_NTC_N_enable > 0){ u_NTC_8_T = u_NTC_8.getDegC(); if(u_NTC_8_T > u_NTC_T_Hi || u_NTC_8_T < u_NTC_T_Lo) u_T_notOK = HIGH; //else u_T_notOK = LOW; else bitWrite(u_T_notOK, 0, LOW); if(u_NTC_N_enable > 1){ u_NTC_9_T = u_NTC_9.getDegC(); if(u_NTC_9_T > u_NTC_T_Hi || u_NTC_9_T < u_NTC_T_Lo) u_T_notOK = HIGH; //else u_T_notOK = LOW; else bitWrite(u_T_notOK, 1, LOW); } } else u_T_notOK = LOW; // read out SHT7x on I2C port if enabled. //Keep track of timing interval if(sht_enable == 1){// cheap byte comparison first if( (millis() - userShtTime) > userShtInterval ){ userShtTime = millis(); sht_T = shtRHT.getTemp(); sht_RH = shtRHT.getHum(); if(millis() - userShtTime > readShtTimeOut) sht_enable = 0;// if readout takes too long, SHT is probably not connected and should be disabled if(sht_T > SHT_T_Hi || sht_T < SHT_T_Lo) sht_RHT_notOK = 1; else if(sht_RH > SHT_RH_Hi || sht_RH < SHT_RH_Lo) sht_RHT_notOK = 1; else sht_RHT_notOK = 0; } } else sht_RHT_notOK = 0; // read enable pushbutton pin, see if Temp. is OK and set outputState accordingly userEnable = digitalRead(pbEnable); // check if temperatures are OK, and if there is at least one sensor enabled if( h_T_notOK == 0 && u_T_notOK == 0 && sht_RHT_notOK == 0 && ((h_NTC_N_enable+u_NTC_N_enable+sht_enable) > 0) ){// T in range digitalWrite(duoLed, HIGH);// T indicator LEDs go green if(userEnable == HIGH || serialEnable == HIGH){// Temperature OK, enable PB pushed or serial cmd received if(outputState == LOW) mustPrintSensorValues = HIGH; outputState = HIGH; serialEnable = LOW;// reset serial enable command flag } if(outputState == HIGH){// Temperatures OK, output enabled. enable PB led should be solid on. Check serial cmd for output disable enableLedState = HIGH; if(serialDisable == HIGH){// disable cmd received over serial: set output low, reset disable receive flag outputState = LOW; serialDisable = LOW; } } else if(millis()- flashTimerLast > flashInterval){// flash LED in enable button flashTimerLast = millis(); if(enableLedState == LOW) enableLedState = HIGH; else enableLedState = LOW; } } else{// temperature not good, or no sensors enabled digitalWrite(duoLed, LOW); if(outputState == HIGH) mustPrintSensorValues = HIGH; outputState = LOW; enableLedState = LOW; serialEnable = LOW;// set serial Enable request flag low if T is not in range } digitalWrite(outputEnable, outputState); if(prevOutputState == LOW && outputState == HIGH) delay(100);// avoid display trouble digitalWrite(enablePbLED, enableLedState); if(mustPrintSensorValues){ printSensorValues(); mustPrintSensorValues = LOW; } //commaReceived = LOW; // see if anything arrived over serial communication and put it in appropriate strings until CR is received while(Serial.available() && inSerial != ENTER){ inSerial = Serial.read(); if(inSerial == ','){ #ifdef DEBUG Serial.println("Comma received"); #endif commaReceived = HIGH; } if(nBytes < 3 && commaReceived == LOW) cmdbuf[nBytes] = (char)inSerial; else if(nBytes > 3 && nBytes < 8 && commaReceived == HIGH) intbuf[nBytes-4] = (char)inSerial; nBytes++; } if(inSerial == ENTER){// concluding CR received: start to interpret received cmd Serial.println();// clear local echo line Serial.flush();// flush remaining bytes in buffer to be ready for next receive int convint = atoi(intbuf);// convert received ASCII to int Serial.print(F("Received: ")); Serial.print(cmdbuf); Serial.print(", "); Serial.println(convint); // see if received first 3B string is a request for // data, output enable, output disable, settings request, or write settings to EEPROM, successively if(strcmp(cmdbuf, dataRequestString) == 0 && convint == 100) printSensorValues(); else if(strcmp(cmdbuf, enableRequestString) == 0 && convint == 100) serialEnable = HIGH; else if(strcmp(cmdbuf, disableRequestString) == 0 && convint == 100) serialDisable = HIGH; else if(strcmp(cmdbuf, settingsRequestString) == 0 && convint == 100){ Serial.print("htl,"); Serial.println(int(h_NTC_T_Lo)); Serial.print("hth,"); Serial.println(int(h_NTC_T_Hi)); Serial.print("hne,"); Serial.println(h_NTC_N_enable, DEC); Serial.print("hna,"); Serial.println(HnSamples, DEC); Serial.print("hrn,"); Serial.println(h_NTC_Rnom, DEC); Serial.print("htn,"); Serial.println(h_NTC_Tnom, DEC); Serial.print("hbn,"); Serial.println(h_NTC_B); Serial.print("utl,"); Serial.println(int(u_NTC_T_Lo)); Serial.print("uth,"); Serial.println(int(u_NTC_T_Hi)); Serial.print("une,"); Serial.println(u_NTC_N_enable, DEC); Serial.print("una,"); Serial.println(UnSamples, DEC); Serial.print("urn,"); Serial.println(u_NTC_Rnom, DEC); Serial.print("utn,"); Serial.println(u_NTC_Tnom, DEC); Serial.print("ubn,"); Serial.println(u_NTC_B); Serial.print("rtl,"); Serial.println(int(SHT_T_Lo)); Serial.print("rth,"); Serial.println(int(SHT_T_Hi)); Serial.print("rrl,"); Serial.println(int(SHT_RH_Lo)); Serial.print("rrh,"); Serial.println(int(SHT_RH_Hi)); Serial.print("rne,"); Serial.println(sht_enable, DEC); } else if(strcmp(cmdbuf, write2EepromString) == 0 && convint == 100){ // write all variables to EEPROM // H0-7 NTCs EEPROM_writeAnything(addr_h_NTC_T_Lo, h_NTC_T_Lo); EEPROM_writeAnything(addr_h_NTC_T_Hi, h_NTC_T_Hi); EEPROM_writeAnything(addr_h_NTC_N_enable, h_NTC_N_enable); EEPROM_writeAnything(addr_h_NTC_nSamples, HnSamples); EEPROM_writeAnything(addr_h_NTC_Rnom, h_NTC_Rnom); EEPROM_writeAnything(addr_h_NTC_Tnom, h_NTC_Tnom); EEPROM_writeAnything(addr_h_NTC_B, h_NTC_B); // U8-9 NTCs EEPROM_writeAnything(addr_u_NTC_T_Lo, u_NTC_T_Lo); EEPROM_writeAnything(addr_u_NTC_T_Hi, u_NTC_T_Hi); EEPROM_writeAnything(addr_u_NTC_N_enable, u_NTC_N_enable); EEPROM_writeAnything(addr_u_NTC_nSamples, UnSamples); EEPROM_writeAnything(addr_u_NTC_Rnom, u_NTC_Rnom); EEPROM_writeAnything(addr_u_NTC_Tnom, u_NTC_Tnom); EEPROM_writeAnything(addr_u_NTC_B, u_NTC_B); // SHT 71 RH/T EEPROM_writeAnything(addr_Sht_T_Lo, SHT_T_Lo); EEPROM_writeAnything(addr_Sht_T_Hi, SHT_T_Hi); EEPROM_writeAnything(addr_Sht_RH_Lo, SHT_RH_Lo); EEPROM_writeAnything(addr_Sht_RH_Hi, SHT_RH_Hi); EEPROM_writeAnything(addr_Sht_Enable, sht_enable); Serial.println(F("Settings written to EEPROM")); } else{// decode command & perform action // now resolve the command. // First character encodes what it applies to: 'h' for H0-7, 'u' for U8-9, 'r' for SHT7x RH/T // Further 2 chars indicate which command it acutally is; see enum list at top char setcmd[3]; for(int i = 0; i<3;i++){ setcmd[i] = cmdbuf[i+1]; } switch( lookup(setcmd) ){// lookup command in LUT case Tlow: { switch(cmdbuf[0]){ case 'h':// set H0-7 NTC Tlow limit if(convint > -26 && convint < 76) h_NTC_T_Lo = (float) convint; break; case 'u':// U8-9 NTC Tlow limit if(convint > -26 && convint < 76) u_NTC_T_Lo = (float) convint; break; case 'r':// SHT7x RH/T T low limit if(convint > -41 && convint < 100) SHT_T_Lo = (float) convint; break; } break; } case Thigh: { switch(cmdbuf[0]){ case 'h':// set H0-7 Thigh limit if(convint > -26 && convint < 76) h_NTC_T_Hi = (float) convint; break; case 'u': if(convint > -26 && convint < 76) u_NTC_T_Hi = (float) convint; break; case 'r': if(convint > -41 && convint < 100) SHT_T_Hi = (float) convint; break; } break; } case Nenable: { byte convbyte = (byte) convint;// convbyte is always positive switch(cmdbuf[0]){ case 'h':// set H0-7 N enable if(convbyte < 9) h_NTC_N_enable = convbyte; else h_NTC_N_enable = 8; break; case 'u':// set U8-9 N enable if(convbyte > 2) u_NTC_N_enable = 2; else u_NTC_N_enable = convbyte; break; case 'r':// set SHT7x RH/T enable if(convbyte) sht_enable = 1; else sht_enable = 0; break; } break; } case nSamples: { byte convbyte = byte(convint);// convbyte is always positive if(convbyte > 8) convbyte = 8; if(convbyte == 0) convbyte = 1; switch(cmdbuf[0]){ case 'h': HnSamples = convbyte; h_NTC_Mux.setNTCup(hNTCMuxPin, HnSamples, h_NTC_Rnom); break; case 'u': UnSamples = convbyte; u_NTC_8.setNTCup(uNTC08Pin, UnSamples, u_NTC_Rseries); u_NTC_9.setNTCup(uNTC09Pin, UnSamples, u_NTC_Rseries); break; } break; } case Rnom: { byte convbyte = (byte) convint;// convbyte is always positive switch(cmdbuf[0]){ case 'h': if(convbyte == 1 || convbyte == 10){ h_NTC_Rnom = convbyte; h_NTC_Mux.setNTCParameters(h_NTC_Rnom, h_NTC_Tnom, h_NTC_B); } break; case 'u': if(convbyte == 1 || convbyte == 2 || convbyte == 3 || convbyte == 5 || convbyte == 10 || convbyte == 20){ u_NTC_Rnom = convbyte; u_NTC_8.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); u_NTC_9.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); } break; } break; } case Tnom: { if(convint == 20 || convint == 25){ switch(cmdbuf[0]){ case 'h': h_NTC_Tnom = (byte) convint; h_NTC_Mux.setNTCParameters(h_NTC_Rnom, h_NTC_Tnom, h_NTC_B); break; case 'u': u_NTC_Tnom = (byte) convint; u_NTC_8.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); u_NTC_9.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); break; } } break; } case Bntc: { if(convint > 2999 && convint < 4001){ unsigned int convuint = (unsigned int) convint; switch(cmdbuf[0]){ case 'h': h_NTC_B = convuint; h_NTC_Mux.setNTCParameters(h_NTC_Rnom, h_NTC_Tnom, h_NTC_B); break; case 'u': u_NTC_B = convuint; u_NTC_8.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); u_NTC_9.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); break; } } break; } case RHlow: { if(convint > 0 && convint < 100 && cmdbuf[0] == 'r') SHT_RH_Lo = (float) convint; break; } case RHhigh: { if(convint > 0 && convint < 100 && cmdbuf[0] == 'r') SHT_RH_Hi = (float) convint; break; } default: Serial.println(F("Command not recognised, or value out of range")); break; }// command interpreter case statement }// interpret and execute command // command digestion completed. Reset variables to get ready for next serial cmd inSerial = 0; memset(cmdbuf, '\0', 4); memset(intbuf, '\0', 5); nBytes = 0; commaReceived = LOW; }// concluding ENTER received over serial // read menu potmeter, and menu pushbutton int menuPotVal = analogRead(menuPot);// for use in menu menuButtonRead = digitalRead(menuButton); // read menu button if(prevMenuButtonRead == LOW && menuButtonRead == HIGH){// detect leading edge delay(50);//require button to be pressed for a bit of time / debounce menuButtonRead = digitalRead(menuButton); if( menuButtonRead == HIGH ){// if menubutton still high after leading edge, advance menu state to next menuState = nextMenuState; menuWatchDog = millis();// reset menu timeout timer } } prevMenuButtonRead = menuButtonRead; // menu watchdog: check interval between menu button push actions has not exceeded timeout if(menuState){// skip watchdog if not in menu (cheap byte check) if(millis()-menuWatchDog > maxMenuInterval){// see if timeout occurred (expensive unsigned long operations) menuState = 0; nextMenuState = DefaultMenu; } } // +=+=+=+=+=+=+=+=+ DISPLAY & MENU STATE MACHINE +=+=+=+=+=+=+=+=+ // menu uses top line of display. Avoid clearing LCD as it causes flicker lcd.home(); // print Temperature values to lcd on bottom line // default is to print H0-7 temperatures. // If no H0-7 NTCs enabled: print U8-9 and RH/T if enabled. Otherwise print blanks. if(h_NTC_N_enable){ lcd.setCursor(0,1); for(byte count = 0; count < 8; count++){ if(count < h_NTC_N_enable){ dtostrf(h_NTC_T[count], 5, 1, dispTemp); lcd.print(dispTemp); } else lcd.print(F(" ")); } } else{// print others lcd.setCursor(0,1); if(u_NTC_N_enable > 0){ lcd.print("U8:");// 3 chars lcd.setCursor(3,1); dtostrf(u_NTC_8_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(8,1); lcd.print(degC);// 2 chars lcd.setCursor(10,1); if(u_NTC_N_enable > 1){ lcd.print(" U9:");// 4 chars lcd.setCursor(14,1); dtostrf(u_NTC_9_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(19,1); lcd.print(degC);// 2 chars } else lcd.print(F(" "));// 11 chars } else lcd.print(F(" "));// 21 chars lcd.setCursor(21,1); if(sht_enable){ lcd.print(F(" RH/T:"));// 6 chars lcd.setCursor(27,1); dtostrf(sht_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(32,1); lcd.print(degC);// 2 chars lcd.setCursor(34,1); lcd.print(", "); lcd.setCursor(36,1); dtostrf(sht_RH, 2,0, dispTemp); lcd.print(dispTemp);// 2 chars lcd.setCursor(38,1); lcd.print(" %"); } else lcd.print(F(" "));// 19 chars } switch(menuState){ case DefaultMenu:// menu ground state. Display top line depends on pot position: // 0: H0-7 NTC parameters // 1: H0-7 & U8-9 T limits // 2: H0-7 text // 3: U8-9 & RH/T status // 4: SHT T, RH limits // 5: U8-9 NTC parameters setTemp = map(menuPotVal, 0, 1020, 0, 5); lcd.home(); switch(setTemp){ case 0: lcd.print(F("H0-7 nS, Rn, Tn, B: "));//20 chars lcd.setCursor(20,0); lcd.print(HnSamples, DEC); lcd.setCursor(21,0); lcd.print(", "); lcd.setCursor(23,0); if(h_NTC_Rnom < 10){ lcd.print(' '); lcd.setCursor(24,0); } lcd.print(h_NTC_Rnom, DEC); lcd.setCursor(25,0); lcd.print(kOhm);// 2 chars lcd.setCursor(27,0); lcd.print(", "); lcd.setCursor(29,0); lcd.print(h_NTC_Tnom, DEC); lcd.setCursor(31,0); lcd.print(degC); lcd.setCursor(33,0); lcd.print(", ");//2 lcd.setCursor(35,0); lcd.print(h_NTC_B); lcd.setCursor(39,0); lcd.print('K'); break; case 1: lcd.print(F("T limits H0-7: "));// 15 chars lcd.setCursor(15,0); dtostrf(h_NTC_T_Lo, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(18,0); lcd.print(','); lcd.setCursor(19,0); dtostrf(h_NTC_T_Hi, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(22,0); lcd.print(degC); lcd.setCursor(24,0); lcd.print(F(" U8-9: "));// 6 chars lcd.setCursor(31,0); dtostrf(u_NTC_T_Lo, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(34,0); lcd.print(','); lcd.setCursor(35,0); dtostrf(u_NTC_T_Hi, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(degC); break; case 2: if(h_NTC_N_enable) lcd.print(F("|H0 |H1 |H2 |H3 |H4 |H5 |H6 |H7 ")); else lcd.print(F("H0-7 NTCs disabled ")); break; case 3: if(u_NTC_N_enable == 0){ lcd.print(F("U8-9 NTC disabled "));// 21 chars } else{ lcd.setCursor(0,0); if(u_NTC_N_enable > 0){ lcd.print("U8:");// 3 chars lcd.setCursor(3,0); dtostrf(u_NTC_8_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(8,0); lcd.print(degC);// 2 chars lcd.setCursor(10,0); if(u_NTC_N_enable > 1){ lcd.print(" U9:");// 4 chars lcd.setCursor(14,0); dtostrf(u_NTC_9_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(19,0); lcd.print(degC);// 2 chars } else lcd.print(F(" "));// 11 chars } else lcd.print(F(" "));// 21 chars } lcd.setCursor(21,0); if(sht_enable){ lcd.print(F(" RH/T:"));// 6 chars lcd.setCursor(27,0); dtostrf(sht_T, 5,1, dispTemp); lcd.print(dispTemp);// 5 chars lcd.setCursor(32,0); lcd.print(degC);// 2 chars lcd.setCursor(34,0); lcd.print(", "); lcd.setCursor(36,0); dtostrf(sht_RH, 2,0, dispTemp); lcd.print(dispTemp);// 2 chars lcd.setCursor(38,0); lcd.print(" %"); } else lcd.print(F(" SHT RH/T disabled "));// 19 chars break; case 4: lcd.print(F("T, RH limits SHT7x: "));// 21 chars lcd.setCursor(21,0); dtostrf(SHT_T_Lo, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(24,0); lcd.print(","); lcd.setCursor(25,0); dtostrf(SHT_T_Hi, 3,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(28,0); lcd.print(degC); lcd.setCursor(30,0); lcd.print(" | "); lcd.setCursor(33,0); dtostrf(SHT_RH_Lo, 2,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(35,0); lcd.print(","); lcd.setCursor(36,0); dtostrf(SHT_RH_Hi, 2,0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(" %"); break; case 5: lcd.print(F("U8-9 nS, Rn, Tn, B: "));//20 chars lcd.setCursor(20,0); lcd.print(UnSamples, DEC); lcd.setCursor(21,0); lcd.print(", "); lcd.setCursor(23,0); if(u_NTC_Rnom < 10){ lcd.print(' '); lcd.setCursor(24,0); } lcd.print(u_NTC_Rnom, DEC); lcd.setCursor(25,0); lcd.print(kOhm);// 2 chars lcd.setCursor(27,0); lcd.print(", "); lcd.setCursor(29,0); lcd.print(u_NTC_Tnom, DEC); lcd.setCursor(31,0); lcd.print(degC); lcd.setCursor(33,0); lcd.print(", ");//2 lcd.setCursor(35,0); lcd.print(u_NTC_B); lcd.setCursor(39,0); lcd.print('K'); break; } nextMenuState = DeviceMenu; break; case DeviceMenu: if(menuPotVal <= menuPotLeftmost){ //lcd.print(F(" ")); lcd.print(F("H0-7 NTC u8-9_ntc sht7x rh/t exit")); menuDevice = 1; nextMenuState = NTCMenu; } else if(menuPotVal > menuPotLeftmost && menuPotVal < 512){ lcd.print(F("h0-7 ntc U8-9 NTC sht7x rh/t exit")); menuDevice = 2; nextMenuState = NTCMenu; } else if(menuPotVal > 512 && menuPotVal < menuPotRightmost){ lcd.print(F("h0-7 ntc u8-9 ntc SHT7x RH/T exit")); menuDevice = 3; nextMenuState = SHTMenu; } else{ lcd.print(F("h0-7 ntc u8-9 ntc sht71 rh/t EXIT")); menuDevice = 0; nextMenuState = DefaultMenu; } break; case NTCMenu: if(menuDevice == 1) lcd.print(F("H0-7 NTCs:"));//10 chars else if(menuDevice == 2) lcd.print(F("U8-9 NTCs:"));//10 chars lcd.setCursor(10,0); if(menuPotVal < potClickLo){ lcd.print(F("T LIMITS N enable set values"));//30 chars nextMenuState = TLimitsMenu; } else if(menuPotVal > potClickHi){ lcd.print(F("t limits N enable SET VALUES")); nextMenuState = NTCValuesMenu; } else{ lcd.print(F("t limits N ENABLE set values")); if(menuDevice == 1) nextMenuState = SetHNEnable; else if(menuDevice == 2) nextMenuState = SetUNEnable; } break; case SHTMenu: eepromWritten = 0; lcd.print(F("SHT7x RH/T: "));//12 chars lcd.setCursor(12,0); if(menuPotVal < potClickLo){ if(sht_enable){ lcd.print(F("DISABLE"));// 7 chars menuChoice = 1; } else{ lcd.print(F("ENABLE ")); menuChoice = 2; } lcd.setCursor(19,0); lcd.print(F(" t limits rh limits"));// 21 chars nextMenuState = SetSHTEnable; } else{ if(sht_enable) lcd.print(F("disable")); else lcd.print(F("enable ")); lcd.setCursor(19,0); if(menuPotVal > potClickHi){ lcd.print(F(" t limits RH LIMITS")); nextMenuState = SHTRHLimitsMenu; } else{ lcd.print(F(" T LIMITS rh limits")); nextMenuState = TLimitsMenu; } menuChoice = 0; } break; case TLimitsMenu: switch(menuDevice){ case 1: lcd.print(F("H0-7 NTC T limits: "));//20 chars break; case 2: lcd.print(F("U8-9 NTCs T limits: ")); break; case 3: lcd.print(F("SHT7x RH/T T limits:")); break; case 0: lcd.print(F("+-+-+ ERROR +-+-+")); nextMenuState = DefaultMenu; break; } lcd.setCursor(20,0); if(menuPotVal < potClickLo){ lcd.print(F("LOW exit high"));// 20 chars nextMenuState = SetTemperatureLimit; menuChoice = 1; } else if(menuPotVal > potClickHi){ lcd.print(F("low exit HIGH")); nextMenuState = SetTemperatureLimit; menuChoice = 2; } else{ lcd.print(F("low EXIT high")); nextMenuState = DefaultMenu; menuChoice = 0; } break; case SetTemperatureLimit: eepromWritten = 0; lcd.print(F("Dial & push to set Temperature: "));//35 chars switch(menuDevice){ case 1: case 2: setTemp = map(menuPotVal, 0, 1020, -25, 75);// range for NTCs break; case 3: setTemp = map(menuPotVal, 0, 1020, -40, 99);// range for SHT7x break; } lcd.setCursor(35,0); dtostrf(setTemp, 3, 0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(degC); nextMenuState = StoreTemperatureLimit; break; case StoreTemperatureLimit: float compTemp; unsigned int addrTemp; if(menuChoice == 1){// low T limit switch(menuDevice){ case 1:// H0-7 NTC compTemp = h_NTC_T_Hi; addrTemp = addr_h_NTC_T_Lo; break; case 2:// U8-9 NTC compTemp = u_NTC_T_Hi; addrTemp = addr_u_NTC_T_Lo; break; case 3:// RH/T compTemp = SHT_T_Hi; addrTemp = addr_Sht_T_Lo; break; } if(float(setTemp) > compTemp){ lcd.print(F("Temperature not set: Low > High limit ")); } else{ //h_NTC_T_Lo = float(setTemp); if(eepromWritten == 0){ EEPROM_writeAnything(addrTemp, float(setTemp) ); } lcd.print(F("Low Temperature limit set to: ")); lcd.setCursor(35,0); dtostrf(setTemp, 3, 0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(degC); } } else if(menuChoice == 2){// high temperature limit switch(menuDevice){ case 1: compTemp = h_NTC_T_Lo; addrTemp = addr_h_NTC_T_Hi; break; case 2: compTemp = u_NTC_T_Lo; addrTemp = addr_u_NTC_T_Hi; break; case 3: compTemp = SHT_T_Lo; addrTemp = addr_Sht_T_Hi; break; } if(float(setTemp) < compTemp){ lcd.print(F("Temperature not set: High < Low limit ")); } else{ //h_NTC_T_Hi = float(setTemp); if(eepromWritten == 0){ EEPROM_writeAnything(addrTemp, float(setTemp)); } lcd.print(F("High Temperature limit set to: ")); lcd.setCursor(35,0); dtostrf(setTemp, 3, 0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(degC); } } else{ lcd.print(F("Error: temperature limit not set ")); } if(eepromWritten == 0){ switch(menuDevice){ case 1: EEPROM_readAnything(addr_h_NTC_T_Lo, h_NTC_T_Lo); EEPROM_readAnything(addr_h_NTC_T_Hi, h_NTC_T_Hi); break; case 2: EEPROM_readAnything(addr_u_NTC_T_Lo, u_NTC_T_Lo); EEPROM_readAnything(addr_u_NTC_T_Hi, u_NTC_T_Hi); break; case 3: EEPROM_readAnything(addr_Sht_T_Lo, SHT_T_Lo); EEPROM_readAnything(addr_Sht_T_Hi, SHT_T_Hi); break; } eepromWritten = 1; } nextMenuState = TLimitsMenu; break; case SetHNEnable: eepromWritten = 0; lcd.print(F("H0-7 NTC enable (0..8, exit): "));// 32 chars menuChoice = map(menuPotVal, 0, 1020, 0, 9); lcd.setCursor(32,0); if(menuChoice == 9){ lcd.print(F(" EXIT")); nextMenuState = DefaultMenu; } else{ for(byte count = 0; count < 9; count++){ lcd.setCursor((32+count),0); if(count < menuChoice) lcd.print('O'); else lcd.print('X'); } nextMenuState = StoreHNEnable; } break; case StoreHNEnable: h_NTC_N_enable = menuChoice; if(eepromWritten == 0){ EEPROM_writeAnything(addr_h_NTC_N_enable, menuChoice); eepromWritten = 1; } lcd.print(F("H0-7 NTC enable mask set to: "));// 32 chars for(byte count = 0; count < 8; count++){ lcd.setCursor((32+count),0); if(count < menuChoice) lcd.print('O'); else lcd.print('X'); } nextMenuState = SetHNEnable; break; case SetUNEnable: eepromWritten = 0; lcd.print(F("U8-9 NTC enable (0..2, exit): "));// 30 chars lcd.setCursor(30,0); if(menuPotVal < menuPotLeftmost){ lcd.print(F(" XX")); menuChoice = 0; nextMenuState = StoreUNEnable; } else if(menuPotVal > menuPotLeftmost && menuPotVal < potClickHi){ lcd.print(F(" OX")); menuChoice = 1; nextMenuState = StoreUNEnable; } else if(menuPotVal > potClickHi && menuPotVal < menuPotRightmost){ lcd.print(F(" OO")); menuChoice = 2; nextMenuState = StoreUNEnable; } else{ lcd.print(F(" EXIT")); nextMenuState = DefaultMenu; } break; case StoreUNEnable: u_NTC_N_enable = menuChoice; if(eepromWritten == 0){ EEPROM_writeAnything(addr_u_NTC_N_enable, menuChoice); eepromWritten = 1; } lcd.print(F("U8-9 NTC enable mask set to: "));// 38 chars for(byte count = 0; count < 2; count++){ lcd.setCursor((38+count),0); if(count < menuChoice) lcd.print('O'); else lcd.print('X'); } nextMenuState = SetUNEnable; break; case SetSHTEnable: if(menuChoice == 2){// previous disabled state should become enabled lcd.print(F("SHT7x RH/T sensor is now ENABLED ")); sht_enable = 1; } else{ lcd.print(F("SHT7x RH/T sensor is now DISABLED ")); sht_enable = 0; } if(eepromWritten == 0){ EEPROM_writeAnything(addr_Sht_Enable, sht_enable); eepromWritten = 1; } nextMenuState = DeviceMenu; break; case SHTRHLimitsMenu: lcd.print(F("SHT7x RH/T RH limits: "));// 22 chars lcd.setCursor(22,0); if(menuPotVal < potClickLo){ lcd.print(F("LOW exit high"));// 18 chars nextMenuState = SetSHTRHLimit; menuChoice = 1; } else if(menuPotVal > potClickHi){ lcd.print(F("low exit HIGH")); nextMenuState = SetSHTRHLimit; menuChoice = 2; } else{ lcd.print(F("low EXIT high")); nextMenuState = DefaultMenu; menuChoice = 0; } break; case SetSHTRHLimit: eepromWritten = 0; lcd.print(F("Dial & push to set Rel. Humidity: "));//36 chars setTemp = map(menuPotVal, 0, 1020, 5, 95); lcd.setCursor(36,0); dtostrf(setTemp, 2, 0, dispTemp); lcd.print(dispTemp); lcd.setCursor(38,0); lcd.print(" %"); nextMenuState = StoreSHTRHLimit; break; case StoreSHTRHLimit: if(menuChoice == 1){// low RH limit if(float(setTemp) > SHT_RH_Hi){ lcd.print(F("Rel. Humidity not set: Low > High limit ")); } else{ SHT_RH_Lo = float(setTemp); if(eepromWritten == 0){ EEPROM_writeAnything(addr_Sht_RH_Lo, SHT_RH_Lo); eepromWritten = 1; } lcd.print(F("Low Relative Humidity limit set to: "));// 36 chars } } else if(menuChoice == 2){// high RH limit if(float(setTemp) < SHT_RH_Lo){ lcd.print(F("Rel. Humidity not set: High < Low limit ")); } else{ SHT_RH_Hi = float(setTemp); if(eepromWritten == 0){ EEPROM_writeAnything(addr_Sht_RH_Hi, SHT_RH_Hi); eepromWritten = 1; } lcd.print(F("High Relative Humidity limit set to:"));// 36 chars } } lcd.setCursor(36,0); lcd.print(setTemp); lcd.setCursor(38,0); lcd.print(" %"); nextMenuState = SHTRHLimitsMenu; break; case NTCValuesMenu: if(menuDevice == 1) lcd.print(F("H0-7 NTCs:"));//10 chars else if(menuDevice == 2) lcd.print(F("U8-9 NTCs:"));//10 chars lcd.setCursor(10,0); if(menuPotVal < potClickLo){ lcd.print(F("NSAMPLES exit ntc parameters")); nextMenuState = SetNTCNSamples; } else if(menuPotVal > potClickHi){ lcd.print(F("nsamples exit NTC PARAMETERS")); nextMenuState = SetNTCRnom; } else{ lcd.print(F("nsamples EXIT ntc parameters")); menuDevice = 0; nextMenuState = DefaultMenu; } break; case SetNTCNSamples: { if(menuDevice == 1) lcd.print(F("H0-7 "));//5 chars else if(menuDevice == 2) lcd.print(F("U8-9 "));//5 chars lcd.setCursor(5,0); setTemp = map(menuPotVal, 0, 1020, 0, 3); menuChoice = 1; byte nStep = 0; while(nStep != byte(setTemp) ){ menuChoice *= 2; nStep++; } lcd.print(F("NTCs: nSamples for average filter "));//34 lcd.setCursor(39,0); lcd.print(menuChoice, DEC); eepromWritten = 0; nextMenuState = StoreNTCNSamples; } break; case StoreNTCNSamples: if(menuDevice == 1){ if(eepromWritten == 0){ HnSamples = menuChoice; EEPROM_writeAnything(addr_h_NTC_nSamples, HnSamples); h_NTC_Mux.setNTCup(hNTCMuxPin, HnSamples, h_NTC_Rnom); eepromWritten = 1; } lcd.print(F("H0-7"));// 4 chars } else if(menuDevice == 2){ if(eepromWritten == 0){ UnSamples = menuChoice; EEPROM_writeAnything(addr_u_NTC_nSamples, UnSamples); u_NTC_8.setNTCup(uNTC08Pin, UnSamples, u_NTC_Rseries); u_NTC_9.setNTCup(uNTC09Pin, UnSamples, u_NTC_Rseries); eepromWritten = 1; } lcd.print(F("U8-9")); } lcd.setCursor(4,0); lcd.print(F(" averaging filter nSamples set to "));// 35 chars lcd.setCursor(39,0); if(menuDevice == 1) lcd.print(HnSamples, DEC); else if(menuDevice == 2) lcd.print(UnSamples, DEC); nextMenuState = DefaultMenu; break; case SetNTCRnom: eepromWritten = 0; if(menuDevice == 1) lcd.print(F("H0-7"));// 4 chars if(menuDevice == 2) lcd.print(F("U8-9")); lcd.setCursor(4,0); lcd.print(F(": dial & push to set Rnom/EXIT "));// 32 chars setTemp = map(menuPotVal, 0, 1020, 0, 6); if(menuDevice == 2){// U8-9 NTC: selected values 1-20kOhm switch(setTemp){ case 0: menuChoice = 1; break; case 1: menuChoice = 2; break; case 2: menuChoice = 3; break; case 3: menuChoice = 5; break; case 4: menuChoice = 10; break; case 5: menuChoice = 20; break; case 6: menuChoice = 0; break; } } else{// H0-7 NTC, Rnom is either 10 or 1 kOhm if(setTemp == 6) menuChoice = 0; else{ if(setTemp < 3) menuChoice = 1; else if (setTemp < 6) menuChoice = 10; } } lcd.setCursor(36,0); if(menuChoice == 0){ lcd.print(F("EXIT")); nextMenuState = DefaultMenu; } else{ if(menuChoice < 10){ lcd.print(' '); lcd.setCursor(37,0); } lcd.print(menuChoice, DEC); lcd.setCursor(38,0); lcd.print(kOhm); nextMenuState = StoreNTCRnom; } break; case StoreNTCRnom: if(menuDevice == 1){ if(eepromWritten == 0){ h_NTC_Rnom = menuChoice; EEPROM_writeAnything(addr_h_NTC_Rnom, h_NTC_Rnom); eepromWritten = 1; } lcd.print(F("H0-7"));// 4 chars } else if(menuDevice == 2){ if(eepromWritten == 0){ if(menuChoice) u_NTC_Rnom = menuChoice; EEPROM_writeAnything(addr_u_NTC_Rnom, u_NTC_Rnom); eepromWritten = 1; } lcd.print(F("U8-9")); } lcd.setCursor(4,0); lcd.print(F(" NTC nominal R set to: "));//31 chars lcd.setCursor(35,0); if(menuChoice < 10){ lcd.print(" "); lcd.setCursor(37,0); } else{ lcd.print(' '); lcd.setCursor(36,0); } lcd.print(menuChoice, DEC); lcd.setCursor(38,0); lcd.print(kOhm); nextMenuState = SetNTCTnom; break; case SetNTCTnom: eepromWritten = 0; lcd.print(F("Dial & push to set NTC T(Rnom): "));// 36 chars lcd.setCursor(36,0); if(menuPotVal < potClickHi){ lcd.print(F("20")); menuChoice = 20; } else{ lcd.print(F("25"));// deg C"); menuChoice = 25; } lcd.setCursor(38,0); lcd.print(degC); nextMenuState = StoreNTCTnom; break; case StoreNTCTnom: lcd.print(F("NTC Temperature (Rnominal) set to: "));//36 chars lcd.setCursor(36,0); lcd.print(menuChoice, DEC); lcd.setCursor(38,0); lcd.print(degC); if(eepromWritten == 0){ if(menuDevice == 1){ EEPROM_writeAnything(addr_h_NTC_Tnom, menuChoice); h_NTC_Tnom = menuChoice; } else if(menuDevice == 2){ EEPROM_writeAnything(addr_u_NTC_Tnom, menuChoice); u_NTC_Tnom = menuChoice; } eepromWritten = 1; } nextMenuState = SetNTCB; break; case SetNTCB: eepromWritten = 0; lcd.print(F("Dial & push to set NTC B value: "));//34 chars setTemp = 5*(map(menuPotVal, 0, 1020, 600, 800));// u_NTC_B: 3000-4000 steps of 5 lcd.setCursor(34,0); lcd.print(setTemp); lcd.setCursor(38,0); lcd.print(" K"); if(menuDevice == 1) h_NTC_B = setTemp; else if (menuDevice == 2) u_NTC_B = setTemp; nextMenuState = StoreNTCB; break; case StoreNTCB: if(menuDevice == 1){ if(eepromWritten == 0){ EEPROM_writeAnything(addr_h_NTC_B, h_NTC_B); EEPROM_readAnything(addr_h_NTC_Rnom, h_NTC_Rnom); EEPROM_readAnything(addr_h_NTC_Tnom, h_NTC_Tnom); EEPROM_readAnything(addr_h_NTC_B, h_NTC_B); h_NTC_Mux.setNTCup(hNTCMuxPin, HnSamples, h_NTC_Rnom); h_NTC_Mux.setNTCParameters(h_NTC_Rnom, h_NTC_Tnom, h_NTC_B); eepromWritten = 1; } lcd.print(F("H0-7")); } else if(menuDevice == 2){ if(eepromWritten == 0){ EEPROM_writeAnything(addr_u_NTC_B, u_NTC_B); EEPROM_readAnything(addr_u_NTC_Rnom, u_NTC_Rnom); EEPROM_readAnything(addr_u_NTC_Tnom, u_NTC_Tnom); EEPROM_readAnything(addr_u_NTC_B, u_NTC_B); u_NTC_8.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); u_NTC_9.setNTCParameters(u_NTC_Rnom, u_NTC_Tnom, u_NTC_B); eepromWritten = 1; } lcd.print(F("U8-9")); } lcd.setCursor(4,0); lcd.print(F(" NTC B value set to: "));// 30 chars lcd.setCursor(34,0); if(menuDevice == 1) lcd.print(h_NTC_B); if(menuDevice == 2) lcd.print(u_NTC_B); lcd.setCursor(38,0); lcd.print(" K"); nextMenuState = DeviceMenu; break; } }// loop() // FUNCTIONS // clear lcd line void lcdClearLine(int lineNum){ if(lineNum == 0 || lineNum == 1){ lcd.setCursor(0,lineNum); lcd.print(F(" ")); } return; } void printSensorValues(){ for(byte count = 0; count < 8; count++){ if(count < h_NTC_N_enable){ Serial.print(h_NTC_T[count],1 ); Serial.print(','); } else{ Serial.print("-99.9,"); } } switch(u_NTC_N_enable){ case 0: Serial.print(F("-99.9,-99.9,")); break; case 1: Serial.print(u_NTC_8_T,1); Serial.print(F("-99.9,")); case 2: Serial.print(u_NTC_8_T,1); Serial.print(','); Serial.print(u_NTC_9_T,1); Serial.print(','); break; } if(sht_enable > 0){ Serial.print(sht_T,1); Serial.print(','); Serial.print(sht_RH,1); Serial.print(','); } else Serial.print("-99.9,99.9,"); if(outputState) Serial.println(F("ENABLED")); else Serial.println(F("DISABLED")); #ifdef DEBUG Serial.print(F("freeMemory():")); Serial.println( freeMemory() ); #endif return; } // lookup commands received over serial in lookup table int lookup(char rxcmd[]) { const int ncmds = sizeof lookup_table / sizeof *lookup_table; for(int i=0; i!= ncmds; i++) if( strcmp(rxcmd, lookup_table[i]) == 0) return i; return None; } #ifdef DEBUG /* Calculates the size of the free list */ int freeListSize() { struct __freelist* current; int total = 0; for (current = __flp; current; current = current->nx) { total += 2; /* Add two bytes for the memory block's header */ total += (int) current->sz; } return total; } int freeMemory() { int free_memory; if ((int)__brkval == 0) { free_memory = ((int)&free_memory) - ((int)&__heap_start); } else { free_memory = ((int)&free_memory) - ((int)__brkval); free_memory += freeListSize(); } return free_memory; } #endif