////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// /* Thermistorcator v2 2013-11-01 Thermistors plus 128x64 I2C output OLED SDA- Analog 4 SCL- Analog 5 2013-11-22 Add two input buttons 2014-02-02 AA - 128x64 screen; note .h has to be changed to reflect x64 height and code reflects new address (0x3D) - Vertical temperature display; tighten code for better display/memory issues; check FreeMemory; strings eat up memory 2014-02-12 AA - Add 5th thermistor for internal/onboard temperature measurement; tighten up code some more. 2014-02-14 AA - Testing 2014-02-15 AA - Cleanup display; only diff/max-mix the first 4 thermistors */ ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// #include #include #include #include #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 #if (SSD1306_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif #define N_THERMISTORS 5 int TempFlag=0; // 0 for C, 1 for F int BlackButton=2; int RedButton=3; int Thermistor_Pin[N_THERMISTORS]; int decplaces=1; int disptype=0; int BlackButtonState; int BlackButtonStatePrev; int RedButtonState; int RedButtonStatePrev; float aminval=999; float amaxval=-999; float temperature_thermistor_stored[N_THERMISTORS]; char MaxString[4]="max"; char MinString[4]="min"; char versionid[11]="2014.02.15"; int i; int cntr; void setup() ////////////////////////////////////////////////////////////////// { // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3C (for the 128x32); 0x3D for the 128x64 // display.display(); // show splashscreen //delay(2000); //display.clearDisplay(); // draw a single pixel //display.drawPixel(10, 10, WHITE); // display.display(); // delay(2000); display.clearDisplay(); display.display(); Thermistor_Pin[0]=A0; Thermistor_Pin[1]=A1; Thermistor_Pin[2]=A2; Thermistor_Pin[3]=A3; Thermistor_Pin[4]=A7; // internal // thermistor pin (analog input) for calibration for(i=0;i<=N_THERMISTORS-1;i++) { pinMode(Thermistor_Pin[i], INPUT); } // for black and red switches pinMode(BlackButton,INPUT_PULLUP); pinMode(RedButton,INPUT_PULLUP); DisplaySplash(); Serial.begin(9600); //Serial.print("starting..."); //Serial.print("freeRam="); //Serial.println(freeRam()); } /*int freeRam () { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } */ void DisplaySplash(){ // text display tests display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); display.print("Thermistorcator"); display.setCursor(0,8); display.print("Clipboard Engineering"); display.setCursor(0,16); display.print("NTCLE100E3103JB0"); display.setCursor(0,24); display.print("-40C to 125C"); display.setCursor(0,32); display.print("Version: "); display.print(versionid); display.setCursor(0,40); display.print("Black = DEC & UNITS"); display.setCursor(0,48); display.print("Red = FUNC"); display.setCursor(0,56); display.print("T1-T5 out - 9600 baud"); // 01234567890123456789012 display.display(); delay(2000); } void loop() ////////////////////////////////////////////////////////////////// { int i; int sensorValue; float voltage; float temperature_thermistor[N_THERMISTORS]; float maxval; float minval; float temptest; RedButtonState = digitalRead(RedButton); BlackButtonState = digitalRead(BlackButton); // // text display tests // display.clearDisplay(); // display.setTextSize(1); // display.setTextColor(WHITE); // display.setCursor(0,0); // display.print("hello, world"); // display.setCursor(0,8); // display.print(icount++); // // text display tests display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); minval=999; maxval=-999; // first column gives units if(TempFlag==0) { Serial.print("C"); } else { Serial.print("F"); } for(i=0;i<=N_THERMISTORS-1;i++) { // get temperature via Vishay thermistor sensorValue = analogRead(Thermistor_Pin[i]); voltage=5.0*sensorValue/1023.0; temperature_thermistor[i] = CalculateTemperatureThermistor(voltage); //Serial.print("Thermistor "); //Serial.print(i); Serial.print(","); // just show value; faster Serial.print(DisplayTemp(temperature_thermistor[i])); // Serial.print(","); delay(10); if(i=0) { display.print("+"); } if(TempFlag==0) // C { display.print((temperature_thermistor[i]-temperature_thermistor_stored[i]) ,decplaces); } else // showing delta only; stored temperature is in C, so can't use C to F function directly { display.print(1.8*(temperature_thermistor[i]-temperature_thermistor_stored[i]) ,decplaces); } } // 6 pixels per character (wide) // 0-5 for char 0, 6-11 for char 1, etc. // Tn = +XXX.X intrnl // 012345678901234 // char 12 starts at n*6 = 12*6 = 72 if(i==N_THERMISTORS-1) { display.setCursor(72,i*8); display.print("intrnl"); } } Serial.println(); // detail on min/max etc. display.setCursor(0,N_THERMISTORS*8); //////////////////////////////////////// if(disptype==0) // show max differences { // type display.setCursor(0,N_THERMISTORS*8); display.print("ABS DELTA"); display.setCursor(0,(N_THERMISTORS+1)*8); display.print(MaxString); display.print("-"); display.print(MinString); display.print("="); display.print(DisplayTemp(maxval)-DisplayTemp(minval),decplaces); } //////////////////////////////////////// else if(disptype==1) // show max/min values, no matter where { display.setCursor(0,N_THERMISTORS*8); display.print("MAX/MIN"); display.setCursor(0,(N_THERMISTORS+1)*8); display.print(MinString); if(minval>=0) { display.print("+"); } display.print(DisplayTemp(minval),decplaces); display.print("/"); display.print(MaxString); if(maxval>=0) { display.print("+"); } display.print(DisplayTemp(maxval),decplaces); } //////////////////////////////////////// else if(disptype==2) // lock in max/min values { display.setCursor(0,N_THERMISTORS*8); display.print("HOLD"); display.setCursor(0,(N_THERMISTORS+1)*8); if(maxval>=amaxval){ amaxval=maxval; } if(minval<=aminval){ aminval=minval; } display.print(MinString); if(aminval>=0) { display.print("+"); } display.print(DisplayTemp(aminval),decplaces); display.print("/"); display.print(MaxString); if(amaxval>=0) { display.print("+"); } display.print(DisplayTemp(amaxval),decplaces); } //////////////////////////////////////// else if(disptype==3) // offsets { display.setCursor(0,N_THERMISTORS*8); display.print("DIFF FROM SET"); } // change decimal places and C/F values if (BlackButtonState==LOW && BlackButtonStatePrev==HIGH) { decplaces=decplaces+1; if(decplaces>2) { TempFlag=1-TempFlag; decplaces=0; } } if (RedButtonState==LOW && RedButtonStatePrev==HIGH) { // every time we change, reset amaxvalue and aminvalue amaxval=-999; aminval=999; // display type increment disptype=disptype+1; if(disptype>3) { disptype=0; } // stored value for offsetting for(i=0;i<=(N_THERMISTORS-1);i++) { if(disptype==3) { temperature_thermistor_stored[i]=temperature_thermistor[i]; } } } // store previous states for transitions BlackButtonStatePrev=BlackButtonState; RedButtonStatePrev=RedButtonState; if(RedButtonState==LOW && BlackButtonState==LOW) { DisplaySplash(); } display.setCursor(0,7*8); display.print("Vcc="); display.print(float(readVcc())/1000.0,3); display.print(" "); display.print(freeMemory()); // show unit in lower right hand corner // display.setCursor(121,(N_THERMISTORS-1)*8); if(TempFlag==0) { display.print("C"); } else { display.print("F"); } display.setCursor(122,56); if(cntr==0) { display.print("-"); } else if(cntr==1) { display.print("\\"); } else if(cntr==2) { display.print("|"); } else { display.print("/"); cntr=-1; } cntr=cntr+1; display.display(); delay(100); } float CalculateTemperatureThermistor(float RawVoltage) ///////////////////////////////////////////////////// { // connection is: // 5V ---- resistor -- X -- thermistor ----- GND // X is connection to analog input // Vishay NTCLE100E3103JB0 thermistor float lvalue; float dk; float vRatio; vRatio = RawVoltage / 5; float rValue; float thermResistance; float thermRefResistance; rValue = 9090; // resistance in ohms in series thermRefResistance = 10000; thermResistance = vRatio * rValue / (1 - vRatio); lvalue = log(thermResistance / thermRefResistance); dk = 1 / (0.003354016 + 0.000256985 * lvalue + 0.000002620131 * lvalue * lvalue + 0.00000006383091 * lvalue * lvalue * lvalue); return(dk - 273.15); // if(TempFlag==0) // { // // return temperature in C // return(dk - 273.15); // } // else // { // // return temperature in F // return(((dk - 273.15)*(9.0/5.0))+32.0); // } } float DisplayTemp(float value) { float ftemp; if(TempFlag==0) { // return temperature in C return(value); } else { // return temperature in F ftemp=value * 1.8 + 32.0; return(ftemp); } } long readTemp() { long result; // Read temperature sensor against 1.1V reference ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = (result - 125) * 1075; return result; } long readVcc() { long result; // Read 1.1V reference against AVcc ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate AVcc in mV return result; }