PDA

View Full Version : Need help with LM34 and 12F675



polymer52
- 2nd December 2009, 00:16
I'm trying to build a fan controller for a solar heater that I built but I can't seem to get it to work. I've tried everything I can think of and now I need help.
Yes probably that kind too. I was sane before I started this.
I'm using an LM34 temperature sensor which outputs 10mv/deg F from 5F (50mv) to 300F (3000mv) and a 12F675.
Attached is a text file with the code and it is also listed below.
Any help would be appreciated. I'm trying to make it come on at 115F and go off at 80F, settable in a constant at the beginning of the code. Later I want to add PWM for servo operated dampers.
Any help will be appreciated.



'Modified from file found at Renolds Electronics
'http://www.rentron.com/PIC12C67XAD.htm
'LM34
'PIN NAME Purpose
' 1 VDD +5v
' 2 Output 10mv/degF, +5° to +300°F = 50mv-3000mv
' 3 VSS GND
'
'PIC12F675
' PIN NAME Purpose
' 1 VDD +5v
' 8 VSS GND
' 5 GPIO.2 PWM out to servo
' 6 GPIO.1 Output to NPN transistor sinking relay.
' 7 GPIO.0 A/D input from center leg of LM34
'******************* Fuses, Defines, Variables & Constants ******************
@ device pic12F675, intrc_osc_noclkout, wdt_off, pwrt_on, mclr_off, bod_off, protect_off
define OSC 4 'Use 4mhz osc
CMCON=7 '(%00000111) Turn off analog comparators
TRISIO=%001001 '(Dec 9)Port direction register. 1=input, 0=output Note TRISIO.3 is always an input.
RESULT VAR BYTE 'A/D CONVERSION RESULT STORAGE BYTE
ADCON1=6 '(%00000110) SET GP.0 TO ANALOG INPUT, Vref = Vdd, ALL ELSE = DIGITAL I/O
HighTemp var byte 'High temperature setpoint
LowTemp Var byte 'Low temperature setpoint
Relay var GPIO.1 'Output pin tp transistor
'PWMOut var GPIO.2 'Pin 5 used to drive damper servos 'To be implemented later
HighTemp = 115 'Relay turn on Temp
LowTemp = 80 'Relay turn off temp
'************************ Main ************************
MAIN:
GOSUB GETVAL 'SETUP A/D
pause 500 'Wait 500ms
gosub Setrelay 'Turn on or off relay
pause 500
GOTO MAIN 'Start over
'************************
GETRESULT:
PAUSEUS 50 'WAIT FOR A/D CHANNEL SETUP (50 uS)
ADCON0.2 = 1 'START CONVERSION BY SETTING GO/DONE-BIT (HIGH)
'************************
LOOP: 'WAIT FOR GO/DONE BIT TO BE CLEARED
IF ADCON0.2=1 THEN 'CHECK GO/DONE BIT (0=DONE)
GOTO LOOP 'NOT FINISHED CONVERTING, THEN LOOP UNTIL DONE
ENDIF 'IF STATEMENT SATISFIED, ADCON0.2 = 0 (DONE)
RETURN 'FINISHED CONVERSION, RETURN TO GETVAL ROUTINE
'************************
GETVAL:
ADCON0=%10000001 'SET A/D Fosc/32,[4MHz], CHANNEL-0 = ON
GOSUB GETRESULT 'START THE CONVERSION
RESULT = ADRES 'STORE THE A/D CONVERSION VALUE IN RESULT
RETURN 'RETURN TO MAIN ROUTINE, START OVER
END
'************************
SetRelay: 'Turn on or off relay with hysterisis
select case RESULT
case RESULT <= lowTemp
low relay
'PWM GPIO.2, 127, 100 'Need 1ms wide pulse at about 40-50 per second. To be implemented later
case RESULT > LowTemp and Temp > HighTemp
low Relay
'PWM GPIO.2, 25, 100 'Need 1ms wide pulse at about 40-50 per second. To be implemented later
end select
'PWM GPIO.2, 127, 100 'Send 50% (127) duty cycle pwm signal out pin 5 for 100 cycles
return
END

mackrackit
- 2nd December 2009, 00:40
To start with, your PIC does not have a ADCON1
It works more like this.
http://www.picbasic.co.uk/forum/showthread.php?t=11947

polymer52
- 2nd December 2009, 01:37
To start with, your PIC does not have a ADCON1
It works more like this.
http://www.picbasic.co.uk/forum/showthread.php?t=11947

Still not sure I understand. My brain hurts at this point.
Ok Should be ADCON0=%00000101?
I may need to sleep on this and try again tomorrow.
The data sheet has me confused.

aratti
- 2nd December 2009, 07:40
Cancelled

Al.

mackrackit
- 2nd December 2009, 23:34
Maybe this will get you going with the ADC on this chip. Seems like MicroChip likes to keep folks guessing by changing some things around for different chips.

This will display the 8 bit ADC reading on a terminal.


<font color="#000080"><i>'12F675 ADC TEST FOR CHANNEL 0
</i></font><font color="#FF0000"><b>DEFINE </b></font><font color="#0000FF"><b>OSC </b></font><font color="#800000"><b>4
</b></font>@ <font color="#0000FF"><b>__config _INTRC_OSC_NOCLKOUT </b></font>&amp; <font color="#0000FF"><b>_WDT_ON </b></font>&amp; <font color="#0000FF"><b>_MCLRE_OFF </b></font>&amp; <font color="#0000FF"><b>_CP_OFF
ANSEL</b></font>=<font color="#800000"><b>%00000001 </b></font>:<font color="#0000FF"><b>CMCON</b></font>=<font color="#800000"><b>7 </b></font>:<font color="#0000FF"><b>TRISIO </b></font>= <font color="#800000"><b>%001001
</b></font><font color="#0000FF"><b>RESULT </b></font><font color="#FF0000"><b>VAR BYTE</b></font> <font color="#000080"><i>'A/D CONVERSION RESULT STORAGE BYTE

</i></font><font color="#0000FF"><b>START</b></font>: <font color="#000080"><i>'A HEART BEAT
</i></font><font color="#0000FF"><b>GPIO </b></font>= <font color="#800000"><b>%010000</b></font>:<font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>500</b></font>:<font color="#0000FF"><b>GPIO </b></font>= <font color="#800000"><b>%000000</b></font>:<font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>500
</b></font><font color="#FF0000"><b>SEROUT2 </b></font><font color="#0000FF"><b>GPIO</b></font>.<font color="#800000"><b>5</b></font>, <font color="#800000"><b>16780</b></font>, [<b><i>&quot;RESULT &quot;</i></b>,<font color="#FF0000"><b>DEC </b></font><font color="#0000FF"><b>RESULT</b></font>,<font color="#800000"><b>$a</b></font>,<font color="#800000"><b>$d</b></font>]
<font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>50
</b></font><font color="#FF0000"><b>GOSUB </b></font><font color="#0000FF"><b>ADC_0 </b></font><font color="#000080"><i>'STARTS THE READING OF ADC CHANNEL 0
</i></font><font color="#FF0000"><b>GOTO </b></font><font color="#0000FF"><b>START

ADC_0</b></font>: <font color="#000080"><i>'READ AN0
</i></font><font color="#0000FF"><b>ADCON0 </b></font>= <font color="#800000"><b>%00000001 </b></font><font color="#000080"><i>'TURNS ADC ON
</i></font><font color="#FF0000"><b>GOSUB </b></font><font color="#0000FF"><b>READ_AD
RESULT </b></font>= <font color="#0000FF"><b>ADRESH </b></font><font color="#000080"><i>'PLACES THE ADC VALUE INTO VAR
</i></font><font color="#FF0000"><b>RETURN

</b></font><font color="#0000FF"><b>READ_AD</b></font>: <font color="#000080"><i>'DOES THE ADC CONVERSION
</i></font><font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>50
</b></font><font color="#0000FF"><b>ADCON0</b></font>.<font color="#800000"><b>1</b></font>=<font color="#800000"><b>1
</b></font><font color="#FF0000"><b>WHILE </b></font><font color="#0000FF"><b>ADCON0</b></font>.<font color="#800000"><b>1</b></font>=<font color="#800000"><b>1</b></font>:<font color="#FF0000"><b>WEND
RETURN
</b></font>

polymer52
- 3rd December 2009, 00:00
Maybe this will get you going with the ADC on this chip. Seems like MicroChip likes to keep folks guessing by changing some things around for different chips.
This will display the 8 bit ADC reading on a terminal.


Thanks I'll try it tomorrow. I just needed to get away from it for awhile.
I started over from scratch this morning and finally got it working. Only thing is that it reads exactly half the temperature (input voltage from the LM34). I multiplied it by 2 in the software to fix the problem but I don't know why it does that. Is there a calibration for the A/D?
Anyway here is my final working code for anyone interested. It could probably be optimized but it ain't broke so I ain't gonna fix it.

I built this to control a solar heater (see it on my web site). It basically reads the voltage from the LM34 on GPIO.0 10mv per deg F and
turns on a fan relay on GPIO.1 when the temperature goes above the preset temp (110F) and outputs a PWM signal on GPIO.2 to open a damper door.
Below the preset low temperature (90F) it turns off the fan and again sends out a PWM signal to close the damper. I still need to tweak pulse widths for the servo. I just set them up to make sure the PWM works.
It also sends out the current temperature and preset info on GPIO.4 to a PC terminal if needed using the debug command.
Hope someone else can use the info and thanks to Bruce for making the basics available.



'Modified from file found at Renolds Electronics
'http://www.rentron.com/PIC12C67XAD.htm
'LM34 F temperature sensor
'PIN NAME Purpose
' 1 VDD +5v
' 2 Output 10mv/degF, +5° to +300°F = 50mv-3000mv
' 3 VSS GND
'
'PIC12F675
' PIN NAME Purpose
' 1 VDD +5v
' 8 VSS GND
' 3 GPIO.4 Serial out for debug
' 5 GPIO.2 PWM out to servo
' 6 GPIO.1 Output to NPN transistor sinking relay.
' 7 GPIO.0 A/D input from center leg of LM34
'********************************* Fuses ******************************
@ device pic12F675, intrc_osc_noclkout, wdt_off, pwrt_on, mclr_off, bod_off, protect_off
'********************************* Setup *******************************
DEFINE debug_mode 1 '0=True, 1=Inverted serial data
DEFINE debug_bit 4 'sends serial data out GPIO.4 at N,8,1
DEFINE debug_baud 2400 'Default baud rate = 2400
DEFINE osc 4 'We're using a 4 MHz oscillator
Define OSCCAL_1K 1 'Set OSCCAL for 1K device
DEFINE ADC_BITS 8 'Set A/D for 8-bit operation
DEFINE ADC_SAMPLEUS 50 'Set A/D sampling time @ 50 uS
CMCON=7 '(%00000111) Turn off analog comparators
TRISIO=%001001 'Port direction register. GPIO.0 & GPIO.3 =inputs (.3 is always input)
ADCON0=%00000000 'Left justified,Vref = Vdd,GP.0=ANALOG INPUT
ANSEL=%01010001 'FOSC=16=101,GPIO.0=analog
Samples VAR WORD ' Multiple A/D sample accumulator
Sample VAR BYTE ' Holds number of Samples to take
Temp VAR BYTE ' Temperature storage
PWMPin var GPIO.2 'Variable for PWM output
Relay var GPIO.1 'Variable for relay output
'LowTemp var byte
'HighTemp var byte
LowTemp con 90 'Turn off relay
HighTemp con 110 'Turn on relay
Samples = 0 ' Clear Samples accumulator on power-up
PAUSE 500 ' Wait .5 second
'********************************* Main ********************************
loop:
FOR sample = 1 TO 20 ' Take 20 Samples
ADCIN 0, temp ' Read channel 0 into temp variable
Samples = Samples + temp ' Accumulate 20 Samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
NEXT sample
temp = Samples/20*2
if temp >lowtemp and temp>hightemp then gosub onrelay
if temp <=lowtemp then gosub offrelay
DEBUG "Current Temp: ",DEC temp," Low Turn Off: ",dec lowtemp," High Turn On: ",dec hightemp,10,13
Samples = 0 ' Clear old sample accumulator
GOTO loop ' Do it forever
END
'******************************* Output **********************************
OnRelay:
high relay 'Turns on GPIO.1
PWM PWMPin, 127, 500 '50% duty cycle for 500 cycles on GPIO.2
return
OffRelay:
low relay 'Turns off GPIO.1
PWM PWMPin, 64, 500 '25% duty cycle for 500 cycles on GPIO.2
return

