PDA

View Full Version : Button problem driving me crazy!! Please help!



bearpawz
- 19th November 2007, 04:08
The info:
Using a pic 16F819, 20MHZ crystal oscilator

What I am trying to do:

I have 4 momentary pushbuttons with coresponding lamps. One is a "power" switch / lamp, the rest are one of three (ie, push one button and its lamp comes on, the others go off).
The "one of three" part works flawlessly.

My problem lies in the "Power" button. The unit defaults with power on and one other lamp lit. When I press the power switch, I want all lamps to go out until power switch is pressed again. (Simulating turn the whole unit off). For the LIFE of me I can not figure out what is going on with my code. Its not a debounce issue, ive tried puting in delays up to 10 seconds after the button is pressed and the unit insists on going back to the power up state. here is the code:


DEFINE OSC 20 ' 20 Mhz Oscillation
OSCCON = $70 ' Oscilator Config reg.

Clear ' Clear all memory
TRISA = %00000000 ' Set port a to all out
TRISB = %00001111 ' Set Port b to i/o


Speaker Var PortA.0 ' Tone pin out
Power Var PortB.0 ' Input for power switch
Auto VAR PortB.1 ' Input for Auto Switch
Normal VAR PortB.2 ' Input for Normal Switch
Pursuit VAR Portb.3 ' Input for Pursuit Switch
Power_LED VAR Portb.7 ' Output for Power Lamp
Auto_LED Var Portb.6 ' Output for Auto Lamp
Normal_LED VAR Portb.5 ' Output for Normal Lamp
Pursuit_LED VAR Portb.4 ' Output for Pursuit Lamp

Initialize:
High Power_LED ' Power Default = ON
low Auto_Led ' Auto Defualt = OFF
High Normal_LED ' Normal Default = ON
low Pursuit_LED ' Pursuit Default = ON

Start:
If Power = 1 Then Power_Pressed
If Power_LED = 1 then ' Execute only if in ON state
If Normal = 1 Then Normal_Pressed ' Normal button pressed?
If Pursuit = 1 Then Pursuit_Pressed ' Pursuite button Pressed?
If Auto = 1 then auto_pressed ' Auto button pressed
EndIF
Goto Start ' Loop forever

'**************************SUBROUTINE AREA********************************

Auto_Pressed: ' Auto button code:
Low Pursuit_LED ' Turn off Pursuit lamp
Low Normal_LED ' Turn off Normal Lamp
High Auto_LED ' Turn on Auto Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto start ' Go back to main routine

Normal_Pressed: ' Normal button code:
Low Pursuit_LED ' Turn off Pursuit lamp
Low Auto_LED ' Turn off Auto Lamp
High Normal_LED ' Turn on Normal Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto Start ' Go back to main routine

Pursuit_Pressed: ' Pursuit button code:
Low Normal_LED ' Turn off Normal Lamp
Low Auto_LED ' Turn off Auto Lamp
High Pursuit_LED ' Turn on Pursuit Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto Start ' Go back to main routine


Power_Pressed:
If Power_LED = 1 Then
Low Power_LED ' Turn off Power LED
Low Auto_LED ' Turn off Auto LED
Low Normal_LED ' Turn off Normal LED
low Pursuit_LED ' Turn off Pursuit LED
pause 1000 ' 1 second debounce delay
ELSE
High Power_LED ' Turn on Power_LED
High Normal_LED ' Turn on Normal_LED
Pause 1000 ' 1 Second Debounce delay
endif
Goto Start

Jerson
- 19th November 2007, 05:24
Just thinking aloud; I haven't checked the datasheet for the device. Is your watchdog kicking in and resetting the device?

Jerson

bearpawz
- 19th November 2007, 05:57
I had already thought of that and tried programming with all that stuff disabled. Ive put "test" lines of code in here and there and its acting like it wants to excute BOTH parts of the if-thenelse statement.

sayzer
- 19th November 2007, 07:59
Hi there,

There are couple of things you did not specify in your code.

1. You set your OSC to be 8Mhz (internal OSC) but you are declaring it to PBP as 20Mhz. Are you using internal OSC or external OSC?

2. Since you did not enable internal weak pull ups on PORTB pins, I assume you are using external pull up resistors on your input buttons. If you are not using any, then input pins may behave like crazy.

3. This chip has analog port on PORTA. You have a speaker on PORTA.0 but you did not disable analog module.

4. "If Power_LED = 1 ..." this won't work. You can not read the state of an output pin. I suggest that you set a flag bit and read that flag instead.

===============================

Archangel
- 19th November 2007, 08:05
The info:
Using a pic 16F819, 20MHZ crystal oscilator

What I am trying to do:

