• AVR Freaks

AnsweredHot!PIC16F505 does not wake-up on pin change

Page: 12 > Showing page 1 of 2
Author
Blubb
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/07/19 06:47:26
  • Location: 0
  • Status: offline
2019/07/23 08:33:41 (permalink)
0

PIC16F505 does not wake-up on pin change

Good afternoon :)
 
I am having trouble with a PIC16F505 refusing to wake up on pin change. While the same button works fine to input commands, the chip does not react to it being pressed once it is asleep. The important parts (so I hope) of the code are given below. Does anyone have an idea what could be going wrong?


#pragma config OSC = IntRC_RB4EN// Oscillator Selection bits (Internal RC oscillator/RB4 function on RB4/OSC2/CLKOUT pin)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection off)
#pragma config MCLRE = OFF      // RB3/MCLR Pin Function Select bit (GP3/MCLR pin function
                                // is digital input, MCLR internally tied to VDD)

void init_pic(void) {

    OPTION = 0b01011111;
            
    // initializing PORTB: RB3 and RB5 as input remaining PORTB as output
    TRISB = 0b00101000; // RB3 is 1 = input, rest is 0 = output: 0x08 = 00001000
    PORTB = 0b00000000;
    //LATB = 0b00000000;
    
    // Initializing PORTC as output
    TRISC = 0b00000000; // All pins in PORTC are 0 = output
    PORTC = 0b00000000; // Initially all PORTC pins are 0 = low
    return;
    
} // end init


void main(void) {
    int timer_start;
    int new_stuff;
        
    // initializing the pic
    new_stuff = PORTB;
    init_pic();
    blink_all();
    
    // main code
    timer_start = set_timer();
    run_timer(timer_start);
    
    // End timer run with sleep
    DbnceHi(PORTBbits.RB3); // wait for stable RB3-button release
    PORTB;
    SLEEP();
    return;

} // end main

 
 
#1
pcbbc
Super Member
  • Total Posts : 1373
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/07/23 09:32:46 (permalink)
+3 (3)
blubbThe important parts (so I hope) of the code are given below. Does anyone have an idea what could be going wrong?

Sorry, but if you do not know what is wrong, you are not qualified to decide what the "important parts" are.
Post a complete working example which demonstrates the susposed problem.
#2
Blubb
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/07/19 06:47:26
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/07/24 00:15:18 (permalink)
0
Dear pcbb

Actually, you are very right. Thank you for your critique. I am learning every day, and you were very right. 
As I tried to minimize the code to a presentable working example I realized that the chip does indeed wake up as long as I do not run the function buzz().
So this time I attached a complete working example.
 
#pragma config OSC = IntRC_RB4EN // Oscillator Selection bits (Internal RC oscillator/RB4 function on RB4/OSC2/CLKOUT pin)
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF // Code Protection bit (Code protection off)
#pragma config MCLRE = OFF // RB3/MCLR Pin Function Select bit (GP3/MCLR pin function
                                // is digital input, MCLR internally tied to VDD)

#include <xc.h>
#include "timer_main_v2.h"
#include "stdmacros-xc8.h"
/* #include <pic16f505.h> // passiert automatisch in xc.h -> pic.h -> pic_chip_select.h */

// Initial setting of pins to input/output
void init_pic(void) {
    
    // setting OPTION bit7 = 0 to enable wake-up on pin-change
    OPTION = 0b01011111;
            
    // initializing PORTB: RB3 and RB5 as input remaining PORTB as output
    TRISB = 0b00101000; // RB3 is 1 = input, rest is 0 = output: 0x08 = 00001000
    PORTB = 0b00000000;
    //LATB = 0b00000000;
    
    // Initializing PORTC as output
    TRISC = 0b00000000; // All pins in PORTC are 0 = output
    PORTC = 0b00000000; // Initially all PORTC pins are 0 = low
    return;
    
} // end init

void blink_all(void) {
    // Short blink at start
    PORTC = 0b00001111;
    __delay_ms(100);
    PORTC = 0b00000000;
    return;
} // blink_all