mackrackit
- 3rd December 2009, 00:20
That is the way the LM34 is when running on 5 volts. Figure the steps in 8 bit and all that.

If you want a 1 degree resolution set up the VREF and have the reference voltage at 3.3 volts.

Then in place of multiplying by 2
you would use
ADC_VAR * 4 / 3

At least that works for me :)

Glad you got it going.

polymer52
- 3rd December 2009, 02:23
That is the way the LM34 is when running on 5 volts. Figure the steps in 8 bit and all that.
If you want a 1 degree resolution set up the VREF and have the reference voltage at 3.3 volts.
Then in place of multiplying by 2
you would use
ADC_VAR * 4 / 3
At least that works for me :)
Glad you got it going.

Thanks for the tip. I'll have to try to find a 3.3v reference tomorrow. I have some 1.25's but that's a little shy.
The LM34 is doing what it's supposed to. It is putting out .700v at 70 degrees but the pic reads it as .350v.
Thanks..

malc-c
- 6th December 2009, 11:30
Interesting thread, and quite by chance similar to a project I was contemplating.

I was thinking of making my own pulse proportional thermostat for use with reptile enclosures. Your code could be the ideal starting point for me, thanks for sharing

polymer52
- 6th December 2009, 12:22
Interesting thread, and quite by chance similar to a project I was contemplating.
I was thinking of making my own pulse proportional thermostat for use with reptile enclosures. Your code could be the ideal starting point for me, thanks for sharing

I've made a couple of changes since I posted that. I'm using the plusout command instead of the PWM command. There is better control with the pulsout command.
I've also added an external thermostat to turn it off. Man does it get hot!
GPIO.1 is pulled low through a 10k then goes to VDD through a wall thermostat.
Here is the final working code:

