some help/advice with a program with 16F1789

Enhanced mid-range devices. PIC12F1xxx and PIC16F1xxx

Re: some help/advice with a program with 16F1789

Postby DavidBLit » Wed Aug 20, 2014 1:53 pm

Yeah, just be ready for both barrels when you slip up.
User avatar
DavidBLit
 
Posts: 14
Joined: Fri May 30, 2014 12:37 pm
Location: The Land of Confusion
PIC experience: Professional 5+ years with MCHP products

Re: some help/advice with a program with 16F1789

Postby stef_r » Tue Aug 26, 2014 9:55 pm

First of all thank you all for all the comments and tips.
Although Olin sugested to use the Timer2, I actually sticked with Timer0 for now only because it is used in the tutorial(s) I use.
If I get more familiar on how to use the Timer0 and get it to work, I defenitly will explore to use the Timer2 instead of Timer0!

But.....
I have writen a code as shown below.
Part of it comes straight from the tutorial, part is (re)written by myself.
Here is how I think it should work:
* If not allready done, switch OFF the LED
* reset / zero the Timer0 and overflow flag
* I press a button.
* when I release the button, there is a debounce delay
* after the debounce delay, the LED turns on
* timer is incrementing from 0 to 255
* After Timer0 overflow has occured, the Timer) overflof flag is set , the LED is turned OFF
* this would be repeating on and on.

And this is the code:
Code: Select all
;****MAIN PROGRAM
MAIN
        ;turn off LED RC0 & RC6
        banksel LATE
        bcf     LATE,RE2                ; turn OFF LED @ RE2

        ;zero Timer0
        banksel TMR0
        clrf    TMR0                    ; clear Timer0
        bcf     INTCON,TMR0IF           ; and clear Timer0 overflow flag

        ;wait for button press @ RB0
        banksel PORTB
wait_dn btfsc   PORTB,RB0               ; if RB => LOW, skip next instruction
        goto    wait_dn

        ;wait for button release @ RB0 and debounce by sampling @ 1mS
db_up   movlw   .10                 ; max count = 10 (10ms @ 1ms/sample)
        movwf   db_cnt
up_smp  movlw   .42                 ; sample every 1ms
up_dly  decfsz  WREG,f              ;   delay 42x3-1 = 125 inst. cycles
        goto    up_dly              ;   = 125 x 8us = 1ms
        banksel PORTB
        btfss   PORTB,RB0           ;   if button RB0 is pressed (RB0 => LOW)
        goto    db_up               ;       restart count
        decfsz  db_cnt,f            ; else repeat until max count reached
        goto    up_smp

        ;turn on LED @ RE2
        banksel LATE
        bsf     LATE,RE2                ; turn ON LED @ RE2

        ;delay
dly_tmr btfss   INTCON,TMR0IF           ; if Timer0 overflow occured
        goto    dly_tmr            ;
        banksel LATE
        bcf     LATC,RE2

        ;repeat forever
        goto    MAIN

    END


But all I see is a very short 'flash' from the LED...
When I quickly and repeatedly press the button, the LED sometimes stay's on for a brief period of time. ( ~200msec?)
I have set the oscilator frequency at the default 500KHz.

What do I miss or what doesn't I see here?????
(I know using interrupts would be 'better' or preferred choiche for this, but for understanding the basics, I would like to figure this one out first... :geek: )
Last edited by stef_r on Tue Aug 26, 2014 10:01 pm, edited 1 time in total.
stef_r
 
Posts: 15
Joined: Thu Aug 14, 2014 12:16 pm
PIC experience: Experienced Hobbyist

Re: some help/advice with a program with 16F1789

Postby Olin Lathrop » Tue Aug 26, 2014 10:00 pm

If your oscillator is 500 kHz, the instruction frequency is 125 kHz, the instruction period is 8 us, and 256 instruction as timed by timer 0 is only 2 ms. That is why the LED is coming on for a very short time.
User avatar
Olin Lathrop
Verified identity
 
Posts: 48
Joined: Fri May 30, 2014 3:38 pm
Location: Littleton, MA USA
PIC experience: Professional 5+ years with MCHP products

Re: some help/advice with a program with 16F1789

Postby stef_r » Tue Aug 26, 2014 10:08 pm