int get_button_input(int wait_time_ms) {
    //const int loop_delay_ms = 10;
    while (wait_time_ms > 0) {
        __delay_ms(10);
        if (0 == PORTBbits.RB3) {
           __delay_ms(100);
            return 1;
        }
        wait_time_ms-=10;
    }
    return 0;
} // get_button_input

int set_timer(void) {
    return 1;
} // set_timer

void buzz(void){
    int button;
    // activate buzzer in end timer run
    PORTCbits.RC5 = 1;
    button = get_button_input(5*1000);
    PORTCbits.RC5 = 0;
} // buzz

void run_timer(int start_time) {
    buzz();
    return;
} // run_timer

void main(void) {
    int timer_start;
        
    // initializing the pic
    init_pic();
    blink_all();
    
    // main code
    timer_start = set_timer();
    run_timer(timer_start);
    
    // End timer run with sleep
    DbnceHi(PORTBbits.RB3); // wait for stable RB3-button release
    PORTB;
    PORTC;
    SLEEP();
    return;
} // end main

#3
pcbbc
Super Member
  • Total Posts : 1373
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/07/24 02:04:58 (permalink) ☼ Best Answerby Blubb 2019/07/25 06:31:34
+2 (2)
In your example you are missing a...
#define _XTAL_FREQ 8000000

 
That means the __delay_ms macro you are using inside get_button_input, which is called from buzz, has no idea how many clock cycles to wait for.
Similarly for  __delay_ms(100) in function blink_all.
 
In fact I'd be surprised if it compiles.  In fact it doesn't, because you haven't supplied...
#include "timer_main_v2.h"
#include "stdmacros-xc8.h"

 
I expect your PIC IS waking from sleep, but getting stuck in get_button_input for some reason.
What state is RB3 in when you wake from sleep?
What is RC5 connect to, and how?
Can you see RC5 go high when you wake from sleep?  Your code should at least get that far.
What clock speed is your PIC running at?
What do you have _XTAL_FREQ set to?
And most importantly - How are you determining "the chip does indeed wake up"?  Is it by some code that executes after calling buzz()?
 
If RB3 remains high and you have _XTAL_FREQ set incorrectly you could be in that routine for considerably longer than 5 seconds.
 
Tips:
set_timer does nothing, other than returning 1 which is assigned to timer_start, passed to run_timer and then ignored.
There is no need for a "return" at the end of a void function.  It does no harm, but most people will omit it.
#4
Blubb
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/07/19 06:47:26
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/07/25 07:25:39 (permalink)
0
Dear pcbbc

Thank you so much for your thorough answer. I appreciate your help very much.

You are right, the two header files are missing. They provide:
timer_main_v2.h
#ifndef MAIN_H
#define MAIN_H
#include <xc.h> // include processor files - each processor file is guarded.
#define _XTAL_FREQ 4000000 /*Clock frequency 4*10^6 Hz*/
#endif

and stdmacros-XC8.h
#define DEBOUNCE 10*1000/256 // switch debounce count = 10 ms/(256us/tick)
#define DbnceHi(PIN) TMR0 = 0; /* reset timer */ \
                     while (TMR0 < DEBOUNCE) /* wait until debounce time */ \
                         if (PIN == 0) /* if input low, */ \
                             TMR0 = 0 /* restart wait */

The frequencies might not match quite adequately, but I ignored this until now. As far as I understand the configuration the PIC16F505 should be running with the internal 4 MHz oscillator.
Something that I was not vey sure about were the first OPTION bits. I have PSA =1, assigning the Prescaler to the WDT, and  PS<2:0> = 111 setting the TIMR0-Rate =1 : 256 / WDT-Rate =1 : 128

To your questions:
When I run the code with the MPLAB DIDE simulator, RB3 is per default high (4.5 V). To wake up the chip, I use a stimulus "pulse low" on RB3. I am not quite sure how the simulator works, but if I do that the simulated chip wakes up and RB3 is high again.
When I load the program on to the physical chip on my device, The device works as in :
- all LEDs  blink
- the buzzer, connected to RC5 over a transistor buzzes annoyingly
- the buzzer stops buzzing when I press the button temporarily setting RB3 temporarily to low.