'LM34 F temperature sensor
'PIN NAME Purpose
' 1 VDD +5v
' 2 Output 10mv/degF, +5° to +300°F = 50mv-3000mv
' 3 VSS GND
'
'PIC12F675
' PIN NAME Purpose
' 1 VDD +5v VDD
' 2 GPIO.5 Serial out for debug
' 3 GPIO.4 PWM out to servo
' 4 GPIO.3 ***Programmer VPP
' 5 GPIO.2 Output to NPN transistor sinking relay.
' 6 GPIO.1 Input from thermostat /***Programmer Clk
' 7 GPIO.0 Analog input from center leg of LM34 /***Programmer Data
' 8 VSS GND VSS
'********************************* Fuses ******************************
@ device pic12F675, intrc_osc_noclkout, wdt_off, pwrt_on, mclr_off, bod_off, protect_off
'********************************* Setup *******************************
DEFINE debug_mode 1 '0=True, 1=Inverted serial data
DEFINE debug_bit 5 'sends serial data out GPIO.5 at N,8,1
DEFINE debug_baud 2400 'Default baud rate = 2400
DEFINE osc 4 'We're using a 4 MHz oscillator
Define OSCCAL_1K 1 'Set OSCCAL for 1K device
DEFINE ADC_BITS 8 'Set A/D for 8-bit operation
DEFINE ADC_SAMPLEUS 50 'Set A/D sampling time @ 50 uS
CMCON=7 '(%00000111) Turn off analog comparators
TRISIO=%00001011 '001001 Port direction register. GPIO.0 & GPIO.3 =inputs (.3 is always input)
ADCON0=%00000000 '00000000 Left justified,Vref=VDD,GP.0=ANALOG INPUT
ANSEL=%01010001 '01010001 FOSC=16=101,GPIO.0=analog
Samples VAR WORD 'Multiple A/D sample accumulator
Sample VAR BYTE 'Holds number of Samples to take
Temp VAR BYTE 'Temperature storage
Thermostat var bit 'Input from thermostat
Relay var GPIO.2 'Variable for relay output
LowTemp con 90 'Turn off relay
HighTemp con 110 'Turn on relay
Samples = 0 'Clear Samples accumulator on power-up
'****************************** Servo Stuff ****************************
Servo var GPIO.4 'Variable for PWM output
low servo 'Initilize GPIO.4 to low
Accum var byte 'GP Accumulator variable
AccLow con 100 'Accumulator Min pulse (move CCW)
AccHigh con 250 'Accumulator Max pulse (Move Cw)
Wait1 con 20 'Delay before repeating loop
Flag var bit 'Holds bit for servo position
flag=0 'initilize flag
PAUSE 500 'Wait .5 second
'********************************* Main ********************************
Main:
FOR sample = 1 TO 20 ' Take 20 Samples
ADCIN 0, temp ' Read channel 0 into temp variable
Samples = Samples + temp ' Accumulate 20 Samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
NEXT sample
temp = Samples/20*2
if temp >lowtemp and temp>hightemp and thermostat=1 then gosub onrelay
if temp <=lowtemp then gosub offrelay
DEBUG "Curr Temp: ",DEC temp,"° F ",10,13,10,13," Off Temp: ",dec lowtemp,"° F "," On Temp: ",dec hightemp,"° F ",10,13
DEBUG "CCW Pulse Width: ",dec Acclow,"ms ", "CW Pulse Width: ",dec Acchigh,",ms ", "Flag: ",dec flag,10,13
Samples = 0 ' Clear old sample accumulator
GOTO main ' Do it forever
END
'******************************* Output **********************************
OnRelay:
high relay 'Turns on GPIO.1
if flag=0 then gosub VentOpen 'If vent is closed then open it.
return
OffRelay:
low relay 'Turns off GPIO.1
if flag=1 then gosub VentClosed 'if vent is open then close it.
return
'**************************** Open Damper ********************************
'@@@@@@@@@ SWAP LINES 75 & 76 AND LINES 84 & 85 TO REVERSE ROTATION @@@@@@@@@@@@
VentOpen:
for Accum=acchigh to acclow step -1 'Move servo 90 deg CW
'for Accum=Acclow to acchigh 'Move servo 90 deg CCW
pulsout servo, Accum
pause Wait1
next
flag=1 'Set Flag to tell when open
return
'**************************** Close Damper *******************************
VentClosed:
for Accum=Acclow to acchigh 'Move servo 90 deg CCW
'for Accum=acchigh to acclow step -1 'Move servo 90 deg CW
pulsout servo, Accum
pause Wait1
next
flag=0 'Set Flag to tell when closed
return

Acetronics2
- 6th December 2009, 13:06
Interesting thread, and quite by chance similar to a project I was contemplating.

I was thinking of making my own pulse proportional thermostat for use with reptile enclosures. Your code could be the ideal starting point for me, thanks for sharing

Hi, Malc

I think there's something for you here ...

http://www.parallax.com/Portals/0/Downloads/docs/books/edu/ic.pdf

have a nice time ...

Alain