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 CCS Technical Support

wakeup from sleep using wdt

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



Joined: 11 Jun 2007
Posts: 25

View user's profile Send private message MSN Messenger

wakeup from sleep using wdt
PostPosted: Fri Oct 09, 2009 2:06 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 09, 2009 2:37 am     Reply with quote

Need to see your fuse setting.
Ttelmah
Guest







PostPosted: Fri Oct 09, 2009 2:37 am     Reply with quote

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

View user's profile Send private message MSN Messenger

added fuses
PostPosted: Fri Oct 09, 2009 3:10 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 09, 2009 3:32 am     Reply with quote

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

View user's profile Send private message MSN Messenger

upgrade code
PostPosted: Fri Oct 09, 2009 4:02 am     Reply with quote

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 Wink
Ttelmah
Guest







PostPosted: Fri Oct 09, 2009 5:40 am     Reply with quote

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

View user's profile Send private message MSN Messenger

PostPosted: Fri Oct 09, 2009 6:21 am     Reply with quote

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

View user's profile Send private message MSN Messenger

upgrade version with adc turn off before trasmission...
PostPosted: Fri Oct 09, 2009 6:30 am     Reply with quote

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







PostPosted: Fri Oct 09, 2009 7:14 am     Reply with quote

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

View user's profile Send private message MSN Messenger

ADDED ADC CLOCK DIV 8
PostPosted: Fri Oct 09, 2009 8:08 am     Reply with quote

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??
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