If I press the button again, setting RB3 temporarily to low, and expecting to wake up the chip by doing so, nothing happens. I doubt that the chip wakes up again or reaches buzz() because then all LEDs would first need to blink. They don't. I have to disconnect power first to then get it to run again.
If i program the PIC16F505 with the same routine except without the buzz() then the chip wakes up and all LEDs blink when the button is pressed again.
 
RC5 is connected over a 330 Ohm resistor to the base of a transistor used as a switch for a buzzer.
#5
pcbbc
Super Member
  • Total Posts : 1373
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/07/25 08:58:02 (permalink)
+1 (1)
If i program the PIC16F505 with the same routine except without the buzz() then the chip wakes up and all LEDs blink when the button is pressed again.

Well, there's no conceivable explaination for that, at least that I can see, other than:
a) Compiler bug
b) Hardware design error
 
As it seems to work correctly in simulation for you, I think we can rule out a).
#6
Blubb
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/07/19 06:47:26
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 09:27:31 (permalink)
0
Hei, i am sorry for the long delay of my answer. 
The summer holiday season got in the way, and I took some time to review the hardware concept.
There I could not find any problems. Maybe I am overlooking something but I decided to also experiment with the code a little more. What I found in this process leads me to still beleive there is a software problem.
 
Again I have a minimum working example attached below (hopefully I did not forget any neccesary includes this time). What I observe is the following. My programmed device works as expected, when the function buzz() is commented out and NOT called. In this case what happens is:
1. The device turns on and is initiallized and blinks all lights once.
2. A LED blinking once indicates that blink_one() was executed. 
3. The device appears to be sleeping (nothing happens)
3. When a button is pressed, setting RB3 temporarily to low, the device wakes up (which can be seen as all lights blink again.)
This can be repeated many times.
 
As soon as buzz() is included in the code, The following happens:
1. The device turns on and is initiallized and blinks all lights once
2. The buzzer buzzes for a short time. (So I assume that buzz() was execuded correctly).
3. The LED from blink_one() blinks repeatedly. It can only be stopped by removing the battery.
 
This leads me to beleive that with buzz() included, the execution never leaves the function countdown() instead blink_one() is called repeatedly. Now I do not understand what could be the reason for this behaviour. The only difference from a working to the non working version seems to be buzz(), which does not do anything else but set RC5 to high once, wait a short time, and set it low again. 
Could the problem have something to do with RC5 also being the T0CKI-pin?
 

/*
* timer_main_v2.c
*/

#pragma config OSC = IntRC_RB4EN// Oscillator Selection bits (Internal RC oscillator/RB4 function on RB4/OSC2/CLKOUT pin)
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF // Code Protection bit (Code protection off)
#pragma config MCLRE = OFF // RB3/MCLR Pin Function Select bit (GP3/MCLR pin function
                                // is digital input, MCLR internally tied to VDD)

#include <xc.h>
#include "timer_main_v2.h"
#include "stdmacros-xc8.h"
/* #include <pic16f505.h> // passiert automatisch in xc.h -> pic.h -> pic_chip_select.h */

// Initial setting of pins to input/output
void init_pic(void) {
    
    // setting OPTION bit7 = 0 to enable wake-up on pin-change
    OPTION = 0b01011111;
            
    // initializing PORTB: RB3 and RB5 as input remaining PORTB as output
    TRISB = 0b00101000; // RB3 is 1 = input, rest is 0 = output: 0x08 = 00001000
    PORTB = 0b00000000;
    //LATB = 0b00000000;
    
    // Initializing PORTC as output
    TRISC = 0b00000000; // All pins in PORTC are 0 = output
    PORTC = 0b00000000; // Initially all PORTC pins are 0 = low
    return;
    
} // end init

void blink_all(void) {
    // Short blink at start
    PORTC = 0b00001111;
    __delay_ms(100);
    PORTC = 0b00000000;
    return;
} // blink_all

