//TEMP2 - TEMPERATURE MONITOR (Type2) //Temperature monitor, data logging and LED display //One to four temperature sensors can be monitored //Each are measured every second //The highest value for each is stored during a 20 second cycle and then written to memory //Designed for the MCP9701 temperature sensors (5v 3-lead but linear and match ADC steps) //An ADC value of 82 represents 0'C and every 4th ADC step represents 1'C (86 = 1'C) //The results are displayed in real time via 3 LEDs per channel //9 temperature levels have been configured to set thresholds for the LEDs //In order to maximise the 256bytes of EEPROM memory, each 10bit ADC value is reduced to 8bits //This creates an error of less than 1'C due to truncation instead of rounding (OK for intended use) //Correct register values of 0-255 convert to 10-201'C (after which the register wraps) //A 20 sec recording interval (x4 sensors) yields ~21minutes recording (256/4*20/60) //To convert memory data to 'C: (((n * 3) + 122) - 82) / 4) (eg: 889 becomes 255 and converts to 201'C) //ADC values larger than 889 convert to >255 so the 8bit register 'wraps' (max 1023 become '44') //Similarly, values <122 become negative so convert to positive due to unsigned variables used //Memory is cleared every time the device is powered up but only if harness is connected //This assumes the wiring harness forces 'mem' port high with a jumper from pin 4 to + //Written for PIC16F687 (20 pin) / BoostC compiler //Personal and non-commercial use encouraged //Copyright 2007 - David Theunissen - See www.flyelectric.ukgateway.net //PREPROCESSOR section ======================================================== #include //Generic device include (actual device set in Settings/Target) //Core configuration option_regs: #pragma DATA _CONFIG, _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO //VARIABLES section =========================================================== //Four temperature sensors each with three LEDs (High, Medium and Low) #define led1h portb.5 //RB5 (Pin12) AN11 'High' LED for Sensor 1... #define led1m portb.4 //RB4 (Pin13) AN10 #define led1l portc.1 //RC1 (Pin15) AN5 #define led2h portc.4 //RC4 (Pin6) #define led2m portb.7 //RB7 (Pin10) #define led2l portb.6 //RB6 (Pin11) #define led3h portc.5 //RC5 (Pin5) #define led3m porta.4 //RA4 (Pin3) AN3 #define led3l porta.5 //RA5 (Pin2) #define led4h porta.0 //RA0 (Pin19) AN0 #define led4m porta.1 //RA1 (Pin18) AN1 #define led4l porta.2 //RA2 (Pin17) AN2 #define mem porta.3 //RA3 (Pin4) //Input to disable writing to EEPROM when harness removed //Held low on board with 10k resistor //Harness holds high when connected //------------------------------------------------------------------------------ typedef unsigned char u8; //Defines u8 as an unsigned char type (8bits) typedef unsigned short u16; //Defines u16 as an unsigned short type (16bits) u8 h; //Startup LED counter u8 r; //Initialises EEPROM u8 i; //Timer in ADC conversion u16 t_value; //Results of each ADC conversion u16 t1; //'Last' temperature - LED display (helps with 'hold' feature) u16 t2; u16 t3; u16 t4; u16 t1_high; //Highest temperature in each cycle - written to EEPROM u16 t2_high; u16 t3_high; u16 t4_high; u8 s; //Counts measurements between writes to memory u16 m_count; //Memory Counter - prevents over-writes u8 t; //Times how long push-button is held down (used in Interrupt) u8 k; //Initialises EEPROM on warm-reset u8 l; //Counter for memory reset counter //FUNCTIONS section =========================================================== void led_off() //Function to switch all LEDs OFF { led1h=0; led1m=0; led1l=0; led2h=0; led2m=0; led2l=0; led3h=0; led3m=0; led3l=0; led4h=0; led4m=0; led4l=0; } //----------------------------------------------------------------------------- void write_data() //Function to write to EEPROM flash memory { intcon.7 = 0; //Disable all interrupts while writing to memory pir1.7 = 0; //EEIF: Clear this bit which gets set after each write eecon2 = 0x55; //Required before writing to memory eecon2 = 0xAA; //Required before writing to memory eecon1.1 = 1; //WR: Writes data eedata to address eeadr while(eecon1.1==1); //Wait for write to complete (becomes 0 when complete) eeadr++; //Increment the address by 1 for next write (8 bit 0-255) intcon.7 = 1; //Enable interrupts again } //------------------------------------------------------------------------------ void run_adc() //Function to run ADC conversions { //Run ADC for(i=0; i<1; i++); //Delay for acquisition capacitor to u8ge (1 = ~14uS) pir1.6 = 0; //Clear the ADC Complete flag adcon0.1 = 1; //GO: Start ADC acquisition while(pir1.6==0); //Wait for conversion to complete (become 1) //Store ADC value in t_value (Creates a 10bit value by merging two registers) MAKESHORT(t_value, adresl, adresh); } //----------------------------------------------------------------------------- void measure_temp() //Function to trigger ADC conversions to measure sensors { //adcon0 structure... //1 Right justify ADC values //0 Use Vdd as reference //xxxx Input channel (THIS PART CHANGES BELOW) //0 ADC capture (GO) not started //1 ADC enabled //Determine 1st sensor value adcon0 = 0b10011001; //Makes AN6 (pin14) channel active run_adc(); //Run ADC conversion t1 = t_value; //Copy result to appropriate register //Determine 2nd sensor value adcon0 = 0b10011101; //Makes AN7 (pin7) channel active run_adc(); //Run ADC conversion t2 = t_value; //Copy result to appropriate register //Determine 3rd sensor value adcon0 = 0b10100101; //Makes AN9 (pin9) channel active run_adc(); //Run ADC conversion t3 = t_value; //Copy result to appropriate register //Determine 4th sensor value adcon0 = 0b10100001; //Makes AN8 (pin8) channel active run_adc(); //Run ADC conversion t4 = t_value; //Copy result to appropriate register } //----------------------------------------------------------------------------- void display_results_1() //Function to display results via LEDs (Mode 1) { /* //Testing variables (hold sensor against hot kettle) u16 level1 = 174; //23'C u16 level2 = 182; //25 u16 level3 = 190; //27 u16 level4 = 198; //29 u16 level5 = 206; //31 u16 level6 = 214; //33 u16 level7 = 222; //35 u16 level8 = 230; //37 u16 level9 = 238; //39 */ //Local variables (values used to monitor 2-stroke cyclinder barrels) u16 level1 = 400; //80-90 Green 50% flash u16 level2 = 440; //90-100 Green 100% on u16 level3 = 480; //100-110 Yellow 50% flash u16 level4 = 520; //110-120 Yellow 100% on u16 level5 = 560; //120-130 Red 50% flash u16 level6 = 600; //130-140 Red 100% on u16 level7 = 640; //140-150 Red + Yellow 100% on u16 level8 = 680; //150-160 Red + Yellow + Green 100% on u16 level9 = 720; //160+ Red + Yellow + Green 12.5% rapid flash led_off(); if (t1>=level1 && t1=level3 && t1=level5) led1h=1; if (t1>=level7) led1m=1; if (t1>=level8) led1l=1; if (t2>=level1 && t2=level3 && t2=level5) led2h=1; if (t2>=level7) led2m=1; if (t2>=level8) led2l=1; if (t3>=level1 && t3=level3 && t3=level5) led3h=1; if (t3>=level7) led3m=1; if (t3>=level8) led3l=1; if (t4>=level1 && t4=level3 && t4=level5) led4h=1; if (t4>=level7) led4m=1; if (t4>=level8) led4l=1; delay_ms(125); if (t1>=level9) {led1l=0; led1m=0; led1h=0;} if (t2>=level9) {led2l=0; led2m=0; led2h=0;} if (t3>=level9) {led3l=0; led3m=0; led3h=0;} if (t4>=level9) {led4l=0; led4m=0; led4h=0;} delay_ms(125); if (t1>=level9) {led1l=1; led1m=1; led1h=1;} if (t2>=level9) {led2l=1; led2m=1; led2h=1;} if (t3>=level9) {led3l=1; led3m=1; led3h=1;} if (t4>=level9) {led4l=1; led4m=1; led4h=1;} delay_ms(125); if (t1>=level9) {led1l=0; led1m=0; led1h=0;} if (t2>=level9) {led2l=0; led2m=0; led2h=0;} if (t3>=level9) {led3l=0; led3m=0; led3h=0;} if (t4>=level9) {led4l=0; led4m=0; led4h=0;} delay_ms(125); if (t1>=level1 && t1=level3 && t1=level5 && t1=level9) {led1l=1; led1m=1; led1h=1;} if (t2>=level1 && t2=level3 && t2=level5 && t2=level9) {led2l=1; led2m=1; led2h=1;} if (t3>=level1 && t3=level3 && t3=level5 && t3=level9) {led3l=1; led3m=1; led3h=1;} if (t4>=level1 && t4=level3 && t4=level5 && t4=level9) {led4l=1; led4m=1; led4h=1;} delay_ms(125); if (t1>=level9) {led1l=0; led1m=0; led1h=0;} if (t2>=level9) {led2l=0; led2m=0; led2h=0;} if (t3>=level9) {led3l=0; led3m=0; led3h=0;} if (t4>=level9) {led4l=0; led4m=0; led4h=0;} delay_ms(125); if (t1>=level9) {led1l=1; led1m=1; led1h=1;} if (t2>=level9) {led2l=1; led2m=1; led2h=1;} if (t3>=level9) {led3l=1; led3m=1; led3h=1;} if (t4>=level9) {led4l=1; led4m=1; led4h=1;} delay_ms(125); if (t1>=level9) {led1l=0; led1m=0; led1h=0;} if (t2>=level9) {led2l=0; led2m=0; led2h=0;} if (t3>=level9) {led3l=0; led3m=0; led3h=0;} if (t4>=level9) {led4l=0; led4m=0; led4h=0;} delay_ms(125); } //=========================================================================== void main() //main program { //Initialise all ports, etc porta=0; portb=0; portc=0; //Start low m_count=0; //Memory write counter //Main port settings (1=Input 0=Output) trisa.0 = 0; //RA0 (Pin19) AN0 trisa.1 = 0; //RA1 (Pin18) AN1 trisa.2 = 0; //RA2 (Pin17) AN2 trisa.3 = 1; //RA3 (Pin4) Input to disable EEPROM writes trisa.4 = 0; //RA4 (Pin3) AN3 trisa.5 = 0; //RA5 (Pin2) trisb.4 = 0; //RB4 (Pin13) AN10 trisb.5 = 0; //RB5 (Pin12) AN11 trisb.6 = 0; //RB6 (Pin11) trisb.7 = 0; //RB7 (Pin10) //trisc.0 = 1; //RC0 (Pin16) AN4 Spare input trisc.1 = 0; //RC1 (Pin15) AN5 trisc.2 = 1; //RC2 (Pin14) AN6 TEMP1 input trisc.3 = 1; //RC3 (Pin7) AN7 TEMP2 input trisc.4 = 0; //RC4 (Pin6) trisc.5 = 0; //RC5 (Pin5) trisc.6 = 1; //RC6 (Pin8) AN8 TEMP4 input trisc.7 = 1; //RC7 (Pin9) AN9 TEMP3 input //ADC port settings (1=Analog 0=Digital) ansel.0 = 0; //RA0 (Pin19) AN0 ansel.1 = 0; //RA1 (Pin18) AN1 ansel.2 = 0; //RA2 (Pin17) AN2 ansel.3 = 0; //RA4 (Pin3) AN3 //ansel.4 = 1; //RC0 (Pin16) AN4 Spare input ansel.5 = 0; //RC1 (Pin15) AN5 ansel.6 = 1; //RC2 (Pin14) AN6 TEMP1 input ansel.7 = 1; //RC3 (Pin7) AN7 TEMP2 input anselh.0 = 1; //RC6 (Pin8) AN8 TEMP4 input anselh.1 = 1; //RC7 (Pin9) AN9 TEMP3 input anselh.2 = 0; //RB4 (Pin13) AN10 anselh.3 = 0; //RB5 (Pin12) AN11 //Static ADC settings adcon1 = 101; //AD Conversion Clock Fosc/16 pie1.6 = 0; //ADC interrupts disabled //Static EEPROM data logging settings eecon1.7 = 0; //EEPGD: Access data memory eecon1.3 = 0; //WRERR: clear on startup in case previously set eecon1.2 = 1; //WREN: enable writing to memory //Flash LEDs on startup for (h=0; h<1; h++) { led1l=1; led1m=1; led1h=1; delay_s(1); led1l=0; led1m=0; led1h=0; delay_ms(250); led2l=1; led2m=1; led2h=1; delay_s(1); led2l=0; led2m=0; led2h=0; delay_ms(250); led3l=1; led3m=1; led3h=1; delay_s(1); led3l=0; led3m=0; led3h=0; delay_ms(250); led4l=1; led4m=1; led4h=1; delay_s(1); led4l=0; led4m=0; led4h=0; delay_ms(250); } //Initialise EEPROM //This overwrites memory but only if harness is connected if (mem==1) //Required harness to be connected to force mem port high { for (r=0; r<255; r++) { eedata = 0; write_data(); } eeadr = 0; //Address to be used for first write in rest of program } //----------------------------------------------------------------------------- while(1) { //Initialise registers after each 'cycle' t1_high=0; t2_high=0; t3_high=0; t4_high=0; //Initialise 'high' registers //Establish cycles for regular writes to memory and updating display for (s=0; s<20; s++) //Measure sensors 's' times in each cycle { //Measure all sensors measure_temp(); display_results_1(); //Store highest values measured in each cycle (if greater) if (t1>t1_high) t1_high=t1; if (t2>t2_high) t2_high=t2; if (t3>t3_high) t3_high=t3; if (t4>t4_high) t4_high=t4; } //After interval set above, write highest temperatures in each cycle to memory if (m_count<252 && mem==1) //Check if space remains (prevent memory over-write) //And harness is connected ('mem' port is high) { //First manipulate values to make them reveal 10-201'C with 8bits //Deduct 122 then divide by 3 to achieve this ('n' in next example) //To convert result 'n' to 'C: (((n * 3) + 122) - 82) / 4 //ADC value 889 becomes 255 and converts to 201'C (889 is actually 201.75; small error) t1_high -= 122; //122 is 10' but we want it to become a 0 t1_high /= 3; //Divide result by 3 to reduce size LOBYTE(eedata, t1_high); //Select low 8bits to record write_data(); //Write to memory m_count ++; //Increment counter to avoid over-writing memory t2_high -= 122; t2_high /= 3; LOBYTE(eedata, t2_high); write_data(); m_count ++; t3_high -= 122; t3_high /= 3; LOBYTE(eedata, t3_high); write_data(); m_count ++; t4_high -= 122; t4_high /= 3; LOBYTE(eedata, t4_high); write_data(); m_count ++; } } //end while } //end main