|
|
View previous topic :: View next topic |
Author |
Message |
giustraman
Joined: 11 Jun 2007 Posts: 25
|
wakeup from sleep using wdt |
Posted: Fri Oct 09, 2009 2:06 am |
|
|
I'm projecting a temperature sensor and I want to measure thermal condition about every 500ms. To reduce power consumption I want to put my pic (12f675) into sleeping mode, thus I'm using wdt to wake up it. This is beta code:
Code: |
//dichiarazione variabili e inizializzazione
int16 temp, value_x;
int1 vett[48];
int count;
for(int i=0;i<48;i++)
vett[i]=0;
for(int i=0;i<16;i++)
{
if((i+1)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
set_adc_channel(0);
delay_us(10);
temp = read_adc();
temp=temp*10;
for(int i=0;i<15;i++)
{
if(temp%2==0)
{
vett[31-i]=0;
}
else
{
vett[31-i]=1;
}
temp=temp/2;
}
//ulteriore ingresso analogico
set_adc_channel(1);
delay_us(10);
value_x = read_adc();
value_x=value_x*10;
for(int i=0;i<16;i++)
{
if(value_x%2==0)
{
vett[47-i]=0;
}
else
{
vett[47-i]=1;
}
value_x=value_x/2;
}
//controllo parità
for(int i=0;i<48;i++)
if(vett[i]==1)
count++;
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
for(int i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(PIN_A2);
delay_us(666);
output_low(PIN_A2);
delay_us(333);
}
else
{
output_high(PIN_A2);
delay_us(333);
output_low(PIN_A2);
delay_us(666);
}
}
[color=red]setup_wdt (WDT_576MS)
sleep(); [/color]
} |
Someone can help me?? Thanks. |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Oct 09, 2009 2:37 am |
|
|
Need to see your fuse setting. |
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 09, 2009 2:37 am |
|
|
Lots of comments:
First, how close needs the timing to be?. The Watchdog, is awfully inaccurate. Even on the 'standard' chip, at 5v, the timing from the nominal 576mSec setting, can vary from 224mSec, to 1056mSec. You need to be aware of this...
Then, when the chip awakens, if you are using a crystal oscillator, there is another 72mSec possible delay, for the oscillator to restart and stabilise. Brings the timings up to 296 to 1128mSec. Is this going to be acceptable?.
Now, on this chip, the WDT, has to be enabled in the fuses, and once enabled, runs all the time. Unlike some of the 18 series chips, where you can turn the WDT on/off from code, on this chip, the enable is permanent. This means you need to ensure that your normal running code, keeps the watchdog cleared, or you will end up resetting. On this chip, the timing can be set 'in line', so program the watchdog to it's maximum interval at boot, and make sure you are restarting it at regular intervals in the code. After the sleep, turn the interval back up.
On the code you post, remember you need a ';' after the setup_wdt line....
Then, you need to be aware that the instruction _after_ the sleep, has been 'prefetched' before you go to sleep, so the 'safest' thing, is to add the line:
delay_cycles(1);
after the sleep, which codes as a 'nop', to ensure there are no unexpected results from this pre-fetch.
Best Wishes |
|
|
giustraman
Joined: 11 Jun 2007 Posts: 25
|
added fuses |
Posted: Fri Oct 09, 2009 3:10 am |
|
|
Code: | #include <12F675.h>
#device adc=10
#FUSES WDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BANDGAP_HIGH
#use delay(clock=4000000)
#include "C:\Documents and Settings\Administrator\Desktop\prova\12f675.h"
int16 temp,value_x;
int1 vett[48];
int count;
int i;
#int_RTCC
void RTCC_isr(void)
{
}
void main()
{
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_wdt(WDT_576MS);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for(i=0;i<48;i++)
{
vett[i]=0;
}
for(i=0;i<16;i++)
{
if((i+1%2)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
set_adc_channel(0);
temp=read_adc();
delay_us(10);
for(i=0;i<15;i++)
{
if(temp%2==0)
vett[31-i]=0;
else
vett[31-i]=1;
temp=temp/2;
}
//ulteriore uingresso analogico
set_adc_channel(1);
value_x=read_adc();
delay_us(10);
for(i=0;i<16;i++)
{
if(value_x%2==0)
vett[47-i]=0;
else
vett[47-i]=1;
value_x=value_x/2;
}
//controllo parità
for(i=0;i<48;i++)
{
if(vett[i]==1)
count++;
}
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
setup_wdt(WDT_576MS);
for(i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(pin_A2);
delay_us(666);
output_low(pin_A2);
delay_us(333);
}
else
{
output_high(pin_A2);
delay_us(333);
output_low(pin_A2);
delay_us(666);
}
}
sleep();
}
} |
Ambient temperature changes slowly and I prefer to use the watch dog timer (even if it is inaccurate to make) every 500 ms to measure the thermal condition ... The circuit has a transmitter (434 MHz AM Transmitter OOK) is a receiver (434 Mhz Standard OOK Receiver). Every bit is sent approximately every 1 ms, changing the A2 pin state.
My aim is turn off pic to reduce power consumption using wdt...Have I complete code entering:
"restart_wdt()"
??? And where have I put it??? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Oct 09, 2009 3:32 am |
|
|
Place setup_wdt() where you want to start the wake interval. It can e.g. work, as you did it. restart_wdt() would be only needed, if the code execution lasts too long.
In addition, you should care, that all current consuming resource are shut down, e.g. setup_adc(ADC_OFF), all pins driving a load to inactive, no floating input pins. |
|
|
giustraman
Joined: 11 Jun 2007 Posts: 25
|
upgrade code |
Posted: Fri Oct 09, 2009 4:02 am |
|
|
Code: | #include <12F675.h>
#device adc=10
#FUSES WDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BANDGAP_HIGH
#use delay(clock=4000000)
#include "C:\Documents and Settings\Administrator\Desktop\prova\12f675.h"
int16 temp,value_x;
int1 vett[48];
int count;
int i;
#int_RTCC
void RTCC_isr(void)
{
}
void main()
{
//setup_adc_ports(sAN0|sAN1|VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_wdt(WDT_576MS);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for(i=0;i<48;i++)
{
vett[i]=0;
}
for(i=0;i<16;i++)
{
if((i+1%2)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
temp=read_adc();
delay_us(10);
for(i=0;i<15;i++)
{
if(temp%2==0)
vett[31-i]=0;
else
vett[31-i]=1;
temp=temp/2;
}
//ulteriore uingresso analogico
set_adc_channel(1);
value_x=read_adc();
delay_us(10);
for(i=0;i<16;i++)
{
if(value_x%2==0)
vett[47-i]=0;
else
vett[47-i]=1;
value_x=value_x/2;
}
//controllo parità
for(i=0;i<48;i++)
{
if(vett[i]==1)
count++;
}
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
setup_wdt(WDT_576MS);
for(i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(pin_A2);
delay_us(666);
output_low(pin_A2);
delay_us(333);
}
else
{
output_high(pin_A2);
delay_us(333);
output_low(pin_A2);
delay_us(666);
}
}
setup_adc(ADC_OFF);
sleep();
delay_cycles(1);
}
} |
Have I missing anything??
Thanks, best regards |
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 09, 2009 5:40 am |
|
|
Put the delays after setting the ADC channel, not after the reading. The ADC input is electrically a capacitor, fed from an internal resistor. It takes _time_ to charge to a newly selected voltage. You are allowing none, so your readings will be invalid...
If you want accuracy, don't use 'ADC_CLOCK_INTERNAL, unless you are going to put the chip to sleep when doing the reading. Read the data sheet.
Best Wishes |
|
|
giustraman
Joined: 11 Jun 2007 Posts: 25
|
|
Posted: Fri Oct 09, 2009 6:21 am |
|
|
I added 20us delay between the two analog inputs... About precision I'm realizing a circuit for temperature measure...
Code: | #include <12F675.h>
#device adc=10
#FUSES WDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BANDGAP_HIGH
#use delay(clock=4000000)
#include "C:\Documents and Settings\Administrator\Desktop\trasmettitore\12f675.h"
int16 temp,value_x;
int1 vett[48];
int count;
int i;
#int_RTCC
void RTCC_isr(void)
{
}
void main()
{
//setup_adc_ports(sAN0|sAN1|VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_wdt(WDT_576MS);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for(i=0;i<48;i++)
{
vett[i]=0;
}
for(i=0;i<16;i++)
{
if((i+1%2)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(10);
temp=read_adc();
for(i=0;i<15;i++)
{
if(temp%2==0)
vett[31-i]=0;
else
vett[31-i]=1;
temp=temp/2;
}
//ulteriore uingresso analogico
delay_us(20);
set_adc_channel(1);
delay_us(10);
value_x=read_adc();
for(i=0;i<16;i++)
{
if(value_x%2==0)
vett[47-i]=0;
else
vett[47-i]=1;
value_x=value_x/2;
}
//controllo parità
for(i=0;i<48;i++)
{
if(vett[i]==1)
count++;
}
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
setup_wdt(WDT_576MS);
for(i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(pin_A2);
delay_us(666);
output_low(pin_A2);
delay_us(333);
}
else
{
output_high(pin_A2);
delay_us(333);
output_low(pin_A2);
delay_us(666);
}
}
setup_adc(ADC_OFF);
sleep();
delay_cycles(1);
}
} |
Do you think my solution can much influence termal precision? Can you help me about it?? |
|
|
giustraman
Joined: 11 Jun 2007 Posts: 25
|
upgrade version with adc turn off before trasmission... |
Posted: Fri Oct 09, 2009 6:30 am |
|
|
Turn off adc:
...
setup_wdt(WDT_576MS);
setup_adc(ADC_OFF);
...
Code: | #include <12F675.h>
#device adc=10
#FUSES WDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BANDGAP_HIGH
#use delay(clock=4000000)
#include "C:\Documents and Settings\Administrator\Desktop\trasmettitore\12f675.h"
int16 temp,value_x;
int1 vett[48];
int count;
int i;
#int_RTCC
void RTCC_isr(void)
{
}
void main()
{
//setup_adc_ports(sAN0|sAN1|VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_wdt(WDT_576MS);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for(i=0;i<48;i++)
{
vett[i]=0;
}
for(i=0;i<16;i++)
{
if((i+1%2)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(10);
temp=read_adc();
for(i=0;i<15;i++)
{
if(temp%2==0)
vett[31-i]=0;
else
vett[31-i]=1;
temp=temp/2;
}
//ulteriore uingresso analogico
delay_us(20);
set_adc_channel(1);
delay_us(10);
value_x=read_adc();
for(i=0;i<16;i++)
{
if(value_x%2==0)
vett[47-i]=0;
else
vett[47-i]=1;
value_x=value_x/2;
}
//controllo parità
for(i=0;i<48;i++)
{
if(vett[i]==1)
count++;
}
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
setup_wdt(WDT_576MS);
setup_adc(ADC_OFF);
for(i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(pin_A2);
delay_us(666);
output_low(pin_A2);
delay_us(333);
}
else
{
output_high(pin_A2);
delay_us(333);
output_low(pin_A2);
delay_us(666);
}
}
sleep();
delay_cycles(1);
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Fri Oct 09, 2009 7:14 am |
|
|
Look at table 7-1 'Tad versus Device operating Frequencies'. For 4MHz, use ADC_CLOCK_DIV_8.
Read the line under the table:
"When the device frequency is greater than 1MHz, the ADC R/C clock source is only recommended if the conversion will be performed during sleep."
Basically, there is no point in selecting ADC=10, and trying for 10bit ADC accuracy, if you are going to use the wrong clock source. There is no advantage to useing the RC clock, in your code, so why do it?.
The reason to use the RC source, would be if you put the chip to sleep, for the actual ADC readings, since then you need this source (which keeps running during the sleep), and in this circumstance (with the main oscillator stopped), this then gives the best possible accuracy. Otherwise, _don't use it_, except at very slow master clock rates.
Best Wishes |
|
|
giustraman
Joined: 11 Jun 2007 Posts: 25
|
ADDED ADC CLOCK DIV 8 |
Posted: Fri Oct 09, 2009 8:08 am |
|
|
Code: | #include <12F675.h>
#device adc=10
#FUSES WDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BANDGAP_HIGH
#use delay(clock=4000000)
#include "C:\Documents and Settings\Administrator\Desktop\trasmettitore\12f675.h"
int16 temp,value_x;
int1 vett[48];
int count;
int i;
#int_RTCC
void RTCC_isr(void)
{
}
void main()
{
//setup_adc_ports(sAN0|sAN1|VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_wdt(WDT_576MS);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for(i=0;i<48;i++)
{
vett[i]=0;
}
for(i=0;i<16;i++)
{
if((i+1%2)%2==1)
vett[i]=1;
else
vett[i]=0;
}
while(1)
{
//temperatura
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
delay_us(10);
temp=read_adc();
for(i=0;i<15;i++)
{
if(temp%2==0)
vett[31-i]=0;
else
vett[31-i]=1;
temp=temp/2;
}
//ulteriore uingresso analogico
delay_us(20);
set_adc_channel(1);
delay_us(10);
value_x=read_adc();
for(i=0;i<16;i++)
{
if(value_x%2==0)
vett[47-i]=0;
else
vett[47-i]=1;
value_x=value_x/2;
}
//controllo parità
for(i=0;i<48;i++)
{
if(vett[i]==1)
count++;
}
for(i=0;i<48;i++)
{
if(count%2==1)
vett[16]=1;
}
setup_wdt(WDT_576MS);
for(i=0;i<48;i++)
{
if(vett[i]==1)
{
output_high(pin_A2);
delay_us(666);
output_low(pin_A2);
delay_us(333);
}
else
{
output_high(pin_A2);
delay_us(333);
output_low(pin_A2);
delay_us(666);
}
}
setup_adc(ADC_OFF);
sleep();
delay_cycles(1);
}
} |
Do you thing there are other errors in this transmission code?? |
|
|
|
|
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
|