PDA

View Full Version : Hysteresis.. How to do it??



hoopstar
- 9th March 2007, 12:36
First up I am extremely new to PICs and PICBasic and am reading and experimenting a LOT trying to fast track to an ulitmate project. As a result, I am breaking the "big picture" down into little pieces and trying to work out as much as I can myself - so please know that I *really* have tried to nut this one out..!!!!!

I am using a 16F877 that measures a variable resistor/voltage divider (with the bigger picture being to measure a thermistor) and depending on a user set variables.. switch a LED on or off..

The thing I need/want to do is have the LED switch on at say 100 degrees and then switch off only when the temperature drops below 80 degrees... I believe this is called Hysteresis..??!!?

But I am stumped at how to do this..?

I've tried using the following:

IF temp >= 100 THEN GOSUB ledon
IF temp <= 80 THEN GOSUB ledoff



Can anyone shed any light on this..??

Thanks


Hoops

markedwards
- 9th March 2007, 15:19
Hoops,

Your example should work fine. I have used similar code and it works great. I have controlled temp with 1 to 3 degrees F hysteresis in harsh/noisy environments. You could use the ADC equivalent for 100F and 80F and skip linearizing the thermistor. I use 10k resistor/10K thermistor/.1uF cap and Darrel Taylor's excellent averaging routine
http://www.picbasic.co.uk/forum/showpost.php?p=13267&postcount=5.

Mark

hoopstar
- 10th March 2007, 00:13
Thanks for the reply Mark

The problem with my code is that as soon as the input falls below the upper temperature setting, it switches off... :(

Rather I want it to wait until it falls below the lower setting - here is my full code - maybe that will explain things.


Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
TRISA = %00001011
trisd = %00000000
temp var byte 'temp variable
ADCON1 = 4 ' Set PortA 0, 1, 3 to A/D inputs
Low PORTE.2 ' LCD R/W line low (W)
Pause 100 ' Wait for LCD to start
mainloop:
ADCON0 = $41 ' Set A/D to Fosc/8, Channel 0, On
Pauseus 50 ' Wait for channel to setup
ADCON0.2 = 1 ' Start conversion
Pauseus 50 ' Wait for conversion
temp = ADRESH ' ADC output address = Temp
Lcdout $fe, 1, "Water Temp = ", #temp,"'F" ' Send to LCD
if temp >= 80 then gosub fan1on ' fan ON at 80
If temp <> 70 then gosub fan1off ' fan OFF at 70
Pause 100 ' Sample 10 times a second
Goto mainloop ' Repeat
End

Return
fan1on
portd.0 = 1
lcdout $fe,$94, "Fan 1 ON"
return
fan1off
portd.0 = 0
return


I hope you can help..

Can't wait until I can afford the full PicBasic and then I can get stuck into putting this all together - being a broke student sucks.


Hoops

skimask
- 10th March 2007, 00:27
[QUOTE=hoopstar;34279]

if temp >= 80 then gosub fan1on ' fan ON at 80
If temp <> 70 then gosub fan1off ' fan OFF at 70


Look at your original code...it doesn't make any sense.
If the temp is above 80, the fan kicks on...BUT...
if the temp is anything EXCEPT 70, the fan kicks off...

Change it to:
if temp => 80 then gosub fan1on
if temp <= 70 then gosub fan1off

Which is basically what you had in the first place. But I think you are sampling far too often. And I'd also throw a counter in there somewhere...something like if the temp is below 70 and you've checked XX number of times, then turn the fan off. (same thing with fan on). That way it'll keep from clicking on and off too often when the temp is right at the switch point.

mackrackit
- 10th March 2007, 19:32
I think the answer to you problem would be to make fan1on a loop not a return.

Stay in that loop until the temp drops below the set point.

Move the ADC commands to a GOSUB and then you can sample from anywhere and have less code.

This example is using two probes on a 18F4320.

CHECK:
T1 = temp1*2
T2 = temp2*2
LCDOUT $FE,1,"INSIDE ",#T1
lcdout $FE,$C0,"OUTSIDE ",#T2
gosub getT1
gosub getT2
if T1 > T2 + 10 then BLINK
goto CHECK

BLINK:
LCDOUT $FE,1,"INSIDE ",#T1
lcdout $FE,$C0,"OUTSIDE ",#T2
high PORTD.0
LOW PORTD.1
pause 100
low PORTD.0
HIGH PORTD.1
pause 100
if T1 = T2 THEN DARK
gosub getT1
gosub getT2
goto BLINK

DARK:
low PORTD.0
LOW PORTD.1
goto CHECK
getT1:
ADCON0=$1 '%00000001 AN0
gosub getAD
temp1 = ADRESH
return

getT2:
ADCON0=$5 '%00000101 AN1
gosub getAD
temp2 = ADRESH
return

getAD:
pause 50
ADCON0.1 = 1
pause 50
return

end

Ioannis
- 12th March 2007, 06:49
Also you could use a variable as a hysterisis.

hyst_high var byte
hyst_low var byte

hyst_low=0
hyst_high=0

....
....

if temp >= 80+hyst_high then gosub fan1on ' fan ON at 80
if temp <= 70+hyst_low then gosub fan1off


fan1on:
hyst_high=5
hyst_low=0
...
...
return

fan10ff:
hyst_low=5
hyst_high=0
...
...
return

Ioannis

Acetronics2
- 12th March 2007, 09:14
You could use the ADC equivalent for 100F and 80F and skip linearizing the thermistor.
Mark

Hi, Mark

I Read somewhere a ( very ... ) simple Thermistor linearization was to parallel the Thermistor a resistor of the same nominal value ...

I didn't try, but Worth the test ... no ???

Alain

hoopstar
- 13th March 2007, 00:35
I think the answer to you problem would be to make fan1on a loop not a return.

Stay in that loop until the temp drops below the set point.

Move the ADC commands to a GOSUB and then you can sample from anywhere and have less code.

I do plan on using GOSUB's but at the moment I am using the demo version of PicBasic and can't really afford to step up to Pro (poor student) so am just qualifying my code/ideas within the line limit of the demo version.

I *really* appreciate all the help and input on this - thanks guys.


Hoops