PDA

View Full Version : Use Button For setup



tump
- 12th November 2007, 22:39
Hello all,

I am new to the pic world as you can probably see from my code below, I have all of the code working except for the creating a changeable setpoint.
I am at my wits end with trying to figure this out, something tells me its a simple problem but my lack coding experience cant figure it out.
All help would be apreciated
Aslo please comment on my coding or lack of, if there is a way to make this code more efficient please let me know

'************************************************* ***************
'* Name : 2LM34_LCD.BAS *
'* Author : tump *
'* Date : 10/30/2007 *
'* Version : 1.00 *
'* Notes : 8-bit A/D temperature conversion with National *
'* ; LM34CAZ analog temperature sensor. *
'* : 2 sensor input *
'* : When sensor 0 is higher than sensor 1 *
'* : Fire PortC.2 *
'* written for easy pic4 development board *
'************************************************* ***************
@ DEVICE PIC16F877A,HS_OSC
DEFINE debug_mode 0 ' Debug sending True serial data
DEFINE debug_reg portc ' Debug Port = PortC
DEFINE debug_bit 6 ' Debug.bit = PortC.6
DEFINE debug_baud 9600 ' Default baud rate = 9600
DEFINE osc 8 ' We're using a X MHz oscillator
DEFINE ADC_BITS 8 ' Set A/D for 8-bit operation
DEFINE ADC_CLOCK 3 ' Set A/D clock r/c
DEFINE ADC_SAMPLEUS 50 ' Set A/D sampling time @ 50 uS
Define LCD_DREG PORTD ' Define LCD pins
Define LCD_DBIT 4 'use upper 4 bits d4-d7
Define LCD_RSREG PORTD
Define LCD_RSBIT 2
Define LCD_EREG PORTD
Define LCD_EBIT 3
DEFINE LCD_LINES 2
Define LCD_COMMANDUS 2000 ' Command Delay (uS)
Define LCD_DATAUS 50 ' Data Delay (uS)
Fan VAR PortC.2
Idle Var PortC.3
Incr VAR portc.4 ' Increment button
Setup VAR portc.5 ' SetUp button
Season VAR PORTB.1 ' 1=summer 0=winter
AtticSamples VAR WORD ' Multiple A/D sample accumulator
AtticSample VAR BYTE ' Holds number of samples to take
GarageSamples VAR WORD ' Multiple A/D sample accumulator
GarageSample VAR BYTE ' Holds number of samples to take
AtticTemp VAR BYTE ' Attic Temperature storage
GarageTemp VAR Byte ' Garage Temperature Storage
Hysterisis VAR BYTE ' Hysterisis
SetPoint VAR BYTE ' Temperature Setpoint

SetPoint = 70
AtticSamples = 0 ' Clear samples accumulator on power-up
GarageSamples = 0 ' Clear samples accumulator on power-up
Hysterisis = 2
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00000011 ' Set PORTA.0,1,2,5 = A/D, PortA.3 = +Vref
TRISC.2 = 0

PAUSE 500 ' Wait .5 second

powerup:
pause 500
DEBUG "P",10,13
LCDOUT $fe, 1, "Heat Circulator"
LCDOUT $fe, $C0, " By Tump"
DEBUG "PowerUp",10,13


loop:
if Setup = 1 then
pause 200
goto SetSetPoint
endif

Toggle Idle
FOR Atticsample = 1 TO 20 ' Take 20 samples
ADCIN 0, AtticTemp ' Read channel 0 into AtticTemp variable
Atticsamples = Atticsamples + Attictemp ' Accumulate 20 samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
Toggle Idle
NEXT Atticsample
Attictemp = Atticsamples/20
Toggle Idle

FOR Garagesample = 1 TO 20 ' Take 20 samples
ADCIN 1, Garagetemp ' Read channel 1 into GarageTemp variable
Garagesamples = Garagesamples + Garagetemp ' Accumulate 20 samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
Toggle Idle
NEXT Garagesample
Garagetemp = Garagesamples/20
Toggle Idle
Pause 100 ' Do it about 10 times a second

