PDA

View Full Version : Strange happenings PBP and 12F683



RussMartin
- 6th February 2009, 00:59
I'm hollering "Uncle!" on this right now.

Attached are two segments from a larger program that, as of right now, works perfectly. It records keypresses (TRIGR) at 8 frames per second and plays them back. This is running on a 12F683 and uses Darrel's interrupts for timing.

What I've been trying is to add (somewhere) a test: If the key is stuck or still held down, I want further execution to stop until the key is released.

And that's where the trouble begins. Sounds silly, simple, and should be straightforward, right? But I've tried an amazing number of combinations of IF . . . ENDIF, WHILE . . . WEND, GOTOs, and GOSUBs. Nothing works quite right. Obviously, I'm not seeing something.

The most common result is that the test "sticks" on odd-numbered attempts and won't release back to the program when the key is released until the key is pressed again. (I've even used ALED as a blinky/status indicator.)

Did I fry one too many brain cells back in the 1960s?

Darrel Taylor
- 6th February 2009, 02:13
Hi Russ,

I don't see any way out of PLOOP.

Since it doesn't increment FRAME, it'll never make it to 240 or find a $FF in EEPROM.
<br>

Charles Linquis
- 6th February 2009, 02:59
Untested, but something like this will probably work. Designed to be called from a timer interrupt.




Gosub ReadKey

If Key = Pressed THEN
IF KeyPressedFlag = 0 THEN
KeyCounter = KeyCounter + 1
IF KeyCounter > DebouncePeriod THEN
KeyCounter = 0
KeyPressedFlag = 1
GOSUB Routine_for_KeyPressed
ENDIF
KeyDownCounter = KeyDownCounter + 1
IF KeyDownCounter > ToleranceLimit then
HSEROUT ["Dummy, Get off the key!"]
ENDIF
ELSE
KeyCounter = 0
KeyPressedFlag = 0
KeyDownCounter = 0
GOSUB Routine_for_KeyReleased
ENDIF

RussMartin
- 6th February 2009, 04:34
Hi Russ,

I don't see any way out of PLOOP.

Since it doesn't increment FRAME, it'll never make it to 240 or find a $FF in EEPROM.
<br>

FRAME is incremented in the interrupt handler for both the PLAY and RECORD subroutines.

Remember, these are just the fragments where I tried trapping the "continued key-on" condition; the whole program works just fine as-is.

RussMartin
- 6th February 2009, 07:49
Here's an example of one of many different attempts.

When the flag is 1, it works just fine.

When the flag is 0, it works fine when there is no data present (the first byte read is $FF). As long as the switch is held down, it flashes the LED one way; when it is released, the LED goes back to its "idle" condition.

For any other data present, it sometimes seems to go directly to PLEXIT; other times, it works as it should.

In fact, I'm playing with it now. On one attempt (with data present), it seems to jump directly to PLEXIT; on the next, it plays back the data. Then the cycle starts over again: One wrong response, one correct one. Time after time.

Archangel
- 6th February 2009, 08:55
Hi Russ,
I remember back in the early nineties making a 3 wire timer the 3 wires being hot ground and load. When you activated the timer by momentarily switching power to the load the timer would activate and hold power on the load for 15 seconds. The circuit used a transistor and a capacitor to feed the base and a 555 timer and another transistor to carry the load. My point is maybe you could use a capacitor on your inputs, when it charges up it drops the load and requires you to release the switch to reactivate.

Acetronics2
- 6th February 2009, 09:03
Hi, Russ

I remember having had similar issues some years ago whith a 16F628 ...

IF THEN tests didn't work at all ... whether the condition result.

Was for a R/C failsafe sequence ... rather annoying, indeed.


