Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
Flashing thermometer for security camera monitoring |
Posted: Fri May 27, 2016 8:50 am |
|
|
Heres a useful project which flashes the temperature on a bright LED and also uses a parallax LCD for readout. The idea is to be able to log on remotely to your in house web cams, and see what temperature it is during the day by counting flashes on an LED on the unit located anywhere in the room. Next time I use a digital readout temp device, but it was lots of fun to use a thermistor and use an interpolated calibration table!
Here is the web write up on this project inlcuding photos of the project, schematics, code, movies and tech notes:
http://schursastrophotography.com/PICprojects/Thermistor.html
the raw code is here:
Code: |
//****************************************************************************
//Chris Schur
//Date: 3/26/16
//****************************************************************************
/*Description of this Program:
This Program takes readings from a thermistor and converts to LCD output and flashes LED the temp in F
//I/O Designations ---------------------------------------------------
// RA0: - Analog Input: Sensor voltage in (0 - 5v)
// RA1:
// RA2:
// RA3:
// RA4: (Open Collector output)
// RA5:
// RB0:
// RB1:
// RB2:
// RB3:
// RB4:
// RB5:
// RB6:
// RB7:
// RC0: Status LED output
// RC1: Digital Output: LCD out
// RC2:
// RC3:
// RC4:
// RC5:
// RC6:
// RC7:
//--------------------------------------------------------------------
//Include Files:
#include <16F876A.h> //Normally chip, math, etc. used is here.
//Directives and Defines:
#device ADC=10 //Set ADC when used to 10 bit = 0 - 1023
#fuses NOPROTECT,HS,NOWDT //xtal is used
#use delay(crystal=10MHz) //xtal speed
#use fast_io(ALL) //must define tris below in main when using this
#define VOLTAGE 5.040 //Regulator Voltage
#define R2 9890 //Series Resistance Ohms
//For serial Parallax LCD only:
#use rs232(baud = 9600, xmit=Pin_C1, bits=8, parity=N, INVERT, stream = LCD)
//NO_ANALOGS is default in device file...
//Interrupts:
//****************************************************************************
//Global Variables:
int16 RESULT; //a/d conversion of sensor
float Rth; //Thermistor Resistance
float Vo; //Calculated output of A/D in volts
float VperBit; //Volts Per bit from A/D
int8 range; //temp range in table 1-8
float delta; //difference between low end of range and Rth
float percent; //decimal percent up from bottom of range
float offset; //temp in C up from bottom of range
float temp; // temp in C
float tempF; //temp in F
int8 tempFint; //temp in F integer part only
int8 n,m; //temp digits separately
int8 i; //counting variable
//****************************************************************************
//Functions/Subroutines, Prototypes:
void rangecalc(void);
void Fcalc(void);
void flash(void);
//****************************************************************************
//-- Main Program
//****************************************************************************
void main(void) {
// Set TRIS I/O directions, define analog inputs, compartors:
set_tris_A(0b11111);
set_tris_B(0b11111111);
set_tris_C(0b11111100);
setup_adc_ports(AN0); //sensor v input is 0 - 5v
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
//(analog inputs digital by default)
//Initialize variables and Outputs: --------------------------------------
output_low(Pin_C0); //status off
RESULT = 0;
delay_ms(750); //Let LCD warmup.
//Setup for timers, PWM, and other peripherals:
//----------------------------------------------------------------
//MAIN LOOP:
while (true) {
//take reading on analog 0 input:
result = read_adc();
//Next calculate the value of the thermistor currently. first calculate the
//voltage that the A/D is reading:
// 0 to 1024 max = 0v to VOLTAGE
// Volts/bit = VOLTAGE / 1024 = VperBit
VperBit = VOLTAGE / 1024;
// Current value from A/D:
// Vo = RESULT * VperBit
Vo = RESULT * VperBit;
//Current value for thermistor:
//Rth = (Vin * R2)/Vo
Rth = ((VOLTAGE * R2) / Vo) - R2;
//Set up ranges for temp calculations. this is from cal sheet with part:
rangecalc();
//Next we take the value in its approprite range and interpolate temp in C.
switch (range) {
case 1: delta=(111300-Rth); //-30 - 25c delta R = 24900 ohms for 5 degr.
percent=(delta/24900); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -25 + offset;
break;
case 2: delta=(86390-Rth); //-25 - 20c delta R = 18700 ohms for 5 degr.
percent=(delta/18700); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -25 + offset;
break;
case 3: delta=(67740-Rth); //-20 - 15c delta R = 14300 ohms for 5 degr.
percent=(delta/14300); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -20 + offset;
break;
case 4: delta=(53390-Rth); //-15 - 10c delta R = 10900 ohms for 5 degr.
percent=(delta/10900); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -15 + offset;
break;
case 5: delta=(42450-Rth); //-10 - 5c delta R = 8600 ohms for 5 degr.
percent=(delta/8600); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -10 + offset;
break;
case 6: delta=(33890-Rth); //-5 - 0c delta R = 6600 ohms for 5 degr.
percent=(delta/6600); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = -5 + offset;
break;
//------------------ 0 degrees C line ------------------------------
case 7: delta=(27280-Rth); //0 - 5c delta R = 5300 ohms for 5 degr.
percent=(delta/5300); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 0;
break;
case 8: delta=(22050-Rth); //5 - 10c delta R = 4000 ohms for 5 degr.
percent=(delta/4000); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 5;
break;
case 9: delta=(17960-Rth); //10 - 15c delta R = 3300 ohms for 5 degr.
percent=(delta/3300); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 10;
break;
case 10: delta=(14680-Rth); //15 - 20c delta R = 2600 ohms for 5 degr.
percent=(delta/2590); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 15;
break;
case 11: delta=(12090-Rth); //20 - 25c delta R = 2100 ohms for 5 degr.
percent=(delta/2090); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 20;
break;
case 12: delta=(10000-Rth); //25 - 30c delta R = 1690 ohms for 5 degr.
percent=(delta/1687); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 25;
break;
case 13: delta=(8313-Rth); //30 - 35c delta R = 1370 ohms for 5 degr.
percent=(delta/1372); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 30;
break;
case 14: delta=(6941-Rth); //35 - 40c delta R = 1120 ohms for 5 degr.
percent=(delta/1120); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 35;
break;
case 15: delta=(5826-Rth); //40 - 45c delta R = 910 ohms for 5 degr.
percent=(delta/910); //fraction up from bottom of range
offset=(5 * percent); //degrees offset up from bottom
temp = offset + 40;
break;
}
Fcalc(); //calculate F value from C
//Calbibration offset. makes it agree with the other digi thermometers.
tempF = tempF - .5;
//next send to the top line of the display:
fputc(254,LCD); //Non Text INSTRUCTION BYTE TO FOLLOW
delay_ms(1);
fputc(1,LCD); //CLEAR SCREEN
delay_ms(10);
fprintf(LCD,"Temp= %3.1f",tempF); //temp in F
//truncate decimal:
tempFint = tempF; //integer temp, no decimal
n = tempFint/10; //first digit of temp 0 - 13
m = tempFint - (n * 10); //second digit 0 - 9
//fputc(254,LCD); //Non Text INSTRUCTION BYTE TO FOLLOW
//delay_ms(1);
//fputc(192,LCD); //move to start of line 2
//delay_ms(10);
// fprintf(LCD,"n= %u",n);
//fprintf(LCD," m= %u",m);
//fprintf(LCD,"Temp= %3.1f",temp); //temp in C
if (tempF >= 0) //dont try to flash negative numbers
flash();
delay_ms(4000); //display time -space between flash sets.
}
}
//********* Functions which have prototypes at top of program ****************
void rangecalc(void) {
if ((Rth <= 111300) && (Rth > 86400)) //-30 to -25C
range = 1;
if ((Rth <= 86400) && (Rth > 67700)) //-25 to -20c
range = 2;
if ((Rth <= 67700) && (Rth > 53400)) //-20 to -15c
range = 3;
if ((Rth <= 53400) && (Rth > 42500)) //-15 to -10c
range = 4;
if ((Rth <= 42500) && (Rth > 33900)) //-10 to -5c
range = 5;
if ((Rth <= 33900) && (Rth > 27300)) //-5 to 0c
range = 6;
if ((Rth <= 27300) && (Rth > 22000)) //0 to 5c
range = 7;
if ((Rth <= 22000) && (Rth > 18000)) //5 to 10c
range = 8;
if ((Rth <= 18000) && (Rth > 14700)) //10 to 15c
range = 9;
if ((Rth <= 14700) && (Rth > 12100)) //15 to 20c
range = 10;
if ((Rth <= 12100) && (Rth > 10000)) //20 to 25c
range = 11;
if ((Rth <= 10000) && (Rth > 8310)) //25 to 30c
range = 12;
if ((Rth <= 8310) && (Rth > 6940)) //30 to 35c
range = 13;
if ((Rth <= 6940) && (Rth > 5820)) //35 to 40c
range = 14;
if ((Rth <= 5820) && (Rth > 4910)) //40 to 45c
range = 15;
}
void Fcalc(void) {
tempF = (temp * 1.8) + 32;
}
void flash(void) { //flashes the digit for the temp integer value
for (i=1;i<=n;i=i+1) { //flashes digit for 0 - 13 times for 10 to 130F
output_high(Pin_C0);
delay_ms(500);
output_low(Pin_C0);
delay_ms(500); }
delay_ms(2000);
for (i=1;i<=m;i=i+1) { //flashes second digit for 0-9 times for 0 to 9F
output_high(Pin_C0);
delay_ms(500);
output_low(Pin_C0);
delay_ms(500); }
return;
} //flash
|
|
|