PDA

View Full Version : Noob needs some help please...



Neosec
- 12th April 2013, 18:27
I have three page boundary warning, but I read in another post that PBP takes care of these. The main loop runs and check for button presses and counts up the lcd_info variable but it never branches (like it used to last week) to the LCD display routines. When I run it the LCD loops... "Main Loop" then "LCD Info" X up to 6 then repeats. Why isn't it branching to the LCD display section? What am I missing?
This is my first project with PICs and PBP other than what I was doing earlier with a DS1821...
I've loaded this into both a 16F886 and 887 and run it on both an EASYPIC3 dev board as well as a breadboard, and with battery and USB power. Results are the same with all configuration, so I'm pretty sure it's in the code somewhere. After two days of looking and commenting out bits of code here and there I don't know where else to look. I probably can't see what's right in front of me. Hope someone else can.
:confused:
Thanks

Edit: Using melabs U2 Programmer to program the MCU; set MCU to 16F887 (or 886 as I switch back and fourth), Oscillator to XT, all other fuses to default.



' PIC 16f886 (28 pin)

' Connections:
' --------------------
' LCD:
'
' PORTB.2 ' LCD RS bit
' PORTB.3 ' LCD Enable Bit
' PORTB.4 ' LCD Data
' PORTB.5 ' LCD Data
' PORTB.6 ' LCD Data
' PORTB.7 ' LCD Data
' PORTC.1 ' LCD Backlight (20mA)
' PORTC.2 ' LCD Power Vdd +5V ~1.5mA
' ------------------------
' ' Buttons:
' PORTC.3 ' Enter / Confirm / Run Up / increase
' PORTC.4 ' Forward
' PORTC.5 ' Back
' PORTC.6 ' Down / decrease
' PORTC.7 ' Up / increase
' ----------------------------
' ' Solar Charge Control:
' PORTC.0 ' To depletion mode MOSFET in series with Solar panel & Battery pack
' -----------------------------
' ' Solar Energy Detect:
' PORTA.2 ' ADC or Input to determine if Solar panel is producting power
' -----------------------------
' ' Battery Level:
' PORTA.3 ' ADC Monitor battery level (state of charge / Charging)
' ---------------------------
' ' Oscillator:
' PORTA.6 ' 4 MHZ Xtal
' PORTA.7 ' 4 MHZ Xtal
' -----------------------------------
' ' Temperature Sensor
' PORTA.5 ' DS1821 Digital temperature sensor
' --------------------------------
'
' EEPROM Locations
' 0 = Alarm temperature set (trip) point
' 1 = Battery level for compare to current batt level to determine charging or not
' 2 = Daily High temperature
' 3 = Daily Low temperature
'
'
'
' CONSTANTS
sol_con con 500 ' Set point where Solar array has enough sun to set flag "sun_up"
'
' Define LCD pins
DEFINE LCD_DREG PORTB ' Sets LCD Data Port to Port-B instead of default Port A
DEFINE LCD_DBIT 4 ' Sets for use of PortB bits 4 thru 7 for the data
DEFINE LCD_RSREG PORTB ' Sets RS (Register Select) to Port B instead of default PortA.4
DEFINE LCD_RSBIT 2 ' Sets RS (Register Select) to bit 2 of port B (PORTB.2)
' ' Enable stays at the default PORTB.3
' Define oscillator
'
define OSC 4 ' Define Oscillator as 4 MHZ
'
' Define Variables
'
btn_up var PORTC.7 ' Momentary SPST push buttons for setting system options
btn_dwn var PORTC.6 ' Momentary SPST push buttons for setting system options
btn_back var PORTC.5 ' Momentary SPST push buttons for setting system options
btn_nxt var PORTC.4 ' Momentary SPST push buttons for setting system options
btn_entr var PORTC.3 ' Momentary SPST push buttons for setting system options
'
sun_lvl var word ' Holds solar energy level info from ADC 2
sun_up var bit ' Storage for sun is shining flag
sun_toggle var bit ' Toggle bit used for resetting daily Hi and Lo Temperatures
toggle_drag var bit ' Qualifier bit to drag toggle bit low with sun_up going low
batt_lvl var word ' Holds battery level info from ADC 3
batt_mem var byte ' Battery level written to memory after subtracting ~450 (indicates 0-100%)
batt_comp var bit ' Storage for flag when batt_lvl compared to batt_mem
charge var bit ' Storage for battery charging or discharging flag for LCD
chg_y_n var byte ' Holds charactor for LCD to display "Y" if charging "N" if not
solar_fet var PORTC.0 ' Solar array control ON / OFF (Depletion mode MOSFET)