; If Garagetemp >= 70 then GOSUB TempOK
If Season=0 THEN goSUB Winter
If SEASON=1 THEN goSUb Summer


TempOK:
'************************************************* ****************************
'** If temperature in garage is greater than or equal to SetPoint turn off ***
'** circulator fan ***
'************************************************* ****************************

LCDOUT $fe, 1, "CirculatorOff ", #AtticTemp,"F" ' Send to LCD Line 1
Lcdout $fe, $C0, "GarageTemp >= 70", #GarageTemp,"F" 'Send to LCD Line 2
Fan = 0
DEBUG "OK,","G",#GarageTemp,".","A",#AtticTemp,10,13
Atticsamples = 0 ' Clear old sample accumulator
Garagesamples = 0 ' Clear old sample accumulator
pause 500
goto loop

Winter:
' if attic temp is greater than garage temp turn on ciculator fan
If GarageTemp >= SetPoint then
goto TempOK
ENDIF

If AtticTemp > GarageTemp + Hysterisis Then
Fan = 1
Else
Fan = 0 'Turn OFF Fan Output
endif

GOTO Messages ' Do it forever

Summer:
' if attic temp is less than garage temp turn on circulator fan
If GarageTemp > SetPoint then
goto TempOK
ENDIF
If AtticTemp + Hysterisis < GarageTemp Then
Fan = 1
Else
Fan = 0
endif

GOTO Messages ' Do it forever

SetSetPoint:
if Incr = 1 then 'change the setpoint
pause 100
SetPoint=SetPoint+1
if Setpoint>80 then SetPoint=60 'Allow setpoint from 60 to 80
LCDOut $FE,1, "Setpoint at", #SetPoint, "F"
endif


Messages:
LCDOUT $fe, 1, "Attic=", #AtticTemp,"F", " ",#Season ' Send to LCD Line 1
Lcdout $fe, $C0, "Garage=", #GarageTemp,"F", " ",#Fan 'Send to LCD Line 2
DEBUG DEC AtticTemp,",", DEC GarageTemp,",",#fan,",",#Season,10,13
Atticsamples = 0 ' Clear old sample accumulator
Garagesamples = 0 ' Clear old sample accumulator
GOTO Loop
END

mister_e
- 12th November 2007, 23:03
I would probably suggest to use a button to exit this Setpoint mode, unless you'll need to do everything really fast... which is almost impossible.

Basically, just loop in Setpoint utill a specific button have been pressed Should work. Something like...


SetSetPoint:
LCDOut $FE,1, "Setpoint at", #SetPoint, "F"

if Incr = 1 then 'change the setpoint
pause 100
SetPoint=SetPoint+1
if Setpoint>80 then SetPoint=60 'Allow setpoint from 60 to 80
'
'
goto SetSetPoint ' Refresh LCD display
endif

If YourSpecificButton= NotPressed then goto SetSetPoint

tump
- 13th November 2007, 00:15
Okay I have it working now in ICD mode but not in real life I guess its a timing issue, how would I get into setup as soon as soon as the button is pressed and not having to wait until it is in the loop for setup mode.

mackrackit
- 13th November 2007, 22:57
Use an interrupt. Or inside of every loop have a GOSUB to check the button.

mister_e
- 14th November 2007, 00:16
To me a Timer interrupt is the most valuable and transparent solution.

tump
- 18th November 2007, 16:23
Thanks for the help and I have tried mister_e's suggestion about interrupts

I have tried with the on interrupt with odd results
the program goes into setup mode with the lcd flickering i guess it is due to the
goto setsetpoint to refresh the lcd .

the problem is it will never leave the loop when i press save ( 1 for active 0 inactive)

I noticed by mistake the if i hold down save the program runs again as soon as i let go it stops, I want the save save to be pressed once and resume running the program.

I am guessing that I made an error in the code below but it compiles just fine.

Thanks in advance for any more help.

SetSetPoint:
DISABLE

LCDOut $FE,1, "Setpoint at", #SetPoint, "F"

if Incr = 1 then 'change the setpoint
pause 500
SetPoint=SetPoint+1
if Setpoint>80 then SetPoint=60 'Allow setpoint from 60 to 80