That would be the case, but I forgot to mention I have set the prescaler to 1:256 so the actual overflow time would be 2ms x 256 = 524ms.... Or am I incorrect?????

Code: Select all
;****CONFIGURE OSCILLATOR
        movlw   b'00000111'         ; configure OPTION_REG
;                 0-------             clear NOT_WPUEN bit; enable weak pull-ups
;                 -0------             clear INTEDG bit; int. on falling edge
;                 --0-----             clear TMR0CS bit; Int. instruction cycle
;                 ----0---             clear PSA bit: Prescaler to Timer0 module
;                 -----111             set prescaler to 1:256
        banksel OPTION_REG
        movwf   OPTION_REG
stef_r
 
Posts: 15
Joined: Thu Aug 14, 2014 12:16 pm
PIC experience: Experienced Hobbyist

Re: some help/advice with a program with 16F1789

Postby DavidBLit » Wed Aug 27, 2014 12:31 pm

bcf LATC,RE2
User avatar
DavidBLit
 
Posts: 14
Joined: Fri May 30, 2014 12:37 pm
Location: The Land of Confusion
PIC experience: Professional 5+ years with MCHP products

Re: some help/advice with a program with 16F1789

Postby tunelabguy » Wed Aug 27, 2014 1:48 pm

DavidBLit wrote:bcf LATC,RE2

Yes, that is a typo, and that error will prevent the LED from being turned off by that instruction. But in the code, the next thing that happens is a jump back to MAIN, where the proper instruction to turn off the LED is issued. So this typo instruction was unnecessary.

However the real problem with the OP's code is that Timer 0 begins to count immediately after it is cleared and its interrupt flag is cleared. So while we are waiting around for the button to be pushed, Timer0 is counting and overflowing. Unless the button is pushed right away before Timer0 can overflow, the interrupt flag will already be set by the time the code first polls for it, so the LED will be turned off immediately. Solution: Don't bother clearing the timer and the interrupt flag until after the LED is turned on.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: some help/advice with a program with 16F1789

Postby stef_r » Sun Aug 31, 2014 11:09 am

Ok, I indeed noticed the type mismatch... :oops:

But the main 'problem' with my initial code is still doesn't respond to the switch while in the delay loop.
In order to fix this, I'm thinking of doing the following:

In my ISR, I want to poll and debouce the 6 inputs. (switch input gives HIGH -> LOW)
Each RAW input is then compared to the debounce state.
If the input is debounced and therefor accepted as a valid input, a flaf (variable) is set

The main program is polling this flag and acts accordingly.

This way, (at least thats my thought) while the main program is in a delay loop, the program still respond to the switch input which is in the ISR, right?

(And now that I have this written down, I need to see how to convert it to Assembler code... :o :? :lol: )
stef_r
 
Posts: 15
Joined: Thu Aug 14, 2014 12:16 pm
PIC experience: Experienced Hobbyist

Re: some help/advice with a program with 16F1789

Postby tunelabguy » Sun Aug 31, 2014 3:11 pm

If you can't figure out why the simple foreground switch polling doesn't work, why do you think that moving to the more complex interrupt-based approach is going to be any better? Get a handle on what is going on while things are still simple or you will be totally lost when more complexity is added.

First of all, what evidence do you have that the program is "not responding to the switch"? Is it that the LED is not visibly flashing? That has already been explained. Fix that in the manner I recommended and go from there.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: some help/advice with a program with 16F1789

Postby MMcLaren » Tue Sep 02, 2014 3:58 am

Hi stef_r,

I wonder if you may be stuck because you've only learned about "blocking" type switch routines in the Gooligum tutorials? If so, you might like to learn about non-blocking methods which would allow you to sample, debounce, and filter out the "new press" or "new release" switch states within a loop structure, without blocking the loop. These non-blocking methods usually involve using a switch state latch (or switch memory) which contains the state of the switch during the last pass through the loop. With loop timing based on a switch sample/debounce interval, each time through the loop you would would collect a 'new' switch sample and then use simple logic to detect a "new press" state (new = 1 & old = 0) or a "new release" state (new = 0 & old = 1) while ignoring the other two states where 'new' = 'old'. The code can be relatively simple (see example below), allowing you to detect and act on a "new press" or a "new release" state without blocking other functions in the loop, like your LED timer function.