'
lcd_lite var PORTC.1 ' LCD Backlight ON / OFF (~20 mA)
lcd_pwr var PORTC.2 ' LCD power down ON / OFF
'
tx_pwr var PORTA.0 ' Transmitter board power (5V into 3V reg.)
tx_alrm var PORTA.1 ' Transmitter - send alarm for low temperature condition
tx_tst var PORTA.4 ' Transmit / receive loop test
tx_confm var PORTB.0 ' Confirmation from receiver that transmitted data was received
tx_g_ng var bit ' Storage for transmit/receive go, no-go flag from tx_confm cycle
'
lcd_info var byte ' Index for which LCD Info to display on line two, 1-4...
' ' ...1=batt_lvl, 2=batt_chrg, 3=tx_g_ng, 4=alrm_set
m var byte ' Storage for mainloop counter
b var byte ' Storage for button set loop counter
counter1 var byte ' Storage for longer period counter 1
counter2 var byte ' Storage for longer period counter 2
'
' DS1821 digital temperature sensor
command var byte ' Storage for command
i var byte ' Storage for loop counter
temp var BYTE ' Storage for temperature
DQ var PORTA.5 ' Alias DS1821 data pin
DQ_DIR var TRISA.5 ' Alias DS1821 data direction pin
'
alrm_set var byte ' Store set point for alarm to trip at
day_hi var byte ' Storage for Daily High temperature EEPROM loc. 2
day_lo var byte ' Storage for Daily Low temperature EEPROM loc. 3


' Define ACD settings
DEFINE ADC_BITS 10 ' 10 bit A/D Conversion
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)

ANSELH = 0 ' Set AN8 thru AN13 Off
ANSEL = %00001100 ' Set pins A.2 & A.3 (AN2, AN3) to analog input, the rest to digital
'ADCON0
ADCON1 = %10000000 ' Set up A/D converter - Right Just., VDD REF.
'
' Set Ports input/output
TRISA = %11101100 ' Set port A I/O
TRISB = %00000001 ' Set port B I/O
TRISC = %11111000 ' Set port C I/O

'SSPCON = 0 ' turn off serial comm

'Define ADC_SAMPLEUS 50 ' Set sampling time in uS (For different chip not needed)
'CM1CON0 = 0 ' Comparators off (Set to zero by default, not needed)
'CM2CON0 = 0 ' Comparators off (Set to zero by default, not needed)
'
'
'
' ALL Settings done by me TO HERE 04/02/2013

' Test parameters. These will be replaced by actual inputs..............
input PORTB.1
tx_g_ng = PORTB.1
lcd_info = 0
' End Test Parameters

' START-UP
high lcd_pwr ' Turn on the LCD display
pause 2000 ' Wait 1 sec for LCD to start up
low tx_pwr ' Turn off the transmitter. A loop will turn it on when needed
low tx_alrm ' Turn off alarm to ensure no accidental activation
low tx_tst ' Turn off Transmitter test pin, loop activates it when needed
write 1, 0 ' Put a zero in EEPROM location 1, clear Battery level in memory (batt_mem)
batt_mem = 0 ' Clear batt_mem - Set to 0
batt_comp = 0 ' Set battery compare flag to 0
read 0, alrm_set ' Get the alarm set temperature from memory
gosub get_temp ' Get current temperature
high solar_fet ' Turn on solar array to charge batteries
sun_lvl = 0 ' Set sun level reading to 0 to prevent false indication of charging
b = 0
' End Start-up


