Author Topic: PIC16F505 won't go to sleep. - SOLVED!  (Read 2100 times)

0 Members and 1 Guest are viewing this topic.

Offline Ralph S.Topic starter

  • Newbie
  • Posts: 4
  • Country: pl
PIC16F505 won't go to sleep. - SOLVED!
« on: December 05, 2015, 08:30:32 pm »
Hi!
I'm currently working on a small 5x6 LED matrix, driven by a PIC 16F505. The problem is it won't enter sleep mode when (I think) it should. The program displays 3 messages.
In theory:
If the button is pressed the PIC wakes up and displays message#1 and then enters sleep mode, unless the button is pressed again. If so message#2 is displayed, and after it finishes scrolling, PIC is going to sleep. If the button is pressed one more time (while displaying m#2) message#3 appears and finally PIC can enter sleep mode (this time for good).
What happens is:
After it finishes scrolling through message#1 it immediately repeats it, on and on.
If I press the button while displaying m#1 for the first time, message#2 appears. When m#2 is done, m#1 comes back again. Pressing the button causes m#1 to reset and start over.
If I somehow manage to get to message#3 it finally ends and the PIC enters sleep mode (I think).

I bet there's some extremely stupid newbie mistake, but I can't figure it out. Can You please help me? Thank you in advance.  ;)

MPLab8.92, XC8 v1.33, PICKit3
Config bits set in MPLab

Code: [Select]
#include <pic16f505.h>
#include <xc.h>
#define _XTAL_FREQ 4000000

void txt(const char array[], char size);

const char m1[74] = {hex numbers, 1 byte = 1 column};
const char m2[57] = {...};
const char m3[107] = {...};
char t=0;
char dummy;

void main(void)
{
OPTION=0b01010111; //wake-up on pin change enabled, T0 source is internal osc
TRISC=0;
TRISB=0b00001000; //all output except RB3
t=0; //this variable changes the displayed messages
if(t==0) txt(m1, 74);
if(t==1) txt(m2, 57);
if(t==2) txt(m3, 107);
PORTB=0;
PORTC=0; //clear all before sleep
dummy=PORTB; //read the port, required for wake-up on pin change
asm("sleep"); //goodnight, sleep tight
}

void txt(const char array[], char size)
{

char i=0; //column pointer

while(i<size)  //work 'till we run out of bytes in array
{
for(char k=0; k<5; k++)  //display each frame 5 times
{
for(char j=0; j<6; j++)  //displaying 1 frame - multiplexing 6 columns
{
PORTB=0;
PORTC=0;
PORTC=array[i+j]; //choose proper byte
if(j==0) RC5=1; //enable column0
if(j==1) RB4=1; //enable column1
if(j==2) RB5=1; //etc...
if(j==3) RB0=1;
if(j==4) RB1=1;
if(j==5) RB2=1;
__delay_ms(2);
}
}

i++; //shift everything left
if(RB3==0) //if button is pressed...
{
t++; //...move on to next message...
i=0xff; //...but first exit this 'while' loop, since 255 is always greater than 'size'
}
}

}
« Last Edit: December 06, 2015, 03:13:01 pm by Ralph S. »
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2082
Re: PIC16F505 won't go to sleep.
« Reply #1 on: December 05, 2015, 09:03:10 pm »
When the processor has been woken from sleep, what is it expected to do?

I'm not familiar with the compiler but I think you want to implement something like:
Code: [Select]
#
       ... as before ...
t=0; //this variable changes the displayed messages
   while (1) {
if(t==0) txt(m1, 74);
if(t==1) txt(m2, 57);
if(t==2) txt(m3, 107);
PORTB=0;
PORTC=0; //clear all before sleep
dummy=PORTB; //read the port, required for wake-up on pin change
asm("sleep"); //goodnight, sleep tight
   }  // end of while loop to catch process when sleep expires

  ... etc.

 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13739
  • Country: gb
    • Mike's Electric Stuff
Re: PIC16F505 won't go to sleep.
« Reply #2 on: December 05, 2015, 09:13:19 pm »
Quote
Config bits set in MPLAB
Why would you not set the config in the code?

Remember the WDT will wake from sleep and start executing after the SLEEP instruction.

You code exits from main, which is an undefined action.

Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline Ralph S.Topic starter

  • Newbie
  • Posts: 4
  • Country: pl
Re: PIC16F505 won't go to sleep.
« Reply #3 on: December 05, 2015, 09:40:55 pm »
Thank you for your replies.
The datasheet says that the device resets on wake-up. I thought that after it wakes up it starts from the beginning and I could get away without the main loop.
I'll put the config line in the code (I was too lazy back then, but now it does seem like a bad idea). The Watchdog Timer is disabled - this is not a crucial application, so why bother?
I'll try to fix the code and program the thing tomorrow.
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2082
Re: PIC16F505 won't go to sleep.
« Reply #4 on: December 05, 2015, 09:56:07 pm »
The datasheet says that the device resets on wake-up.
Yes, I believe you're right - I was forgetting this is the 5xx family In that case, I think you need to make the setting of "t=0" dependent on the cause of the reset.
« Last Edit: December 05, 2015, 09:58:36 pm by Andy Watson »
 

Offline Ralph S.Topic starter

  • Newbie
  • Posts: 4
  • Country: pl
Re: PIC16F505 won't go to sleep.
« Reply #5 on: December 06, 2015, 03:12:31 pm »
Hah! I've got it! Just as I expected it was a foolish mistake.
The program couldn't exit whe 'while' loop in 'txt' function. The loop condition was (i<size), but a few lines later the program grabbed 'i+1'th, 'i+2'th (... etc.) element of the array. If the given array's size was for example 74, and the loop counted to 73, it loaded the 74+j'th element. Also it happened that the 'txt' function was stored just next to message#1 array in the memory, so when the program reached out of its boundary the function repeated itself  ;D
I've changed the condition to (i<(size-5)) and the problem is gone  :) No need for an infinite loop in main, because the processor starts over after it wakes up.


Was:
Code: [Select]
void txt(const char array[], char size)
{

char i=0;

while(i<size)  //if 'i' gets any near to 'size'...
{
for(char k=0; k<5; k++) 
{
for(char j=0; j<6; j++) 
{
PORTB=0;
PORTC=0;
PORTC=array[i+j]; //...we reach to '(size+1)'th element which happens to be the 'txt' function address
if(j==0) RC5=1;
if(j==1) RB4=1;
if(j==2) RB5=1;
if(j==3) RB0=1;
if(j==4) RB1=1;
if(j==5) RB2=1;
__delay_ms(2);
}
}

i++;
if(RB3==0)
{
t++;
i=0xff;
}
}

}

Should be:
Code: [Select]
oid txt(const char array[], char size)
{

char i=0;

while(i<(size-5)) // now it stays within its boundary
{
for(char k=0; k<5; k++) 
{
for(char j=0; j<6; j++) 
{
PORTB=0;
PORTC=0;
PORTC=array[i+j];
if(j==0) RC5=1;
if(j==1) RB4=1;
if(j==2) RB5=1;
if(j==3) RB0=1;
if(j==4) RB1=1;
if(j==5) RB2=1;
__delay_ms(2);
}
}

i++;
if(RB3==0)
{
t++;
i=0xff;
}
}

I hope that someone will learn from my silly mistake. One again, thank you all for taking your time to help me  :-+
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf