We can substitute a thermistor for the 10K pot in program #9 and we have a thermometer. The major problem is calibration of the thermistor. We must make up a table of temperature values for each TMR0 reading we get. You can see the ones I came up with at the end of the program. Just by luck it covered the temperature range I was interested in without changing the prescalar ratio, (it stays at 1:16). The temperatures are degrees Fahrenheit and the low numbers after 99 are 100 and up.
The thermistor has a room temperature value of about 9K. Peter Anderson, ( http://www.phanderson.com), sells them for $0.65. He also sells the National LM35DZ thermometer for about $1.25 that you can use to calibrate the thermistor. You will need something like digital multimeter to read LM35 at 10 mV/ deg F, (just add a battery). I placed the thermistor and thermometer together in a stirred bath of ice water which I let heated up. I took tmr0 readings and temperature about every degree or so. Putting the values in Excel allowed me to fit a quadratic and create a table of temperature vs TMR0 reading. The values occur in two tables with the integer 2 digits in one and the single fractional digit in the other.
You will notice that I placed the tables at H'200' and H'300'which are the 3rd and 4th pages of '84 program memory. This brings up a problem you may encounter with the program counter. 'Goto' and 'call' can modify the program counter and reach any place in the 16F84's program space. If you modify PCL, ( Program Counter Low byte ), you can make a change of only 256 locations, the size of one page. The high byte of the program counter, the page bits, are not directly available. Any instruction, other than goto or call or return, that modifies PCL also causes the page bits of the program counter to be loaded from a register called PCLATH.
PCLATH seems to be initialized to zero. As long as our table stays in page 0 everything is O.K. If we place our table on another page, we have to preload PCLATH with the page every time we access the table. This is done in the main loop, 'sholoop' where 2 is loaded in to PCLATH before temptable is called. Things get more complicated when a table crosses a page boundary. We simplify things by making sure our table stays within one page.
The thermometer is probably not very accurate. The LM35DZ I used could have been off although it did read 31.9 deg F in the ice bath. The quadratic deviates from the real curve at the upper and lower end. It gives a ice point value 2 degrees high, (TMR0 value at ice point was 65). Higher order polynominals seemed to wiggle around too much. You can probably come up with a better fit and something to check the LM35.
;-------------------------------------------------------------------------; ; THERM.ASM Shows Temperature from Thermistor on LCD ; ;-------------------------------------------------------------------------; LIST P=16F84 ; 16F84 Runs at 4 MHz INCLUDE "p16f84.inc" __CONFIG _PWRTE_ON & _LP_OSC & _WDT_OFF ; uses 32.768 kHz crystal ERRORLEVEL -224 ; supress annoying message because of tris ERRORLEVEL -302 ; supress message because of page change ; Define Information #DEFINE RS PORTA, 0 ; RA0 is RS line of LCD #DEFINE E PORTA, 1 ; RA1 is E line of LCD ; RB0-RB3 are D4-D7 of LCD ; Macro EStrobe MACRO ; Strobe the "E" Bit bsf E bcf E ENDM CBLOCK 0CH Temp ; a temporary variable count ; counter bin ; binary number to be converted to BCD hundreds ; BCD hundreds result tens_and_ones ; BCD tens and ones result savetmr0 ; used to save value of tmr0 dispvalue ; used to hold temperature to be displayed tableindex ; points to table value to display ENDC ORG 0 ; start at location 0 goto main ; jump over to main routine ;-------------------------------------------------------------------------; ; Data for message to be output ; ;-------------------------------------------------------------------------; shomsg: ; Message to Output addwf PCL, f ; Output the Characters m0 dt "TMR0 Value:", 0 m1 dt "Temperature", 0 ;-------------------------------------------------------------------------; ; Ratios of Prescaler ; ;-------------------------------------------------------------------------; preratio: addwf PCL, f ; select offset using W dt D'2',D'4',D'8',D'16',D'32',D'64',D'128' ;-------------------------------------------------------------------------; ; Initialize the ports ; ;-------------------------------------------------------------------------; Init: clrf PORTA clrf PORTB movlw B'00010000' ; RA4 input, others outputs tris PORTA movlw B'00110000' ; RB4, RB5 input, others outputs tris PORTB movlw B'00100011' ; pull-ups enabled ; prescaler assigned to RA4 ; prescaler set to 1:16 option return ;-------------------------------------------------------------------------; ; Initialize the LCD ; ;-------------------------------------------------------------------------; initlcd: movlw D'40' call nmsec ; Wait 40 msecs before Reset bcf RS ; send an 8 bit instruction movlw 0x03 ; Reset Command call NybbleOut ; Send the Nybble call Dlay5 ; Wait 5 msecs before Sending Again EStrobe nop nop ; Wait 244 usecs before Sending the Second Time EStrobe nop nop ; Wait 244 usecs before Sending the Third Time bcf RS ; send an 8 bit instruction movlw 0x02 ; Set 4 Bit Mode call NybbleOut nop nop movlw 0x028 ; 4 bit, 2 Line, 5x7 font call SendINS movlw 0x010 ; display shift off call SendINS movlw 0x001 ; Clear the Display RAM call SendINS call Dlay5 ; Note, Can take up to 4.1 msecs movlw 0x006 ; increment cursor call SendINS movlw 0x00C ; display on cursor off call SendINS return ;-------------------------------------------------------------------------; ; Send the character in W out to the LCD ; ;-------------------------------------------------------------------------; SendASCII addlw '0' ; Send nbr as ASCII character SendCHAR ; Send the Character to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the High Nybble bsf RS ; RS = 1 call NybbleOut movf Temp, w ; Send the Low Nybble bsf RS call NybbleOut return ;-------------------------------------------------------------------------; ; Send an instruction in W out to the LCD ; ;-------------------------------------------------------------------------; SendINS ; Send the Instruction to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the High Nybble bcf RS ; RS = 0 call NybbleOut movf Temp, w ; Send the Low Nybble bcf RS call NybbleOut return ;-------------------------------------------------------------------------; ; Send the nibble in W out to the LCD ; ;-------------------------------------------------------------------------; NybbleOut ; Send a Nybble to the LCD movwf PORTB EStrobe ; Strobe out the LCD Data nop nop return ;-------------------------------------------------------------------------; ; Output the message on the LCD ; ;-------------------------------------------------------------------------; OutMessage: movwf FSR ; Point at first letter OutLoop: movf FSR, w ; Get pointer into W incf FSR, f ; Set up for next letter call shomsg ; Get character to output iorlw 0 ; At the End of the Message? btfsc STATUS, Z ; Skip if not at end return ; Yes - Equal to Zero call SendCHAR ; Output the ASCII Character goto OutLoop ; Get the next character ;-------------------------------------------------------------------------; ; Change binary nbr in bin to BCD ; ;-------------------------------------------------------------------------; binary_to_bcd ; by Scott Dattalo clrf hundreds swapf bin, W addwf bin, W andlw B'00001111' skpndc addlw 0x16 skpndc addlw 0x06 addlw 0x06 skpdc addlw -0x06 btfsc bin,4 addlw 0x16 - 1 + 0x6 skpdc addlw -0x06 btfsc bin,5 addlw 0x30 btfsc bin, 6 addlw 0x60 btfsc bin,7 addlw 0x20 addlw 0x60 rlf hundreds, f btfss hundreds, 0 addlw -0x60 movwf tens_and_ones btfsc bin,7 incf hundreds, f return ;-----------------------------------------------------------------------; ; Delay routine ; ;-----------------------------------------------------------------------; msec250 movlw 0 ; 250 msec delay (adjusted to try and ; allow for 2.5% low loop time) goto $+2 Dlay5 movlw 5 ; delay for 5 milliseconds nmsec: ; delay for # msec in W on entry nop ; each nop is 0.122 milliseconds nop nop ; each total loop is 8 X 0.122 = 0.976 msec nop addlw H'FF' ; same as subtracting 1 from W btfss STATUS, Z ; skip if result is zero goto nmsec ; this is 2 X 0.122 msec return ; back to calling point ;-------------------------------------------------------------------------; ; Display binary value in W in decimal ; ; ;-------------------------------------------------------------------------; DispDec movwf bin call binary_to_bcd movf hundreds, W call SendASCII swapf tens_and_ones, W andlw H'F' call SendASCII movf tens_and_ones, W andlw H'F' call SendASCII return ;-------------------------------------------------------------------------; ; The Main routine ; ;-------------------------------------------------------------------------; main: call Init ; initialize ports, set up timer call initlcd ; initialize the LCD movlw H'80' ; position at 1st line column 0 call SendINS movlw m0 -2 ; send 'TMR0 Value:' message call OutMessage movlw H'C0' call SendINS ; position at 2nd line column 0 movlw m1 -2 ; send 'Temperature:' message call OutMessage sholoop: movlw H'8C' ; position at 1st line column 12 call SendINS bcf INTCON, T0IF ; clear timer zero interrupt flag clrf TMR0 ; zero TMR0 call msec250 ; wait a total of one second call msec250 call msec250 call msec250 movf TMR0, W ; retrieve timer zero movwf savetmr0 ; save the value btfsc INTCON, T0IF ; check if timer overflowed goto overload ; yes, display 'OVR' call DispDec ; display TMR0 value movlw H'CC' ; position at 2nd line column 12 call SendINS movlw 2 ; set up PCLATH to page 2 movwf PCLATH movlw D'64' ; 1st table value is for tmr0 = 64 subwf savetmr0, W ; subtract 64 from tmr0 value movwf tableindex call temptable1 ; get 1st two digits of temperature movwf dispvalue ; save it in display value swapf dispvalue, W ; get hi nibble in W andlw H'0F' ; lowest 4 bits call SendASCII ; display it movf dispvalue, W ; get lo nibble in W andlw H'0F' ; lowest 4 bits call SendASCII ; display it movlw '.' ; send decimal point call SendCHAR movlw 3 ; set up for second table, (page 3) movwf PCLATH movf tableindex, W call temptable2 ; get decimal point call SendASCII ; display it goto sholoop ; repeat forever overload movlw 'O' ; output 'OVER' call SendCHAR movlw 'V' call SendCHAR movlw 'E' call SendCHAR movlw 'R' call SendCHAR movlw ' ' call SendCHAR goto sholoop ; and continue org H'200' temptable1: ; get temperature to display addwf PCL, f dt 33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,40,41,41,42,42,43 dt 43,44,44,45,45,46,46,46,47,47,48,48,49,49,50,50,50,51,51,52,52 dt 53,53,53,54,54,55,55,56,56,56,57,57,58,58,58,59,59,60,60,60,61 dt 61,62,62,62,63,63,64,64,64,65,65,66,66,66,67,67,67,68,68,69,69 dt 69,70,70,70,71,71,72,72,72,73,73,73,74,74,74,75,75,75,76,76,77 dt 77,77,78,78,78,79,79,79,80,80,80,81,81,81,81,82,82,82,83,83,83 dt 84,84,84,85,85,85,86,86,86,86,87,87,87,88,88,88,89,89,89,89,90 dt 90,90,91,91,91,91,92,92,92,92,93,93,93,94,94,94,94,95,95,95,95 dt 96,96,96,96,97,97,97,97,98,98,98,98,99,99,99,99,99,00,00,00,00 dt 00,01,01,01 org H'300' temptable2: addwf PCL, f dt 7,2,7,2,7,2,6,1,6,1,5,0,5,0,4,9,4,8,3,8,2,7,1,6,1,5,0,4 dt 9,3,8,2,6,1,5,0,4,8,3,7,2,6,0,4,9,3,7,1,6,0,4,8,2,7,1,5 dt 9,3,7,1,5,9,3,7,1,5,9,3,7,1,5,9,3,7,0,4,8,2,6,9,3,7,1,4 dt 8,2,6,9,3,7,0,4,4,7,1,5,8,2,5,9,2,6,9,3,6,0,3,6,0,3,7,0 dt 3,7,0,3,6,0,3,6,9,3,6,9,2,5,8,2,5,8,1,4,7,0,3,6,9,2,5,8 dt 1,4,7,0,3,5,8,1,4,7,0,2,5,8,1,3,6,9,2,4,7,0,2,5,7,0,3,5 dt 8,0,3,5,8,0,3,5,8,0,3,5,7,0,2,4,7,9,1,4,6,8,0,3,5 endInterested:
Questions:
hi i have a similar task to do but with a pic18f452. i also need to send the data to the usart. however, the usart only accepts a maximum of 9 bits. what do i do? safrazali51@yahoo.comJames Newton of James Newton's Massmind replies: After sending the first 9 bits, send another 9? Actually, people usually send 8 bits at a time.
Could this be used for high temps, say 2000-2500 degrees F? What types of areas would I need to look into? Could I substitute a thermocouple for a thermistor? Calibrate it with a Dickson B2500 thermometor?
btw this temperature sensor uses 3 AA batteries? and wats the line symbol stand for between the two 34p capacitors and a thermositor can be esily get? got any component no. for me? sorri i'm a newbie in electronics..
lets say i use this thermositor has the temperature sensor but i want to add on a ventilation system, as in when it hits 60 degree it will turn on the fan n buzzer and when it drop to 59 it will turn it off again so how are u suppose to connect it to the circuit and write the code it has been puzzling me for weeks.. pls help
Comments:
I also need to send data from the pic to the lcd but i need to use c language. any ideas on how to convert from binary to ascii using c language i tried the atoi function but it does not workJames Newton of Massmind replies: Try sprintf().