I hope this helps. Good luck in your studies.

Cheerful regards, Mike, K8LH (Michigan, USA)

Code: Select all
        clrf    swold           ; clear switch state latch          |00

;********************************************************************
;  main loop                                                        *
;********************************************************************
loop
        call    delay25ms       ; 25-ms debounce/loop interval      |00
        comf    PORTB,W         ; sample active lo RB0 switch       |00
        movwf   swnew           ; save new sample                   |00

newrelease
        btfss   swnew,0         ; new == 0? no, skip (exit), else   |00
        btfss   swold,0         ; old == 1? yes, skip, else         |00
        bra     newpress        ; branch (not new release)          |00

newpress
        btfsc   swnew,0         ; new == 1? no, skip (exit), else   |00
        btfsc   swold,0         ; old == 0? yes, skip, else         |00
        bra     swlatch         ; branch (not new press)            |00

        movlw   1<<RE2          ; bit mask for LED on RE2           |00
        xorwf   PORTE,F         ; toggle LED (RE2)                  |00
        movlw   800/25+1        ; 800-ms / 25-ms loop time          |00
        movwf   ledtmr          ; reset 800-msec LED timer          |00

swlatch
        movf    swnew,W         ; update switch state latch         |00
        movwf   swold           ;                                   |00

ontimer
        btfsc   PORTE,RE2       ; LED on? no, skip (exit), else     |00
        decfsz  ledtmr,F        ; 800-ms time out? yes, skip        |00
        bra     loop            ;                                   |00
        bcf     PORTE,RE2       ; turn LED off                      |00
        bra     loop            ;                                   |00

;********************************************************************


MMcLaren
 
Posts: 18
Joined: Sun Aug 31, 2014 10:08 pm
PIC experience: Experienced Hobbyist

Re: some help/advice with a program with 16F1789

Postby stef_r » Wed Sep 03, 2014 9:22 am

Hi MMcLaren,

Thank you very much for the information!
I think you might be right. Although I have experimented with PIC's before this is the first time I want to 'dig into it' a bit further. Some may say Assembler and 8-bit PIC's isn't the best way to start with and would suggest to go for C and 16- or 32 bit MCU's.
But since I really wanted to 'get to know' the PIC's hardware architecture, and didn't want to get stuck by a program like PICbasic with a limitied supported devices and other shortcomings, Assembler looked the language to learn for me.

The Gooligum tutorials helped me a lot with the basics (lit a LED, creating delay loops for flashing a LED, reading switch inputs etc.).
But the problem is, and I admit I might want to jump too far ahead sometimes, while I'll start to learn or get the hand on the Assembler language, at the same time I want to write a program for a small project I'm currently working on.
The project involves just some 'simple?' functions like inverting an input with a defined delay, conditional outputs (output B may only be activated when input A AND input B are powered).
But then I walk into things like above, that the switch doesn't respond while in the delay loop.

If I look further in the Gooligum tutorials, I see that some approaches I've learned so far are solved differently and much easier, like with the use of interrupts and stuff like that. and my 'problem' is that I then want to try and use that code before I actually be at that chapter and missing some chapters and proberbly some critical need-to-know information.

On the other hand, I do learn a lot from seeing an example and modifying it to see what happends.

Some of the instructions in your code are new for me, so I will take a good look at them later this day to 'see' what they are exactly doing and how they are used.
Looking to your code, if I would use this code I think I need to make counter variables like the "ledtmr" and "delay25ms" routine, right?

For the progress of my project, I have lowered the oscillator frequency to 125KHz so I can create a delay loop of ~2sec.
The actual delay loop would need to be around 1000 - 1300 ms.
To lower the frequency in the OSCCAL register, I would avoid to wrap the timer into multiple loops. For the use of my program (responding to switch inputs and flash some outputs) it doesn't really matter if the speed is 125KHz of 4MHz... But I thought it would make sense and perhaps make my life easier to go for the lowest speed.

Anyway, I will look into your code in more detail and hopefully I will manage to get the switch responding the way I want... :mrgreen:
stef_r
 
Posts: 15
Joined: Thu Aug 14, 2014 12:16 pm
PIC experience: Experienced Hobbyist

PreviousNext

Return to 14-Bit Core (enhanced)

Who is online

Users browsing this forum: No registered users and 1 guest

cron