CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SLEEP & ULPWU Help

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Armondo522
Guest







SLEEP & ULPWU Help
PostPosted: Fri May 29, 2009 8:31 am     Reply with quote

Hi,

I am using a PIC 16F886 Micro with a ULPWU feature. I am feeding a voltage level to the ULPWU Pin from a sensitive light sensor. I want to put the micro to sleep while there is light available and wake up when it goes dark for a given interval. Below is my code. It appears to be working in just the opposite manner than I anticipated. When I cover the sensor, I get no reaction. When I slowly move my hand away from the sensor and let light shine on it. The routine wakes up and times out normally.
Should I put all the control code shown in main in the ULPWU ISR? Or am I just going about this the wrong way.
Any Help appreciated.

Thanks

void main()
{
set_tris_A(0b11111111);

setup_oscillator(OSC_4MHZ);
setup_adc_ports(sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(SPI_SS_DISABLED);
set_adc_channel (1);

clear_interrupt(int_ULPWU);

enable_interrupts(INT_ULPWU);
enable_interrupts(INT_EXT); // pyro interrupt
EXT_INT_EDGE(L_TO_H);

read_switch(); // get timeout value

PIE2=0B00000100; // setup ULPWU Interrupt
PCON=0B00100000; // in case compiler does'nt
enable_interrupts(GLOBAL);

output_low(pin_C1); /// led ground
output_High(pin_A7);// pyro test


do //start of loop
{
restart: // jump after wakeup

if(lite_leds) // start of sequence depend on flag
{
clear_interrupt(int_ULPWU); // int must have fired to get here
disable_interrupts(INT_ULPWU); // disable for duration of test
sec_run=0;
setup_timer_2(T2_DIV_BY_16,187,16); // start and zero 1 sec timer
set_timer2(0);

enable_interrupts(INT_TIMER2); // 1 hz led flash routine

seconds_to_run= minutes_to_run*60; // calulate time to stay active
multiple= seconds_to_run/3;
first_timer= multiple;
second_timer=multiple*2;//
third_timer=multiple*3;

full_power(); // turn on leds full power

do
{
delay_ms(5);
if(get_voltage()>.5) // only on when its dark, reads sensor
// Get_Voltage A/D routine
{
goto all_over; // exit and shutdown if light is back on
}
}while(sec_run<first_timer); // 1st time interval
output_low(pin_B2);
delay_ms(10); // reset driver

two_thirds_power(); // 2/3 power

do
{
if(get_voltage()>.5) // only on when its dark
{
goto all_over;
}
delay_ms(5);
}while(sec_run<second_timer);

output_low(pin_B2);
delay_ms(10);

one_third_power(); // 1/3 power

do
{
delay_ms(5);
if(get_voltage()>.5) // only turn on when its dark
{
goto all_over;
}
}while(sec_run<third_timer);

all_over:

lite_leds=false; // clear flag end of sequence

output_low(pin_B2); // turn off leds
output_low(pin_C0); // turn off 1 hz led
clear_interrupt(int_ULPWU);
disable_interrupts(INT_TIMER2);
enable_interrupts(INT_ULPWU); // so we can start again
} // end of IF

sleep(); // goto sleep if there is light

#ASM // stop here after sleep
NOP
#ENDASM

if(get_voltage()>.5) // in case of a false trip on sensor
{ // recycle and wait
goto all_over;
}

lite_leds=true;

}while(true); // end of loop MAIN

}
Ttelmah
Guest







PostPosted: Fri May 29, 2009 8:50 am     Reply with quote

Learn to use the code buttons.....

Get rid of your direct setups for ULPWU.
Disable the INT_GLOBAL (otherwise the EXT interrupt will also wake you).
Have just a 'delay_cycles(1)' as the first instruction after the sleep (this codes a NOP).
Then use the sleep_ulpwu function. This allows you to specify the charge time (in uSec), and then wakes when the capacitor discharges and triggers the ulpwu.

However the purpose/reasoning behind your code is not clear. You have a line saying that ULPWU must have triggered to get here, yet if ULPWU has triggered or INT_EXT has triggered, it won't reach this line, since you have no interrupt handlers at all shown.

With interrupts, you have two choices:
Have them enabled, and INT_GLOBAL _disabled_. You can then poll the interrupts, or wake from sleep with them.
If INT_GLOBAL is enabled as well, you _must_ have handler code.

Best Wishes
Armondo522
Guest







PostPosted: Fri May 29, 2009 9:04 am     Reply with quote

Thank you for the reply.
I do not want a timed interrupt, instead I need a level interrupt on the ULPWU pin. When light is on the sensor its above ViL. I want to interrupt when <ViL. The external interupt, should also have the same effect. I think my biggest problem is understanding what happens exactly happens after a wake up event occurs.

Thanks in advance.
Ttelmah
Guest







PostPosted: Fri May 29, 2009 2:39 pm     Reply with quote

You can still just use the sleep_ulpwu function. Just set the charge time to 0.

However the problems with your code as shown still apply regarding interrupts.
You must never enable_interrupts(GLOBAL), without having interrupt handler code present. Even if you think the interrupts won't trigger, you must assume they will.

With interrupts, there is an individual 'enable', for each function, and the global enable. If both a set, whether or not you are asleep, the handler is needed, and will be called (when asleep, it'll happen one instruction after you wake). You must get rid of the enable_interrupts(GLOBAL) line, or add a handler for the interrupts.

When you 'sleep' (either ulpwu, or a normal sleep), if an enabled interrupt occurs _whether or not the INT_GLOBAL is enabled_, the chip will wake up. It'll execute the next instruction (which was prefetched when you went to sleep), and if the global interrupt flag is set, will then immediately call the handler code - problem since you don't have any. When the handler returns (or immediately if the global interrupt is disabled), the following code then executes.

Best Wishes
Guest








PostPosted: Sat May 30, 2009 4:29 pm     Reply with quote

I have moved the whole routine to a function to be called after the micro wakes up. In the function I need to enable interrupts so I can count ticks for time. I think I understand how the sleep works now..

thanks a bunch
Code:

#include "C:\Program Files\PICC\Projects\Led light\led_main.h"
 // #include <float.h>
 // #include <stdio.h>
 // #include <stdlib.h>
  #ZERO_RAM

//#use delay(clock=4000000,INTERNAL,RESTART_WDT)

float  dummy;
byte lite_leds=False;
long minutes_to_run=1;
long sec_run=0;
long seconds_to_run;
byte no_run=0;
long multiple,first_timer,second_timer,third_timer,tick_counter;
float input_volts;
void full_power();
float get_voltage();
void two_thirds_power();
void one_third_power();
void read_switch();

void lite_the_leds()
{
//restart:          // jump after wakeup
                // start of sequence depend on flag
read_switch();
clear_interrupt(int_ULPWU);            // int must have fired to get here
disable_interrupts(INT_ULPWU);         // disable for duration of test
sec_run=0;
setup_timer_2(T2_DIV_BY_16,187,16);    // start and zero 1 sec timer
set_timer2(0);

enable_interrupts(INT_TIMER2);         // 1 hz led flash routine
enable_interrupts(GLOBAL);
seconds_to_run= minutes_to_run*60;     // calulate time to stay active
multiple= seconds_to_run/3;

first_timer= multiple;
second_timer=multiple*2;//
third_timer=multiple*3;

full_power();                       // turn on leds full power

do
{
delay_ms(5);
if(get_voltage()>.5)        // only on when its dark, reads sensor
                             // Get_Voltage  A/D  routine
{
goto all_over;             // exit and shutdown
}
}while(sec_run<first_timer);  // 1st time interval

output_low(pin_B2);
delay_ms(10);                 // reset driver

two_thirds_power();           // 2/3 power

do
{
if(get_voltage()>.5)        // only  on when its dark
{
goto all_over;
}
 delay_ms(5);
}while(sec_run<second_timer);

output_low(pin_B2);
delay_ms(10);

one_third_power();         // 1/3 power

do
{
delay_ms(5);
if(get_voltage()>.5)        // only turn on when its dark
{
goto all_over;
}
}while(sec_run<third_timer);

all_over:

lite_leds=false;           // clear flag

output_low(pin_B2);        // turn off leds
output_low(pin_C0);        // turn off 1 hz led
clear_interrupt(int_ULPWU);
disable_interrupts(INT_TIMER2);
enable_interrupts(INT_ULPWU);
}

Float get_voltage()
{
// this is universal routine to get the input voltage so we can decide whether to pwm or not
int cntr;
long sum=0;
int samples=100;

delay_ms(5);

for(cntr=0;cntr<=samples;cntr++)
{
sum=read_adc()+sum;
delay_us(100);
}

input_volts= ((float)sum/(float)samples)* .019;

return input_volts;
}

void one_third_power(void)
{
byte x=0;
byte y=0;

// address 2
output_high(pin_b2);    /// tsetup

for(y=0;y<=4;y++)
{
   //for( x=0;x<=15;x++)
   //   {
     output_low(pin_b2);
     delay_us(1);
     output_high(pin_b2);
     delay_us(1);
    //  }
    // delay_us(10);
}

output_high(pin_b2);
}

void two_thirds_power(void)
{
byte x=0;
byte y=0;

// address 2

output_high(pin_b2);    /// tsetup

for(y=0;y<=9;y++)
{
   //for( x=0;x<=14;x++)
   //   {
     output_low(pin_b2);
     delay_us(1);
     output_high(pin_b2);
     delay_us(1);
    //  }
     //delay_us(10);
}
output_high(pin_b2);
}

void full_power(void)
{
int   x;
// address 2
output_high(pin_b2);    /// tsetup
delay_us(2);

for(x=0;x<=14;x++)
{
output_low(pin_b2);
delay_us(5);
output_high(pin_b2);
delay_us(5);
}
output_high(pin_b2);      // reset data
}

void power_up(void)
{
long multiple,first_timer,second_timer,third_timer;

seconds_to_run= minutes_to_run*60;
multiple= seconds_to_run/3;

first_timer= multiple;
second_timer=multiple*2;
third_timer=multiple*3;

full_power();

while(sec_run<first_timer);
output_low(pin_B2);
delay_ms(2);

two_thirds_power();
while(sec_run<second_timer);
output_low(pin_B2);
delay_ms(2);

one_third_power();

while(sec_run<third_timer);

no_run=false;

output_low(pin_B2);
}

void read_switch(void)
{
byte msb3,msb2,msb1,lsb;

set_tris_c(0b11110000);

output_high(pin_c2);
delay_ms(10);                         // set pin hi to energize

msb3 = input(pin_c7)*8;
msb2 = input(pin_c6)*4;
msb1 = input(pin_c5)*2;
lsb = input(pin_c4)*1;

minutes_to_run=msb3+msb2+msb1+lsb;
output_low(pin_c2);
//minutes_to_run=3;
set_tris_c(0b11111111);


}


//    ###############################            this is what starts the light on sequence
#INT_ULPWU
void ULPW_isr(void)
{
//######################## in order to get here the room light must be off

return;

if(get_voltage()>1)        // only turn on when its dark
{
return;
}

enable_interrupts(INT_EXT);
lite_leds=true;

delay_ms(15);
}

//#####################################
//#############################  pyro detector

#int_EXT            // this is pyro interrupt
void  EXT_isr(void)
{
if(get_voltage()>.5)        // only turn on when its dark
{
return;
}

lite_leds=true;
sec_run=0;

///power_up();
//return;
}

//################################### unused #int_TIMER2                  // seconds timer
void  TIMER2_isr(void)
{
tick_counter++;
if (tick_counter>20)
{
sec_run++;
output_toggle(pin_c0);
tick_counter=0;
}
}

void main()
{
   set_tris_A(0b11111111);
 
   setup_oscillator(OSC_4MHZ);
   setup_adc_ports(sAN1|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_spi(SPI_SS_DISABLED);
   set_adc_channel (1);
   
   clear_interrupt(int_ULPWU);
   
   //enable_interrupts(INT_ULPWU);
  // enable_interrupts(INT_EXT);            // pyro interrupt
   EXT_INT_EDGE(L_TO_H);
   setup_timer_2(T2_DIV_BY_16,187,16);

   read_switch();         // get timeout value

   PIE2=0B00000100;           // setup ULPWU Interrupt
   PCON=0B00100000;
   //  enable_interrupts(GLOBAL);
all_over:
   output_low(pin_C1); ///    led ground
   output_High(pin_A7);//      pyro test     

  sleep();

Delay_cycles(1);

if(get_voltage()>.5)        // in case of a false trip on sensor
{                           // recycle and wait 
goto all_over;
}

lite_the_leds();
 
 goto  all_over;
 
 }
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group