' Mainloop
mainloop:
Lcdout $fe, 1, " Main Loop" 'Display sign-on message
pause 1000
'm = 0
For m = 1 to 250 ' For Next loop generates X second delay while checking buttons
gosub check_button ' Check to see if a button has been pressed
pause 10 ' pause 10 milliseconds
next m ' Repeat loop 250 times
'
lcd_info = lcd_info + 1 ' Increment LCD info VAR, lcd_info count determines what info is displayed on the LCD
Lcdout $fe, 1, "LCD Info ", dec (lcd_info)
pause 1000
' if lcd_info = 3 then goto alarm_ck ' Check for am Alarm condition (temperature below the set point)
If lcd_info >= 6 then ' Reset LCD info VAR to 0 when count reaches 6
lcd_info = 0 ' Reset LCD info VAR to 0 when count reaches 6
counter1 = counter1 + 1 ' Longer period counter, used for longer delays in program (Hi Lo temp reset, Sleep?)
' if counter1 >= 5 then ' X cycles throught 250 counter above...
' gosub tx_test '
counter1 = 0 ' Reset counter 1 after GOSUB
'counter2 = 0 ' reset counter 2
' endif
gosub get_temp ' Get curent temperature
endif
'
' Go and display LCD infor based on lcd_info count
branchl lcd_info,[lcd_batt,lcd_chrg,lcd_tx,lcd_alrm_set,lcd_day_hi,l cd_day_lo]
'
get_temp:
Gosub init1821 ' Init the DS1821

command = $EE ' Start temperature conversion. Changed from 44h to EEh for DS1821
Gosub write1821

Pause 1000 ' Wait 1 second for conversion to complete

Gosub init1821 ' Do another init

command = $AA ' Read the temperature.
Gosub write1821
Gosub read1821

' Display the decimal temperature
' Lcdout $fe, 1, dec (temp >> 1),".",dec(temp.0 * 5)," degrees C" ' This line was the original code, replacement right below

' Convert to Degrees Fahrenheit
temp = temp * 9/5 + 32 ' Degree C to Degrees F ONLY work for positive Degrees C temps (32 F and above).

return


' Initialize DS1821 and check for presence
init1821:
Low DQ ' Set the data pin low to init
Pauseus 500 ' Wait > 480us
DQ_DIR = 1 ' Release data pin (set to input for high)

Pauseus 100 ' Wait > 60us
If DQ = 1 Then
Lcdout $fe, 1, "DS1821 not Found"
Pause 500
Goto mainloop ' Try again
Endif
Pauseus 400 ' Wait for end of presence pulse
Return


' Write "command" byte to the DS1821
write1821:
For i = 1 to 8 ' 8 bits to a byte
If command.0 = 0 Then
Gosub write0 ' Write a 0 bit
Else
Gosub write1 ' Write a 1 bit
Endif
command = command >> 1 ' Shift to next bit
Next i
Return

' Write a 0 bit to the DS1821
write0:
Low DQ
Pauseus 60 ' Low for > 60us for 0
DQ_DIR = 1 ' Release data pin (set to input for high)
Return

' Write a 1 bit to the DS1821
write1:
Low DQ ' Low for < 15us for 1
@ nop ' Delay 1us at 4MHz
DQ_DIR = 1 ' Release data pin (set to input for high)
Pauseus 60 ' Use up rest of time slot
Return


' Read temperature from the DS1821
read1821:
For i = 1 to 8 ' 16 bits to a word. * Changed to 8 for DS1821 Byte
temp = temp >> 1 ' Shift down bits
Gosub readbit ' Get the bit to the top of temp
Next i
Return

' Read a bit from the DS1821
readbit:
temp.7 = 1 ' Preset read bit to 1. Was temp.15 chgd to .7
Low DQ ' Start the time slot
@ nop ' Delay 1us at 4MHz
DQ_DIR = 1 ' Release data pin (set to input for high)
If DQ = 0 Then
temp.7 = 0 ' Set bit to 0. Was temp.15 chgd to .7
Endif
Pauseus 60 ' Wait out rest of time slot
Return
'
'
check_button:

if btn_up = 0 OR btn_dwn = 0 OR btn_back = 0 _ ' If any button is pressed
OR btn_nxt = 0 OR btn_entr = 0 then ' Go to button loop

High lcd_lite ' Turn on the LCD Backlight
goto button_loop
endif
return


' ADC
adc_loop: ' Get readings form the Analog to digital converters
'
ADCIN 2, sun_lvl ' Get ADC value from ADC 2, the solar array
if sun_lvl > sol_con then ' If the ADC reading is high enough...
sun_up = 1 ' ... consider the sun to be up (day time).
else
sun_up = 0 ' If ADC reading not high enough, the sun is considered down (night)
endif