I have 4 momentary pushbuttons with coresponding lamps. One is a "power" switch / lamp, the rest are one of three (ie, push one button and its lamp comes on, the others go off).
The "one of three" part works flawlessly.

My problem lies in the "Power" button. The unit defaults with power on and one other lamp lit. When I press the power switch, I want all lamps to go out until power switch is pressed again. (Simulating turn the whole unit off). For the LIFE of me I can not figure out what is going on with my code. Its not a debounce issue, ive tried puting in delays up to 10 seconds after the button is pressed and the unit insists on going back to the power up state. here is the code:


Hi Bearpawz,
You did not say what your circuit <b>IS</b> doing, or not doing. Since you are pulling PortB.0 up to signal your PIC, I ask if you remembered to pull it down with a resistor to logic low so as not to have a high impeadance on that pin? Lemmie guess, a controller for a dual purpose or B/W, yes?
JS
EDIT: WOW Sayzer slipped in just ahead of me ! Hi Sayzer !

bearpawz
- 19th November 2007, 17:29
Hi there,

There are couple of things you did not specify in your code.

1. You set your OSC to be 8Mhz (internal OSC) but you are declaring it to PBP as 20Mhz. Are you using internal OSC or external OSC?

2. Since you did not enable internal weak pull ups on PORTB pins, I assume you are using external pull up resistors on your input buttons. If you are not using any, then input pins may behave like crazy.

3. This chip has analog port on PORTA. You have a speaker on PORTA.0 but you did not disable analog module.

4. "If Power_LED = 1 ..." this won't work. You can not read the state of an output pin. I suggest that you set a flag bit and read that flag instead.

===============================

1. OSCON is recycled code, I commented it out. However I am programming it to use HS in the config bit so it shouldn’t really matter... (?)

2. Weak pull ups are not enabled but the hardware uses cookie cutter schematic example from PBP manual under the "Button" command. Pin is held low Via 10K resistor until pushed, then goes high.

3. I haven’t even bothered with the port a stuff yet. Its basically just sending a DTFMOUT command when a button is pressed.

4. "IF POWER LED = 1 Then..", It actually DOES work. In fact, there is absolutely no issues with that line of code at all. I tested it by simply not turning on the power LED. When Power LED is off it does not execute the if/then statement; only when it is on. Either way, I’ve tried using a simple 1 bit flag and it didn’t resolve anything.


Here are the lines of code in question with my notes as to what’s happening:

Start:
If Power = 1 Then Power_Pressed <----- Only branch to power pressed if button pushed
'If Power_LED = 1 then ' Execute only if in ON state
' If Normal = 1 Then Normal_Pressed ' Normal button pressed?
' If Pursuit = 1 Then Pursuit_Pressed ' Pursuit button Pressed?
' If Auto = 1 then auto_pressed ' Auto button pressed
'EndIF
Goto Start ' Loop forever

.
.
.

Power_Pressed: <---- Should only be here when power pressed. This part seems fine until...
If Power_LED = 1 Then <--- Check to see if we are on of off by looking at power LED
Low Power_LED ' Turn off Power LED
Low Auto_LED ' Turn off Auto LED
Low Normal_LED ' Turn off Normal LED
low Pursuit_LED ' Turn off Pursuit LED
pause 1000 ' 1 second denounce delay

================================================== ===============
Right here is the problem. At this point what will happen is the unit goes into (simulated) power off mode and waits for 1 second. That at least confirms the code is working, and the swtich should have had ample time to no longer be in a pushed state. And the above block does indeed do what it is supposed to when it is supposed to.

So at this point we should be jumping over everything in the ELSE statement and going directly back to start. Instead, it executes everything in the else statement.
================================================== ==================

ELSE
High Power_LED ' Turn on Power_LED
High Normal_LED ' Turn on Normal_LED
Pause 1000 ' 1 Second Debounce delay
endif
Goto Start