goto SetSetPoint 'refresh LCD with new setpoiont
endif

If Save = 0 then goto SetSetPoint

Resume
ENABLE

mackrackit
- 19th November 2007, 07:08
Try adding


IF Save = 1 then GOTO loop

before


If Save = 0 then goto SetSetPoint

tump
- 19th November 2007, 19:16
Thanks tried your suggestion but still not working.

When save = 1
I want it to exit the loop and resume running the program, am I missing something obvious, or not so obvious since I am new at this ???

mackrackit
- 19th November 2007, 19:24
Maybe it is a debounce problem. Add a "PAUSE" at the beginning of "loop".


loop:
PAUSE 250 'Give a little time to get off the button
if Setup = 1 then

tump
- 19th November 2007, 20:22
I am using an interrupt now I have pasted the whole code below in case i missed something with the interrupt.



@ DEVICE PIC16F877A,HS_OSC
DEFINE debug_mode 0 ' Debug sending True serial data
DEFINE debug_reg portc ' Debug Port = PortC
DEFINE debug_bit 6 ' Debug.bit = PortC.6
DEFINE debug_baud 9600 ' Default baud rate = 9600
DEFINE osc 8 ' We're using a X MHz oscillator
DEFINE ADC_BITS 8 ' Set A/D for 8-bit operation
DEFINE ADC_CLOCK 3 ' Set A/D clock r/c
DEFINE ADC_SAMPLEUS 50 ' Set A/D sampling time @ 50 uS
Define LCD_DREG PORTD ' Define LCD pins
Define LCD_DBIT 4 'use upper 4 bits d4-d7
Define LCD_RSREG PORTD
Define LCD_RSBIT 2
Define LCD_EREG PORTD
Define LCD_EBIT 3
DEFINE LCD_LINES 2
Define LCD_COMMANDUS 2000 ' Command Delay (uS)
Define LCD_DATAUS 50 ' Data Delay (uS)
Fan VAR PortC.2
Idle Var PortC.3
Save Var portc.1
Incr VAR portc.4 ' Increment button
Decr VAR portc.5 ' Decrement button
Season VAR PORTB.1 ' 1=summer 0=winter
AtticSamples VAR WORD ' Multiple A/D sample accumulator
AtticSample VAR BYTE ' Holds number of samples to take
GarageSamples VAR WORD ' Multiple A/D sample accumulator
GarageSample VAR BYTE ' Holds number of samples to take
AtticTemp VAR BYTE ' Attic Temperature storage
GarageTemp VAR Byte ' Garage Temperature Storage
Hysterisis VAR BYTE ' Hysterisis
SetPoint VAR BYTE ' Temperature Setpoint

SetPoint = 70
AtticSamples = 0 ' Clear samples accumulator on power-up
GarageSamples = 0 ' Clear samples accumulator on power-up
Hysterisis = 2
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %00000011 ' Set PORTA.0,1,2,5 = A/D, PortA.3 = +Vref
TRISC.2 = 0
intcon = %10010000 ' enable rbo interrupt
PAUSE 500 ' Wait .5 second

powerup:
on interrupt goto SetSetPoint
pause 500
DEBUG "P",10,13
LCDOUT $fe, 1, "Heat Circulator"
LCDOUT $fe, $C0, "By Sonic"
DEBUG "PowerUp",10,13


loop:

toggle Idle
FOR Atticsample = 1 TO 20 ' Take 20 samples
ADCIN 0, AtticTemp ' Read channel 0 into AtticTemp variable
Atticsamples = Atticsamples + Attictemp ' Accumulate 20 samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
Toggle Idle
NEXT Atticsample
Attictemp = Atticsamples/20
Toggle Idle

FOR Garagesample = 1 TO 20 ' Take 20 samples
ADCIN 1, Garagetemp ' Read channel 1 into GarageTemp variable
Garagesamples = Garagesamples + Garagetemp ' Accumulate 20 samples
PAUSE 250 ' Wait approximately 1/4 seconds per loop
Toggle Idle
NEXT Garagesample
Garagetemp = Garagesamples/20
Toggle Idle
Pause 100 ' Do it about 10 times a second