ADCIN 3, batt_lvl ' Get ADC value from ADC channel 3
batt_lvl = (batt_lvl - 450) ' Remove bottom 4.4 volts or so from battery reading
if batt_lvl > 575 then batt_lvl = 0 ' Limit high battery level reading, too high = 0 (error)
return

' Battery - compare ADC volts to volts in EEPROM (memory) location 1
batt_mem_comp:
read 1, batt_mem
if batt_lvl >= batt_mem and _ ' If battery level is increasing or staying the...
batt_comp = 0 then batt_comp = 1 ' ...same set batt_comp 1 to indicate charging
if batt_lvl > batt_mem then write 1, batt_lvl ' As battery is charging write the new higher voltage to memory
if batt_lvl < (batt_mem - 15) then batt_comp = 0 ' If battery voltage falls (by about 0.2), Battery not charging...
' ... this gives a buffer for passing clouds etc.
' Check if battery charging (increasing or steady volts)
charge_ck_loop:
'
if sun_up = 1 and batt_comp = 1 then charge = 1 ' If sun is up and batt volts increasing then charging
if sun_up = 0 and batt_comp = 1 then charge = 0 ' If sun is not up, no charging
if sun_up = 1 and batt_comp = 0 then charge = 0 ' If battery volts aren't going up, no charging
if sun_up = 0 and batt_comp = 0 then charge = 0 ' No sun, no volts, No charge.

' Daily reset of batt_mem

reset_batt_mem:
'
if sun_up = 0 and batt_comp = 0 then write 1, 0 ' Write a 0 to EEPROM loc. 1 when
' sun goes down and batt discharging
return

'Compare, set, reset, & read from EEPROM daily Hi & Lo temperatures
'
compare_hi_lo:

if sun_up = 1 then toggle_drag = 1 ' When the sun comes up set toggle drag to 1
if sun_up = 0 and toggle_drag = 1 then sun_toggle = 0 ' If the sun is down set toggle drag to 0
if sun_toggle = 0 then ' If sun toggle is a 0 then reset daily hi & lo temperatures by...
write 2, temp ' Write the current temperature to EEPROM locatio 2 (Hi temp)
write 3, temp ' Write the current temperature to EEPROM locatio 3 (Lo temp)
sun_toggle = 1 ' Set suntoggle bit to 1
toggle_drag = 0 ' Set toggle drag to 0
endif

if temp > day_hi THEN write 2, temp ' If current temperature is greater than hi temp in...
' ...memory then write the new higher temperature
if temp < day_lo THEN write 3, temp ' If current temperature is less than lo temp in...
' ...memory then write the new lower temperature
read 2, day_hi ' Read the hi temperature into the variable day_hi
read 3, day_lo ' Read the lo temperature into the variable day_lo

Return



' LCD Display Information cycle

lcd_batt: '$DF hex for degree symbol
gosub adc_loop ' Get battery and Solar levels
Lcdout $fe, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $fe, $C0, "Battery At ", DEC (batt_lvl), "%" ' Display battery fullness %age
goto mainloop

lcd_chrg:
gosub batt_mem_comp ' Run battery voltage comparison loop if voltage...
' ... is increasing charge = 1
if charge = 1 then
chg_y_n = $59 ' 59 is Hex for "Y" if charging ($ indicates Hex)
Else
chg_y_n = $4E ' 4E is Hex for "N" if not charging
endif
Lcdout $fe, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $fe, $C0, "Charging?(Y/N) ", (chg_y_n) ' Display "Y" if charging & "N" if not


goto mainloop

lcd_tx:

if tx_g_ng = 1 then ' Check to see if the Tx/RX test passed
Lcdout $fe, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $fe, $C0, "Tx/Rx Test: PASS" ' Display that test passed
else
Lcdout $fe, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $fe, $C0, "Tx/Rx Test FAIL!" ' Display that test failed
PAUSE 1000 ' ... and pause for 5 sec to bring attention
endif
goto mainloop

lcd_alrm_set:
Lcdout $FE, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $FE, $C0, "Alrm Tmp Set ", DEC (alrm_set),$DF ' Display what the alarm is set...
goto mainloop ' ...to go off at