void blink_one(void) {
    // Short blink at start
    PORTC = 0b00000001;
    __delay_ms(100);
    PORTC = 0b00000000;
    __delay_ms(100);
    return;
} // blink_one

int get_button_input(int wait_time_ms) {
    //const int loop_delay_ms = 10;
    __delay_ms(100);
    return 0;
} // get_button_input

int set_timer(void) {
    return 1;
} // set_timer

void buzz(void){
    int button;
    // activate buzzer in end timer run
    PORTC = 0b00100000;
    button = get_button_input(5*1000);
    PORTC = 0b00000000;
} // buzz

void countdown(int start_time) {
    buzz();
    blink_one(); // DEVICE DOES NOT SLEEP BUT RUNS THIS LINE CONTINUOUSLY.
} // run_timer

void main(void) {
    int timer_start;
        
    // initializing the pic
    init_pic();
    blink_all();
    
    // main code
    timer_start = set_timer();
    countdown(timer_start);
    
    // End timer run with sleep
    DbnceHi(PORTBbits.RB3); // wait for stable RB3-button release
    PORTB;
    PORTC;
    SLEEP();
    return;
} // end main

/*
* timer_main_v2.h
*/
#ifndef MAIN_H
#define MAIN_H
#include <xc.h> // include processor files - each processor file is guarded.
#define _XTAL_FREQ 4000000
#endif

/*
* stdmacros-xc8.h
*/
#define DEBOUNCE 10*1000/256 // switch debounce count = 10 ms/(256us/tick)
#define DbnceLo(PIN) TMR0 = 0;
                     while (TMR0 < DEBOUNCE)
                         if (PIN == 1)
                             TMR0 = 0
 

#7
nigelwright7557
Super Member
  • Total Posts : 308
  • Reward points : 0
  • Joined: 2006/11/06 08:15:51
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 09:52:48 (permalink)
0
It might be a hardware problem where turning on buzzer is affecting the power rails ?
I know you have to be careful with relays as turn off can put a big spike on the rails and crash the micro.
Have you decoupled your power rail ?
 
 
#8
1and0
Access is Denied
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 10:02:22 (permalink)
+4 (4)
blubb
I am having trouble with a PIC16F505 refusing to wake up on pin change. While the same button works fine to input commands, the chip does not react to it being pressed once it is asleep. The important parts (so I hope) of the code are given below. Does anyone have an idea what could be going wrong?
...
As soon as buzz() is included in the code, The following happens:
1. The device turns on and is initiallized and blinks all lights once
2. The buzzer buzzes for a short time. (So I assume that buzz() was execuded correctly).
3. The LED from blink_one() blinks repeatedly. It can only be stopped by removing the battery.
 
This leads me to beleive that with buzz() included, the execution never leaves the function countdown() instead blink_one() is called repeatedly. Now I do not understand what could be the reason for this behaviour. The only difference from a working to the non working version seems to be buzz(), which does not do anything else but set RC5 to high once, wait a short time, and set it low again. 

Your PIC device has a stack of ONLY 2 levels depth.  So, countdown() -> buzz() -> get_button_input() will cause a stack overflow.
 
Edit: 
 
void countdown(int start_time) {
    buzz();
    blink_one(); // DEVICE DOES NOT SLEEP BUT RUNS THIS LINE CONTINUOUSLY.
} // run_timer

When the stack is overflown, returning from countdown() will return to the instruction after buzz(), which in turn calls blink_one() and then returns again to the same point, resulting in an infinite loop of calling blink_one().
 
post edited by 1and0 - 2019/08/09 10:18:40
#9
Blubb
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/07/19 06:47:26
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 12:31:23 (permalink)
0
Hi nigelwright and 1and0, thank you for your immediate answers. :)


I guess you're right, it could be a hardware problem with the buzzer drawing too much current from the power sourcce or something. But the buzzer is coupled over a transistor and when I checked with an oscilloscope all the values of voltage and current appeared within the limits I calculated.