I just got out of that by re-organizing my subs ( that were called by goto's ...) a bit more "rationnaly" ...

May be posts are not fallen into Archives yet ... ( I'll dig somewhat ... )

Alain

PS: Got it ... but hurry up !!! I Won't be able to post a lot until it passes the limit ... lol
http://www.picbasic.co.uk/forum/showthread.php?t=1952

RussMartin
- 6th February 2009, 16:28
Joe, the switch drives an optoisolator which in turn drives the PIC input (GPIO.3 configured as input, not MCLR). (I've looked at the switch and the output from the opto on the scope; there's not much bounce.)

Alain, my general arrangement of the program is:

PROGRAM (things done at power-up only)

MAIN LOOP (you've seen it)

SUBROUTINES (you've seen the one that is the problem)

INTERRUPT HANDLER

END

I'll try moving some things around, but I continue mystified and frustrated.

Acetronics2
- 6th February 2009, 16:52
Hi, Russ

I do not have any problem left with :




PROGRAM (things done at power-up only)

INTERRUPT HANDLER

MAIN LOOP (you've seen it)

END ( for safety ...)

SUBROUTINES (you've seen the one that is the problem)

END
.
.
.

and @ last prog memory location
@GOTO Program ( if "not so good" supply ... EQU : Prog Pointer lost )

RussMartin
- 7th February 2009, 02:30
Okay, here's the latest, in full.

It works just fine.

I had hoped to also have a flag called MFLAG at EEPROM address 255, managed in a manner similar to what is done with PFLAG.

If MFLAG is 0, the program would be prevented from looping when the trigger (TRIGR) is still being held high (on). But it doesn't matter where I put IF . . . ENDIF or WHILE . . . WEND or GOTOs or GOSUBs. Whenever they are dealing with TRIGR, I get glitches.

So I'm posting the whole thing. Maybe one of you can see what prevents me from getting what I need to do in a manner that will work.

Acetronics2
- 7th February 2009, 09:03
Hi, Russ



If the key is stuck or still held down, I want further execution to stop until the key is released.


generally, I do that :



'************************************************* *******************
' Test Sélection
'************************************************* *******************

Delay = 0
BUTTON Selection,0,255,0,Delay,1,Wait1 ' button pressed pulls to ground

GOTO Affichage ' or Wherever you want, if no press !
' rem: NO DELAY if test = 0 !!!

Wait1: ' Wait for release

Delay = 0
BUTTON Selection,0,255,0,Delay,1,Wait1

GOTO Affichage ' Here, we continue ONLY if Button has been released ...
.
.
.



Alain

Jerson
- 7th February 2009, 12:31
Wouldn't this work? You have it in Erase already.


MAIN: IF TRIGR=1 THEN
PAUSE 10
GOSUB PLAY
while TRIGR=1:wend 'block till the key is released
ENDIF
IF CONTROL=0 THEN
PAUSE 10
GOSUB RECORD
while CONTROL=0:wend 'block till the key is released
ENDIF
IF ACTIVE=0 THEN
PAUSE 10
GOSUB MANUAL
while ACTIVE=0:wend 'block till the key is released
ENDIF
GOTO MAIN

RussMartin
- 7th February 2009, 20:29
Thanks, Jerson and Alain. I'll keep both of those ideas in mind.

What I ended up doing that worked: Inspired by part of what Charles said, I check the condition of the switch in the interrupt handler and set a flag if the switch is closed. Then I check the flag during the MAIN loop. If it and another flag are both set, it kicks to a subroutine.

But nothing yet explains why I couldn't dependably perform simple conditionals on that input in the MAIN loop. It's a mystery.

RussMartin
- 9th February 2009, 10:34
I've attached the most recent version.

Once in a while, for no apparent reason, or after a RECORD cycle, when TRIGR is activated (with MFLAG set to 0), the program appears to jump directly to NOTCLR.

How long does the interrupt service in TIMER take? I'm sure it's a matter of microseconds, but how many using DT_INTS-14?

Is it possible that, if TRIGR goes high during the very short time while the interrupt is being serviced, the routine is going to skip going to PLAY and instead will go to NOTCLR?

And, if so, what is the best solution?

RussMartin
- 10th February 2009, 16:26
The problem still occurs and I seem unable to predict when.

Sometimes, execution seems to go directly to NOTCLR.

I attached the full program (slightly earlier version) to my prior post.

The only changes have been in MAIN, PLAY, NOTCLR, and TIMER, shown below.

Can someone point out where I'm going wrong?




MAIN: IF TRIGR=1 THEN ' Selects "playback"
PAUSE 9 ' Pause ~10 milliseconds for debounce
GOSUB PLAY
ENDIF
IF MFLAG=0 AND KEYCHK=1 THEN ' If mode selection prohibits continuous
GOSUB NOTCLR ' switch closure, Await switch opening
ENDIF
IF CONTROL=0 THEN ' Selects "record"
PAUSE 9 ' Pause ~10 milliseconds for debounce
GOSUB RECORD
ENDIF
IF ACTIVE=0 THEN ' Manual override when idle
PAUSE 9 ' Pause ~10 milliseconds for debounce
GOSUB MANUAL
ENDIF
GOTO MAIN

-----

PLAY: CYCLE=0 : FLASH=8 : FLASH2=5 ' Status LED indicates "playback"
CLOCK=0 ' Reset the clock for read
PLOOP: IF FRAME=248 THEN GOTO PLEXIT ' If top of data is reached, exit
READ FRAME,STATE ' Read the frame from data memory
IF STATE=$FF THEN GOTO PLEXIT ' If end-of-data marker is read, exit
IF STATE=1 THEN ' For state 1,
RELAY=1 : ALED=1 ' turn the relay and activity LED on,
ENDIF ' otherwise,
IF STATE=0 THEN ' for state 0,
RELAY=0 : ALED=0 ' turn the relay and activity LED off
ENDIF
GOTO PLOOP ' Repeat until an exit condition occurs
PLEXIT: CYCLE=0 : FLASH=16 : FLASH2=9 ' Status LED indicates "idle"
RETURN

-----

NOTCLR: CYCLE=0 : FLASH=2 : FLASH2=2 ' Status LED indicates "attention!"
WHILE KEYCHK=1 OR TRIGR=1 ' While the trigger input is active,
WEND ' further execution is prevented
PAUSE 9 ' Pause ~10 milliseconds
CYCLE=0 : FLASH=16 : FLASH2=9 ' Return to the idle state
RETURN



For some reason, this won't allow me to include TIMER in the above without dropping statements, so I'll do that one this messy way. Note: FRAME above is the low byte of ADDRS below.

TIMER: CYCLE=CYCLE+1
IF CYCLE<FLASH2 THEN
SLED=1
ELSE
SLED=0
ENDIF
IF CYCLE>FLASH THEN CYCLE=0
ADDRS=CLOCK>>1
CLOCK=CLOCK+1
IF TRIGR=1 THEN
KEYCHK=1
ELSE
KEYCHK=0
ENDIF
@ INT_RETURN