lcd_day_hi:
gosub compare_hi_lo
Lcdout $FE, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $FE, $C0, "Daily Hi ", DEC (day_hi), $DF, "F" ' Display the daily hi temperature
goto mainloop

lcd_day_lo:
Lcdout $FE, 1, " Temp is ", dec (temp), $DF, "F" ' Display current temperature
Lcdout $FE, $C0, "Daily Lo ", DEC (day_lo), $DF, "F" ' Display the daily lo temperature
goto mainloop
'
' What gets done when a button is pressed...
button_loop:

if btn_up = 1 and btn_dwn = 1 and btn_back = 1 _ ' If no buttons are pressed go to mainloop...
and btn_nxt = 1 and btn_entr = 1 then
goto mainloop
endif

button_set_loop:
if btn_up = 0 then up ' If the up button is pressed go to the Up loop
if btn_dwn = 0 then down ' If the down button is pressed go to the Down loop
if btn_back = 0 then back ' If the back button is pressed go to the Back loop
if btn_nxt = 0 then forward ' If the next button is pressed go to the Next loop
if btn_entr = 0 then ' If the enter button is pressed go to the Enter loop
goto enter
else
goto button_loop ' If no buttons are pressed run the button loop again...
endif ' ... which takes you to the main loop.

up:
while btn_up = 0 ' While the Up button is pressed do this loop...
pause 33 ' pause 33 milliseconds to debounce switch
alrm_set = alrm_set + 1 ' increase alarm set point by one degree F
pause 300 ' pause for 300 milliseconds
lcdout $FE, 1, dec (alrm_set) ' Display the alarm set point as it's changed
wend ' Repeat, increasing it 1 degree F every ~1/3...
' ... second until the switch is released

goto button_loop

down:
while btn_dwn = 0
pause 50
alrm_set = alrm_set - 1
pause 300
lcdout $FE, 1, dec (alrm_set)
wend

goto button_loop

back:
while btn_back = 0
pause 50
alrm_set = alrm_set - 1
pause 300
lcdout $FE, 1, dec (alrm_set)
wend

goto button_loop

forward:
while btn_nxt = 0
pause 50
alrm_set = alrm_set + 1
pause 300
lcdout $FE, 1, dec (alrm_set)
wend

goto button_loop

enter: ' Enter button loop
while btn_entr = 0 ' While the button is pressed...
pause 50 ' pause 0.05 seconds
wend ' Do this loop until button is released
write 0, alrm_set ' Write the new setting to memory location zero
lcdout $FE, 1, dec (alrm_set), " Has Been Set" ' Disp[lay what has been set
pause 3000 ' Leave that displayed for 3 seconds

goto mainloop ' go back to normal operation (main loop)

tx_test:
lcdout $FE, 1, " Transmit Test" ' Display that a tx test is being performed
LCDOUT $FE, $C0, " In Progress"
high tx_pwr ' Turn on the transmitter
pause 1000 ' Wait 1 seconds for the transmitter to stabilize
high tx_tst ' Output a high to the chosen data pin for the test
pause 1500 ' wait 1.5 sec for the signal to tbe received and confirmation sent back
if tx_confm = 1 then ' Check for confirmation from the receiver
tx_g_ng = 1 ' Set the Tx go/no go bit to 1 if confirmation was received...
else
tx_g_ng = 0 ' ...Otherwise set it to 0
endif
low tx_pwr ' Turn off the tranxmitter
low tx_tst ' set the transmit test pin back to low
IF tx_g_ng = 1 Then ' Display the result of the test...
lcdout $FE, 1, " Transmit Test"
LCDOUT $FE, $C0, " PASS"
pause 1500
Else
lcdout $FE, 1, " Transmit Test"
LCDOUT $FE, $C0, " FAIL"
pause 3000
endif

return