I am super excited about the information about the allowed levels of depth. I did not know this was a thing. I will try a rewritten version of the code as soon as possible. Will keep you updated on whether that solved the problem.
#10
jtemples
عُضْوٌ جَدِيد
  • Total Posts : 11414
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 13:20:21 (permalink)
0
Your PIC device has a stack of ONLY 2 levels depth

 
I haven't used one of those ancient PICs in a long time, but I'm vaguely remembering that the compiler will generate a software call stack (automatically?) when needed for the PICs with two-deep stacks.
#11
dan1138
Super Member
  • Total Posts : 3265
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 15:46:46 (permalink)
+2 (2)
Using C with the base-line (12-bit) PICs is a real pain.
 
There are several "issues" with the base-line architecture:
  • Call stack is limited to two levels
  • Called functions entry point must be in the first 256 instruction locations
  • TRIS registers are write only
  • Well written C code can generate crap object code for base-line PICs
 
#12
1and0
Access is Denied
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 16:22:14 (permalink)
+1 (1)
jtemples
I haven't used one of those ancient PICs in a long time, but I'm vaguely remembering that the compiler will generate a software call stack (automatically?) when needed for the PICs with two-deep stacks.

For that you'll have to manually select "Managed Stack".  From OP's description of the problem, I don't think he is using managed stack; hence, stack overflow causes blink_one() to loop repeatedly.
post edited by 1and0 - 2019/08/09 16:51:05
#13
ric
Super Member
  • Total Posts : 24324
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F505 does not wake-up on pin change 2019/08/09 16:27:18 (permalink)
+1 (1)
A PIC16F15323 is pin compatible with a PIC16F505, about the same price, but MUCH MUCH more powerful!
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#14
1and0
Access is Denied
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 16:28:56 (permalink)
+2 (2)
blubb
 
I am super excited about the information about the allowed levels of depth. I did not know this was a thing. I will try a rewritten version of the code as soon as possible. Will keep you updated on whether that solved the problem.

You have two options:
  1. rewrite your code to have no more than two levels of nested function calls, or
  2. select "managed stack" in the compiler properties.
 
#15
jtemples
عُضْوٌ جَدِيد
  • Total Posts : 11414
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 17:27:39 (permalink)
0
What I'm remembering was in HI-Tech 9.60:
 
The baseline PIC devices have a two-level deep hardware stack which is used to store the return address of a subroutine call. Typically, PICC uses a call instruction to transfer control to a C function when it is called, however on baseline processors, the size of the stack severely limits the level of nested C function calls possible.
 
By default, function calls on baseline PICs are implemented using a method involving an assembly jump instruction and a lookup table, or jump table. A function is called by jumping directly to its address after storing the address of a jump table instruction which will be able to return control back to the calling function. The address is stored as an object local to the function being called.

#16
1and0
Access is Denied
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/09 18:11:03 (permalink)
+1 (1)
XC8 just throws a warning:
warning: (1393) possible hardware stack overflow detected; estimated stack depth: 3

#17
rpg7
Super Member
  • Total Posts : 1386
  • Reward points : 0
  • Joined: 2003/11/07 12:47:35
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/10 03:42:06 (permalink)
+2 (2)
I might have missed something, but it appears the the OP's code returns from main() aftr  sleeping. AFAIK, the code should loop endlessly.

    PORTB;
    PORTC;
    SLEEP();
    return;
} // end main

#18
1and0
Access is Denied
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/10 09:28:31 (permalink)
+1 (1)
rpg7
I might have missed something, but it appears the the OP's code returns from main() aftr  sleeping. AFAIK, the code should loop endlessly.

    PORTB;
    PORTC;
    SLEEP();
    return;
} // end main


On these baseline PIC devices, a wake-up from Sleep causes a device Reset.  So, that return will never get executed. ;)
 
 
#19
rpg7
Super Member
  • Total Posts : 1386
  • Reward points : 0
  • Joined: 2003/11/07 12:47:35
  • Status: offline
Re: PIC16F505 does not wake-up on pin change 2019/08/11 00:02:04 (permalink)
0
1and0
 
 

On these baseline PIC devices, a wake-up from Sleep causes a device Reset.  So, that return will never get executed. ;)
 
Thanks for the info :)
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5