|
|
View previous topic :: View next topic |
Author |
Message |
Armondo522 Guest
|
SLEEP & ULPWU Help |
Posted: Fri May 29, 2009 8:31 am |
|
|
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
|
|
Posted: Fri May 29, 2009 8:50 am |
|
|
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
|
|
Posted: Fri May 29, 2009 9:04 am |
|
|
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
|
|
Posted: Fri May 29, 2009 2:39 pm |
|
|
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
|
|
Posted: Sat May 30, 2009 4:29 pm |
|
|
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;
} |
|
|
|
|
|
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
|