' Check for alarm condition (Low Temperature) and activate alarm as required
'
alarm_ck:
if temp <= alrm_set then ' Compare current temp to set temp, run loop if alarm
high tx_pwr ' Turn on transmitter
high lcd_pwr ' Turn on LCD
pause 2000 ' Wait for LCD to initialize
for i = 1 to 10 ' Run loop 10 times
high tx_alrm ' Alarm pin on Txmitter high
low lcd_lite ' turn off LCD backlight
LCDOUT $FE, 1, "**** ALARM! ****" ' Display alarm message
LCDOUT $FE, $C0, "TEMPERATURE LOW!" ' Display alarm message
gosub check_button ' Check for button press
pause 1500 ' Pause for 1.5 sec
low tx_alrm ' Turn off alarm pin o Txmitter
high lcd_lite ' Turn on LCD backlight
LCDOUT $FE, 1, "TEMPERATURE LOW!" ' Display alarm message
LCDOUT $FE, $C0, "**** ALARM! ****" ' Display alarm message
gosub check_button ' Check for button press
pause 1500 ' Pause for 1.5 sec
next i ' Repete loop
'gosub compare_hi_lo ' Reset
gosub get_temp ' Get gurrent temperature
endif

if temp > alrm_set then ' If current temp is back above set temp...
low tx_alrm ' Turn off the Alarm pin on Txmitter
low tx_pwr ' Turn off Txmitter power
low lcd_lite ' Turn off LCD Backlight after alarm or shortly after a button press
goto mainloop ' Go back to normal operation (main loop)
else
goto alarm_ck ' If temp is low go to alarm loop again.
endif

end