; If Garagetemp >= 70 then GOSUB TempOK
If Season=0 THEN goSUB Winter
If SEASON=1 THEN goSUb Summer


TempOK:
'************************************************* ****************************
'** If temperature in garage is greater than or equal to SetPoint turn off ***
'** circulator fan ***
'************************************************* ****************************

LCDOUT $fe, 1, "CirculatorOff ", #AtticTemp,"F" ' Send to LCD Line 1
Lcdout $fe, $C0, "GarageTemp >= ",#SetPoint, #GarageTemp,"F" 'Send to LCD Line 2
Fan = 0
DEBUG "OK,",#SetPoint,"'","G",#GarageTemp,".","A",#AtticTemp,10,13
Atticsamples = 0 ' Clear old sample accumulator
Garagesamples = 0 ' Clear old sample accumulator
pause 500
goto loop

Winter:
' if attic temp is greater than garage temp turn on ciculator fan
If GarageTemp >= SetPoint then
goto TempOK
ENDIF

If AtticTemp > GarageTemp + Hysterisis Then
Fan = 1
Else
Fan = 0 'Turn OFF Fan Output
endif

GOTO Messages ' Do it forever

Summer:
' if attic temp is less than garage temp turn on circulator fan
If GarageTemp > SetPoint then
goto TempOK
ENDIF
If AtticTemp + Hysterisis < GarageTemp Then
Fan = 1
Else
Fan = 0
endif

GOTO Messages ' Do it forever

SetSetPoint:
DISABLE

LCDOut $FE,1, "Setpoint at", #SetPoint, "F"

if Incr = 1 then 'change the setpoint
pause 500
SetPoint=SetPoint+1
if Setpoint>80 then SetPoint=60 'Allow setpoint from 60 to 80
goto SetSetPoint 'refresh LCD with new setpoiont
endif

If Save = 0 then goto SetSetPoint

LCDOut $FE,$C0, "Saved Setpoint", #SetPoint, "F"
Resume
ENABLE
goto loop

Messages:
LCDOUT $fe, 1, "Attic=", #AtticTemp,"F", " ",#Season ' Send to LCD Line 1
Lcdout $fe, $C0, "Garage=", #GarageTemp,"F", " ",#Fan 'Send to LCD Line 2
DEBUG DEC AtticTemp,",", DEC GarageTemp,",",#fan,",",#Season,10,13
Atticsamples = 0 ' Clear old sample accumulator
Garagesamples = 0 ' Clear old sample accumulator
GOTO Loop
END

mister_e
- 19th November 2007, 21:53
Rule #1: Keep Interrupt Service Routine as short as possible. in your ISR you don't want to use stuff like LCDOUT of spin inside 'till something happen. You check what you have to check, you set some variable/flags, and you get-out of there. In your main loop, or elsewhere, you wait and waste all time you want, as long as it's not going to messed the timer interrupt... unless you want to use Darrel's instant interrupts OR asm interrupts.

tump
- 19th November 2007, 22:16
Thanks for the info, but this is the only way I can figure to get this done, I am having a hard enough time the basic way never mind asm interupts (I have not a clue on where to begin).

Does this mean that this will not work due to the LCDout or did I make an error in writing the code.

I dont know of any other way to do this, so If any one can give me a code example that would be greatly appreciated.

mister_e
- 19th November 2007, 23:41
Before the RESUME, try to clear the interrupt flag unless it will just get out of the ISR, then return there over and over....

INTCON.1=0

Maybe you'll need to implement some switch debouncing as well.

tump
- 21st November 2007, 18:51
thanks for the info it works great now.
But I have another question, why do I need to add this line I searched the manual and example and dont see INTCON used, did I do something wrong and this is a band aid ??

I am trying to learn from my mistakes that is why I am asking

mackrackit
- 21st November 2007, 19:43
Hi,

You will find INTCON in the data sheet, section 2.2.2.3.

INTCON.1=0 needs to be used, you have not done anything wrong. Basically this stops the interrupt and lets things continue.




I am trying to learn from my mistakes that is why I am asking

That is why this forum is so useful, we learn from each others mistakes:)