What I have done to try and resolve this is: use a flag instead of directly reading the pin: there was no change. I’ve added test code to confirm that the unit is executing the code in the "else" section as opposed to just restarting the program. I have even tried putting in Repeat/until loops to check for the button being 0 again and then being 1. I’m starting to think the think is just possessed. Everything else works exactly the way it is supposed to. I’ve tried the same code testing different switches... It all boils down to this one if/then/else statement that SHOULD work. :(


Just for complete fun, I decided to go back and re-add a flag instead of reading the port directly. It had no effect. I even went as far as trying a brand new chip (16F818 instead of 819) and it still does the same exact thing. here is the NEW code: And I’m just totally stumped.




DEFINE OSC 20 ' 20 Mhz Oscillation
'OSCCON = $70 ' Oscilator Config reg.

Clear ' Clear all memory
TRISA = %00000000 ' Set port a to all out
TRISB = %00001111 ' Set Port b to i/o


Speaker Var PortA.0 ' Tone pin out
Power Var PortB.0 ' Input for power switch
Auto VAR PortB.1 ' Input for Auto Switch
Normal VAR PortB.2 ' Input for Normal Switch
Pursuit VAR Portb.3 ' Input for Pursuit Switch
Power_LED VAR Portb.7 ' Output for Power Lamp
Auto_LED Var Portb.6 ' Output for Auto Lamp
Normal_LED VAR Portb.5 ' Output for Normal Lamp
Pursuit_LED VAR Portb.4 ' Output for Pursuit Lamp
Power_Flag Var bit ' Flag to indicate power on/off


Initialize:
High Power_LED ' Power Default = ON
low Auto_Led ' Auto Defualt = OFF
High Normal_LED ' Normal Default = ON
low Pursuit_LED ' Pursuit Default = ON
Power_Flag = 1 ' Unit is on, set power flag

Start:
If Power = 1 Then Power_Pressed
If Power_Flag = 1 then ' Execute only if in ON state
If Normal = 1 Then Normal_Pressed ' Normal button pressed?
If Pursuit = 1 Then Pursuit_Pressed ' Pursuite button Pressed?
If Auto = 1 then auto_pressed ' Auto button pressed
EndIF
Goto Start ' Loop forever

'**************************SUBROUTINE AREA********************************

Auto_Pressed: ' Auto button code:
Low Pursuit_LED ' Turn off Pursuit lamp
Low Normal_LED ' Turn off Normal Lamp
High Auto_LED ' Turn on Auto Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto start ' Go back to main routine

Normal_Pressed: ' Normal button code:
Low Pursuit_LED ' Turn off Pursuit lamp
Low Auto_LED ' Turn off Auto Lamp
High Normal_LED ' Turn on Normal Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto Start ' Go back to main routine

Pursuit_Pressed: ' Pursuit button code:
Low Normal_LED ' Turn off Normal Lamp
Low Auto_LED ' Turn off Auto Lamp
High Pursuit_LED ' Turn on Pursuit Lamp
'DTMFOUT Speaker, [1] ' Send tone sound out
Goto Start ' Go back to main routine


Power_Pressed:
If Power_Flag = 1 Then
Low Power_LED ' Turn off Power LED
Low Auto_LED ' Turn off Auto LED
Low Normal_LED ' Turn off Normal LED
low Pursuit_LED ' Turn off Pursuit LED
pause 1000 ' debounce delay
Power_Flag = 0 ' Falgged for off state
ELSE
High Power_LED ' Turn on Power_LED
High Normal_LED ' Turn on Normal_LED
Pause 1000 ' Debounce delay
Power_Flag = 1 ' Flagged for on state
endif
Goto Start

mister_e
- 19th November 2007, 23:18
untested but i figure i would change the following section...


PowerOn var bit

Initialize:
Clear ' Clear all memory
poweron = 1
High Power_LED ' Power Default = ON
low Auto_Led ' Auto Defualt = OFF
High Normal_LED ' Normal Default = ON
low Pursuit_LED ' Pursuit Default = ON

Start:
If Power = 1 Then Power_Pressed
If poweron = 1 then' Execute only if in ON state
If Normal = 1 Then Normal_Pressed ' Normal button pressed?
If Pursuit = 1 Then Pursuit_Pressed ' Pursuite button Pressed?
If Auto = 1 then auto_pressed ' Auto button pressed
endif
Goto Start ' Loop forever '
'
'
'
'
'
'
'
'
'
Power_Pressed:
If poweron = 1 Then
Low Power_LED ' Turn off Power LED
Low Auto_LED ' Turn off Auto LED
Low Normal_LED ' Turn off Normal LED
low Pursuit_LED ' Turn off Pursuit LED
poweron=0
pause 1000 ' 1 second debounce delay
ELSE
High Power_LED ' Turn on Power_LED
High Normal_LED ' Turn on Normal_LED
poweron=1
Pause 1000 ' 1 Second Debounce delay
endif
Goto Start

deuh.. looks the same thing you've done... weird... it has to work.

mister_e
- 19th November 2007, 23:32
insert those config fuse at the top of your code..


asm
list w=-207
cfg1 = _HS_OSC & _MCLR_OFF & _CCP1_RB2 & _BODEN_ON & _PWRTE_ON &_WDT_OFF
cfg2 = _LVP_OFF & _DEBUG_OFF & _CP_OFF & _WRT_ENABLE_OFF & _CPD_OFF
list w=+207
__CONFIG cfg1 & cfg2
endasm

Jerson
- 20th November 2007, 03:56
Its more a manner of style I presume, but, here's how I prefer to configure the device



@ device HS_OSC, MCLR_OFF, PWRT_ON, WDT_OFF
@ device PROTECT_ON,BOD_ON, CPD_ON


To understand these defines, look at the M16F81x.INC file. They are all listed there.
Excerpted from the file


; *** DEVICE Fuses Definitions
EXTRC_OSC_CLKOUT equ 3FEC0013h ; XX XXXX XXX1 XX11
EXTRC_OSC_NOCLKOUT equ 3FEC0012h ; XX XXXX XXX1 XX10
EXTRC_OSC equ 3FEC0012h ; XX XXXX XXX1 XX10
INTRC_OSC_CLKOUT equ 3FEC0011h ; XX XXXX XXX1 XX01
INTRC_OSC_NOCLKOUT equ 3FEC0010h ; XX XXXX XXX1 XX00
INTRC_OSC equ 3FEC0010h ; XX XXXX XXX1 XX00
EXTCLK_OSC equ 3FEC0003h ; XX XXXX XXX0 XX11
EC_OSC equ 3FEC0003h ; XX XXXX XXX0 XX11
HS_OSC equ 3FEC0002h ; XX XXXX XXX0 XX10
XT_OSC equ 3FEC0001h ; XX XXXX XXX0 XX01
LP_OSC equ 3FEC0000h ; XX XXXX XXX0 XX00
WDT_ON equ 3FFB0004h ; XX XXXX XXXX X1XX
WDT_OFF equ 3FFB0000h ; XX XXXX XXXX X0XX
PWRT_ON equ 3FF70000h ; XX XXXX XXXX 0XXX
PWRT_OFF equ 3FF70008h ; XX XXXX XXXX 1XXX
MCLR_ON equ 3FDF0020h ; XX XXXX XX1X XXXX
MCLR_OFF equ 3FDF0000h ; XX XXXX XX0X XXXX
BOD_ON equ 3FBF0040h ; XX XXXX X1XX XXXX
BOD_OFF equ 3FBF0000h ; XX XXXX X0XX XXXX
LVP_ON equ 3F7F0080h ; XX XXXX 1XXX XXXX
LVP_OFF equ 3F7F0000h ; XX XXXX 0XXX XXXX
CPD_ON equ 3EFF0000h ; XX XXX0 XXXX XXXX
CPD_OFF equ 3EFF0100h ; XX XXX1 XXXX XXXX
WRT_1FOURTH equ 39FF0000h ; XX X00X XXXX XXXX
WRT_HALF equ 39FF0200h ; XX X01X XXXX XXXX
WRT_3FOURTHS equ 39FF0400h ; XX X10X XXXX XXXX
WRT_OFF equ 39FF0600h ; XX X11X XXXX XXXX
DEBUG_ON equ 37FF0000h ; XX 0XXX XXXX XXXX
DEBUG_OFF equ 37FF0800h ; XX 1XXX XXXX XXXX
CCPMX_ON equ 2FFF0000h ; X0 XXXX XXXX XXXX
CCPMX_OFF equ 2FFF1000h ; X1 XXXX XXXX XXXX
PROTECT_ON equ 1FFF0000h ; 0X XXXX XXXX XXXX
PROTECT_OFF equ 1FFF2000h ; 1X XXXX XXXX XXXX


I think this makes it independent of whether you use MPASM or PM assembler.

mister_e
- 20th November 2007, 04:07
Yup, but i NEVER use PM, it's way to limited when you compare with MPASM function set. AND it work for ALL pic family, from 10f to pic32

The right syntax for MPASM would be..

@ __CONFIG _HS_OSC & _MCLR_OFF & _CCP1_RB2 & _BODEN_ON & _PWRTE_ON &_WDT_OFF & _LVP_OFF & _DEBUG_OFF & _CP_OFF & _WRT_ENABLE_OFF & _CPD_OFF

but it's way too long, why i've splitted in 2 lines. LIST directive is just to remove mpasm warning... label found in colum 1... really annoying stuff.

Ingvar
- 20th November 2007, 09:37
Hi Bearpawz,

I just tried your code on a 16F628 and it worked just fine. You probably have a hardwareproblem. Check and make sure that your outputs are swinging all the way between 0 and Vdd, if not you're in trouble. Most common mistake is a missing(or to low) resistor in series with the LED. You also need to make sure that your pulldownresistors(on the buttons) are properly connected. Other shorts could ofcourse also be a problem.

bearpawz
- 20th November 2007, 14:46
Even though ive been through every circuit on the board with a meter and found no problems, Im thinking it must be hardware as well. Im going to see if I can find the right style switch in a push on/push off configuration and just hook up supply power to that switch (the way it should be done anyway). thanks for the help though.