'''''' CODE Size Check """""""""""""""""





' SOLAR cut-off ' Mind where this is put (after the math on batt_lvl for display)

if batt_lvl >= 110 then ' If battery level 110% or more turn off solar array
Low solar_fet ' Puts ground (0 volts) on MOSFET gate
else
high solar_fet ' Puts +5 volts on MOSFET gate
endif


' SOLAR Powered cycle 'Goes in main loop

if sun_lvl >= 200 then
gosub run_day
else
gosub run_nite
endif


run_day:
' constant runnng loop with LCD display, backlite w/ good battery, tx tests
return

if batt_lvl >= 100 then
high lcd_lite
'Run loop
endif


run_nite:
' sleep cycle loop implemented, low power mode
return



' NIGHT Sleep mode

low lcd_pwr
low lcd_lite

'TRISA = %11101100 ' Set port A I/O Ok, No change
TRISB = %11111111 ' Set port B I/O was %00000001 for LCD out & tx_confm in
TRISC = %11111010 ' Set port C I/O was %11111000 buttons,
' ' C.2 LCD pwr, C.1 LCD Lite, C.0 sol-FET
ANSEL = 0 ' Turn off ADCs
'
FLAGS = 0 ' So LCD will reinitalize on wake-up
Sleep 60

ANSEL = %00001100 ' Reset(AN2, AN3) on
TRISB = %00000001 ' Set port B I/O
TRISC = %11111000 ' Set port C I/O






end

Neosec
- 12th April 2013, 19:03
Some one shoot me! I figured it out 10 minutes after posting. It is branching... I was relying on the loop for the delay for the LCD to display the info. once I put in the "Main Loop" and "LCD Info" bit for debugging they would immediately overwrite the LCD info from the branch, and I would not see it of course.
For some reason posting a question here causes me to find the answer almost immediately afterwards. Thanks for the "Magic" this site casts on me.

xapmanis
- 14th April 2013, 09:57
Same happens with me :D !! Try to make some flowchart on paper with a pencil or on any programm it helps to think and see clear ur code. :) Also try some beer or a coffe for a change :P xaxaxa

Regards Kostas.

Neosec
- 14th April 2013, 15:27
Thanks for the tips!! I'll give the flow chart a try. I don't drink coffee and it's a little too early for beer :D

mark_s
- 14th April 2013, 16:26
This looks like trouble in your code. You gosub to "check_button:" and then goto "button_loop:" if a button is pressed. This creates a case where the gosub never returns, which can cause problems. Beer may help.



check_button:

if btn_up = 0 OR btn_dwn = 0 OR btn_back = 0 _ ' If any button is pressed
OR btn_nxt = 0 OR btn_entr = 0 then ' Go to button loop

High lcd_lite ' Turn on the LCD Backlight
goto button_loop
endif
return

Neosec
- 15th April 2013, 02:02
That bit has been reworked as follows...


check_button:
if btn_up = 0 OR btn_dwn = 0 OR btn_back = 0 _ ' If any button is pressed...
OR btn_nxt = 0 OR btn_entr = 0 _ ' and the LCD Backlight is on...
and lcd_lite = 1 then ' Then Go to button loop
goto button_loop
endif
if btn_up = 0 OR btn_dwn = 0 OR btn_back = 0 _ ' If any button is pressed...
OR btn_nxt = 0 OR btn_entr = 0 _ ' and the LCD backlight is not on...
and lcd_lite = 0 then ' Then turn on the backlight...
high lcd_lite ' ...and pause 2 seconds
pause 2000 ' Holding the button longer than 2 sec. gets you to...
endif ' the button loop VIA the mainloop & check_button and...
return ' IF statement above.

But the GOTO / GOSUB seems ok... At least is seems to be working.


button_loop:
'
if btn_up = 1 and btn_dwn = 1 and btn_back = 1 _ ' If no buttons are pressed go to mainloop...
and btn_nxt = 1 and btn_entr = 1 then
goto mainloop
endif ' Otherwise continue...

button_set_loop:
if btn_up = 0 then up ' If the up button is pressed go to the Up loop
if btn_dwn = 0 then down ' If the down button is pressed go to the Down loop
if btn_back = 0 then back ' If the back button is pressed go to the Back loop
if btn_nxt = 0 then forward ' If the next button is pressed go to the Next loop
if btn_entr = 0 then ' If the enter button is pressed go to the Enter loop
goto enter
else
goto button_loop ' If no buttons are pressed run the button loop again...
endif ' ... which takes you to the main loop.

up:
while btn_up = 0 ' While the Up button is pressed do this loop...
pause 30 ' pause for 30 milliseconds
alrm_set = alrm_set + 1 ' increase alarm set point by one degree F
lcdout $FE, 1, "Alarm Set ", _ ' Display the alarm set point as it's changed
dec (alrm_set),$DF, "F"
pause 300
wend ' Repeat, increasing it 1 degree F every ~1/3...
lite_timer = 0 ' ... second until the switch is released
goto button_loop

down:
while btn_dwn = 0
pau... (and it continues)


The check_button loop returns to the main loop, the button_loop series all end with a GOTO mainloop so it finds its way back. In the code above what I wanted to accomplish was that any button press would turn on the LCD backlight but not increment the variable in button_loop in doing so. The above code work pretty well though I may back off the 2 second pause.
I'm aware that there is much room for improvement in both the code and the hardware... I'm learning as I go. I'm working with a deadline of April 17th so I don't have the time to pretty it up. The hardware is functional with some software work-arounds... Rev B will be awesome! :D
The IF statement about all the buttons being "1" (not pressed) is likely not necessary since it was a button press that got me there in the first place. Cleaning up that stuff will come later, right now it doesn't break anything and I'm not tight on space yet.

Thanks for looking it over I'm grateful for any tips.

PS I know... interrupts and timers... in Rev B ;)

Demon
- 15th April 2013, 02:23
GOTO out of a subroutine is never a good idea.

Set a flag before GOSUB, change the flag within the subroutine, then check the flag once you've returned and GOTO at that point.

Robert

Edit: it may work this time, but it's a habit you don't want to get into.

Neosec
- 15th April 2013, 02:35
I don't follow... can you give a quick example?

Charlie
- 15th April 2013, 10:54
In most programming languages, when you GOSUB, a number of registers get stored in memory to free them up for use by the subroutine. When you RETURN, those values are put back so the program can continue where it left off. When you GOTO out of a subroutine, the registers are not restored. If you did this when writing a program in a Windows or Linux environment, where the values are store in program RAM, the memory is not released when you GOTO out of the subroutine. This is called a memory leak in your program. Do this often enough, and all the RAM is used and not released until a reboot. It's a good habit to always return from a GOSUB with a RETURN to prevent this.

spcw1234
- 15th April 2013, 12:41
I had a similar routine once and it worked fine, until the 23rd time pressing the button it would cause the pic to reset. As Demon said, just have the button set a bit to 1 then return. Immediately after the gosub check if the bit is a 1 and if it is then goto wherever you want.

Demon
- 15th April 2013, 14:15
I don't follow... can you give a quick example?

Flag=0
Gosub routine
If flag = 1 then goto somewhere
.
.
Routine:
Bla bla bla
If something then flag = 1
Return

Robert

Neosec
- 15th April 2013, 23:01
OK, got it. Thanks to everyone for the input.