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

Problems with sleep and the ADC on the PIC 12CE674

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



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

Problems with sleep and the ADC on the PIC 12CE674
PostPosted: Tue Sep 28, 2004 12:47 pm     Reply with quote

Hey:
I've got some code that's doing something screwy: it's driving Pin 6 (GP1) low even though I've set it a bunch of times to be an input and an analog one at that. The chip's mostly in sleep mode, but it's using WDT events to wake up, so it should just be restarting. I am using the right pointers, have the chip hooked up correctly (no shorts to ground!), set the ADC up right, etc. In the actual code I'm really pushing the chip (using both Timer0 and WDT and all the pins in various manners). Anyone had this same problem?

Here's the code:

#include <12CE674.h>
#device PIC12CE674 *=8 ADC=8


#include <math.h>

#use delay(clock=4000000)
#use fast_io(A)

#fuses INTRC,WDT,PUT,NOPROTECT,NOMCLR//,NOBROWNOUT // Need to fix this piece of it


#rom 0x7ff = {0x3494} // This is for a 12CE674 Device


#define VOLTAGE_CHANNEL 1 // Correct
#define MAXVOLTAGE 199 // This should correspond to 12.6 volts for an 8 bit A/D
#define MINVOLTAGE 141 // This should correspond to 9 volts for an 8 bit A/D
#define NINEpONE 143 // This should correspond to 9.1 volts for an 8 bit A/D
#define NINEpFIVE 168
//#define WATCHDOG_TIMER


#define THERM_CHANNEL 0
#define MAXTEMP 204 // This corresponds with 65 degrees, and let's the operator know he's about to die

#define GREENLED PIN_A2 // Correct
#define REDLED PIN_A4 // Correct
#define BULB PIN_A5 // Correct
#define BUTTON PIN_A3 // Correct

#define CONSTANT0 4080 // This defines the duty cycle for the LED

//#byte STATUS_REG = 03h

// Global Variables

int1 green_led_state=0, red_led_state=0;
int1 green_led_flash=0, red_led_flash=0;
int duty_cycle;
long dummy=0;
int constant=CONSTANT0;
int pressnumber;

// This receives the last A/D conversion
int value;

// This is the main counter for the pwm
int pwm=0, duty=0;

int1 start=0, lamp_on=0;

#INT_TIMER0
void PWMoutput()
{
pwm++;
if (pwm == 256) {
pwm=0;
if (lamp_on) { output_high(BULB); }
}

if (duty == pwm)
{
output_low(BULB);
}

if ((!start) && (lamp_on)) // Lamp has not been started yet
{
if (duty<duty_cycle) duty++;
}
} // End PWMoutput

void buttonpress()
{
if (!(input(BUTTON))) {
pressnumber++;
if (pressnumber>=3)
{
pressnumber=0;
}
delay_ms(100);
restart_wdt();
}
}

void sandman()
{
lamp_on=0;
output_low(BULB);
disable_interrupts(INT_TIMER0);
while (pressnumber==0)
{
buttonpress();
sleep();
}
}

void startbackup()
{
setup_wdt(WDT_1152MS);
enable_interrupts(INT_TIMER0);

set_tris_a(0x0B); // Setup the register as follows: 0b0001011 Correct (ones are inputs)

setup_adc_ports(AN0_AN1_ANALOG); // Set all of these pins as analog inputs
setup_adc(ADC_CLOCK_DIV_32); // Set the clock for the fastest mode, not that it matters



}

void flash_redgreen()
{
int i;

for (i=0; i<10; i++)
{
restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
output_high(GREENLED);
output_low(REDLED);
restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
output_low(GREENLED);
output_high(REDLED);

}
output_low(REDLED);
pressnumber=0;
sandman();
startbackup();
}



void flash_red()
{

int8 i;

output_low(GREENLED);

for (i=0; i<10; i++)
{
buttonpress();
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
output_low(REDLED);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
restart_wdt();
delay_ms(100);
output_high(REDLED);

}
pressnumber=0;
sandman();
startbackup();

}



main ()
{

byte value;
int i;

// Setup Pins

pressnumber=0;


set_tris_a(0x0B); // Setup the register as follows: 0b0001011 (ones are inputs)
setup_adc_ports(AN0_AN1_ANALOG); // Set all of these pins as analog inputs
setup_adc(ADC_CLOCK_DIV_32);



setup_timer_0(RTCC_INTERNAL); // This will give us overflows every 255 instructions, just fine for PWM work

setup_wdt(WDT_1152MS); // We have to set this afterwards so the prescaler does it's thing

enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);


output_high(GREENLED);
output_low(BULB);

delay_ms(100);
output_low(GREENLED);
output_low(REDLED);

restart_wdt();

delay_ms(100);
restart_wdt();

if (restart_cause() == WDT_TIMEOUT)
{
output_high(GREENLED);
output_high(REDLED);
restart_wdt();
while (1) {
delay_ms(100);
sleep();
}
}

// The interrupt turn ons were here...


// First, check to see if the temp is out of range. If so, go to redgreen flash routine


while (1)
{
buttonpress();
if (pressnumber==0)
{
output_low(REDLED);
output_low(GREENLED);
sandman();
startbackup();

set_adc_channel(THERM_CHANNEL);
value = read_adc();

if (value>=MAXTEMP)
{
flash_redgreen();
}
setup_wdt(WDT_1152MS);


}
restart_wdt();

set_adc_channel(VOLTAGE_CHANNEL);
value=read_adc();

dummy=constant/value;
dummy=dummy/value;

duty_cycle=dummy;

if (value<MINVOLTAGE) // We need to soft charge the battery
{
flash_red();
}

if (value>NINEpFIVE)
{
output_high(GREENLED);
output_low(REDLED);
}
else if (value>NINEpONE)
{
output_low(GREENLED);
output_high(REDLED);
}
else
{
duty_cycle=(duty_cycle/4);
restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
restart_wdt();
output_low(REDLED);
delay_ms(250);
restart_wdt();
delay_ms(250);
restart_wdt();
output_high(REDLED);
}


if (pressnumber==1)
{
lamp_on=1;
}
if (pressnumber==2)
{
duty_cycle=duty_cycle/2;
}

restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
restart_wdt();
delay_ms(250);
restart_wdt();


// end main loop


}
}
[/code]
_________________
To watch plants grow, blink more slowly.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 28, 2004 1:24 pm     Reply with quote

Quote:
The chip's mostly in sleep mode, but it's using WDT events to wake up, so it should just be restarting.

That's not true. If you read section 9.8.1, WAKE-UP FROM SLEEP,
http://ww1.microchip.com/downloads/en/DeviceDoc/30561b.pdf
in the 12CE674 data sheet, it says:
Quote:
External MCLR Reset will cause a device reset. All
other events are considered a continuation of program
execution and cause a "wake-up".

So a WDT wakeup does not cause it to restart. It causes it
to continue program execution.

I didn't look closely at your code because you put it in italics,
which makes it very hard to read. If you need us to look
further at your code, please edit your post and use the "Code"
button to highlight your code instead of italics. (And post a new
reply, to let us know that you did this.)
Leif Steinhour



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

Correction
PostPosted: Tue Sep 28, 2004 2:41 pm     Reply with quote

I meant "continuing" rather than "resetting". I knew about that, and the code is planned accordingly. As per your request, here's the code in the correct format:
Code:


#include <12CE674.h>
#device PIC12CE674 *=8 ADC=8


#include <math.h>

#use delay(clock=4000000)
#use fast_io(A)

#fuses INTRC,WDT,PUT,NOPROTECT,NOMCLR//,NOBROWNOUT  // Need to fix this piece of it

#rom 0x7ff = {0x3494}        // This is for a 12CE674 Device


#define VOLTAGE_CHANNEL 1   //
#define MAXVOLTAGE 199      // This should correspond to 12.6 volts for an 8 bit A/D
#define MINVOLTAGE 141      // This should correspond to 9 volts for an 8 bit A/D
#define NINEpONE   143      // This should correspond to 9.1 volts for an 8 bit A/D
#define NINEpFIVE  168

#define THERM_CHANNEL 0
#define MAXTEMP 204        // This corresponds with 65 degrees, and let's the operator know he's about to die

#define GREENLED   PIN_A2  //
#define REDLED     PIN_A4  //
#define BULB       PIN_A5  //
#define BUTTON     PIN_A3  //

#define CONSTANT0  4080       // This defines the duty cycle for the LED

// Global Variables

int1 green_led_state=0, red_led_state=0;
int1 green_led_flash=0, red_led_flash=0;
int duty_cycle;
long dummy=0;
int constant=CONSTANT0;
int pressnumber;

// This receives the last A/D conversion
int value;

// This is the main counter for the pwm
int pwm=0, duty=0;

int1 start=0, lamp_on=0;

#INT_TIMER0
void PWMoutput()
{
pwm++;
if (pwm == 256) {
                  pwm=0;
                  if (lamp_on) { output_high(BULB); }
                }

if (duty == pwm)
{
   output_low(BULB);
}

if ((!start) && (lamp_on)) // Lamp has not been started yet
{
  if (duty<duty_cycle) duty++;
}
}  // End PWMoutput

void buttonpress()
{
if (!(input(BUTTON))) {
      pressnumber++;
      if (pressnumber>=3)
      {
         pressnumber=0;
      }
      delay_ms(100);
      restart_wdt();
   }
}

void sandman()
{
lamp_on=0;
output_low(BULB);
disable_interrupts(INT_TIMER0);
while (pressnumber==0)
   {
      buttonpress();
      sleep();
   }
}

void startbackup()
{
   setup_wdt(WDT_1152MS);
   enable_interrupts(INT_TIMER0);

  set_tris_a(0x0B);  // Setup the register as follows: 0b0001011 
   setup_adc_ports(AN0_AN1_ANALOG);  // Set all of these pins as analog inputs
   setup_adc(ADC_CLOCK_DIV_32);        // Set the clock for the fastest mode, not that it matters



}

void flash_redgreen()
{
  int i;

  for (i=0; i<10; i++)
    {
        restart_wdt();
        delay_ms(250);
        restart_wdt();
        delay_ms(250);
        output_high(GREENLED);
        output_low(REDLED);
        restart_wdt();
        delay_ms(250);
        restart_wdt();
        delay_ms(250);
        output_low(GREENLED);
        output_high(REDLED);

    }
    output_low(REDLED);
    pressnumber=0;
    sandman();
    startbackup();
}



void flash_red()
{

  int8 i;

   output_low(GREENLED);

   for (i=0; i<10; i++)
   {
   buttonpress();
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    output_low(REDLED);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    restart_wdt();
    delay_ms(100);
    output_high(REDLED);

   }
   pressnumber=0;
   sandman();
   startbackup();

}



main ()
{

  byte value;
  int i;

  // Setup Pins

   pressnumber=0;


   set_tris_a(0x0B);  // Setup the register as follows: 0b0001011
   setup_adc_ports(AN0_AN1_ANALOG);  // Set all of these pins as analog inputs
   setup_adc(ADC_CLOCK_DIV_32);        // Set the clock for the fastest mode, not that it matters


   setup_timer_0(RTCC_INTERNAL);  // This will give us overflows every 255 instructions, just fine for PWM work

   setup_wdt(WDT_1152MS);   // We have to set this afterwards so the prescaler does it's thing

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_TIMER0);


   output_high(GREENLED);
   output_low(BULB);

   delay_ms(100);
   output_low(GREENLED);
   output_low(REDLED);

   restart_wdt();

   delay_ms(100);
   restart_wdt();

   if (restart_cause() == WDT_TIMEOUT)
      {
         output_high(GREENLED);
         output_high(REDLED);
         restart_wdt();
         while (1) {
         delay_ms(100);
         sleep();
         }
      }

      // The interrupt turn ons were here...


   // First, check to see if the temp is out of range. If so, go to redgreen flash routine


   while (1)
      {
         buttonpress();
         if (pressnumber==0)
         {
            output_low(REDLED);
            output_low(GREENLED);
            sandman();
            startbackup();

           set_adc_channel(THERM_CHANNEL);
           value = read_adc();

           if (value>=MAXTEMP)
              {
                 flash_redgreen();
              }
           setup_wdt(WDT_1152MS);


         }
         restart_wdt();

         delay_ms(100);
         restart_wdt();

         set_adc_channel(VOLTAGE_CHANNEL);
         value=read_adc();

         dummy=constant/value;
         dummy=dummy/value;

         duty_cycle=dummy;

         if (value<MINVOLTAGE)   // We need to soft charge the battery
           {
              flash_red();
           }

         if (value>NINEpFIVE)
            {
               output_high(GREENLED);
               output_low(REDLED);
             }
         else if (value>NINEpONE)
            {
               output_low(GREENLED);
               output_high(REDLED);
            }
         else
            {
               duty_cycle=(duty_cycle/4);
               restart_wdt();
               delay_ms(250);
               restart_wdt();
               delay_ms(250);
               restart_wdt();
               output_low(REDLED);
               delay_ms(250);
               restart_wdt();
               delay_ms(250);
               restart_wdt();
               output_high(REDLED);
            }


         if (pressnumber==1)
         {
         lamp_on=1;
     //       output_low(GREENLED);
     //       output_high(REDLED);
         }
         if (pressnumber==2)
         {
            duty_cycle=duty_cycle/2;
          //  output_high(GREENLED);
          //  output_low(REDLED);
         }

         restart_wdt();
         delay_ms(250);
         restart_wdt();
         delay_ms(250);
         restart_wdt();
         delay_ms(250);
         restart_wdt();
         delay_ms(250);
         restart_wdt();
         // output_high(REDLED);
         // If the switch is pressed after a soft start, then reduce the duty cycle by 50%
        // Otherwise turn it off


   // main loop


   }
}

_________________
To watch plants grow, blink more slowly.
Ttelmah
Guest







PostPosted: Tue Sep 28, 2004 2:59 pm     Reply with quote

You say that the code is written to handle the fact that a watchdog 'continues', from a sleep, but it doesn't really look like it is.
As it stands, the code will have sit looping in the sleep, delaying 100mSec, then going to sleep, waking, executing the allready fetched loop instruction, delaying 100mSec, sleeping again etc..
If you want the chip to restart from the watchdog, you need to sit in a loop for a couple of seconds or more (remember the watchdog 'times' are very approximate), without the sleep instruction, which will then force the watchdog, to trigger a restart. Simply coding 'while(true);' will force a watchdog restart if it is enabled. Otherwise, if you want it to continue (which you then seem to show), code with a layout like:
initialise.
sleep
dummy instruction (delay_us(1))
If you get here the chip has woken from the watchdog.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 28, 2004 3:35 pm     Reply with quote

A couple things before we go any further:

1. What is the version of your compiler ?
This will be a number like 3.188 or 3.212, etc.
You can find it at the top of your list file (.LST)
after you compile a program.

2. You have tons and tons of code like this:
Code:

        restart_wdt();
        delay_ms(250);
        restart_wdt();
        delay_ms(250);


The #use delay() statement has an optional parameter which
tells the compiler to add code to restart the WDT when it's doing
a delay. If you add this parameter, then you don't need to do
code like you have above. You can clean up your program.
Example:
#use delay(clock=4000000, restart_wdt)
Leif Steinhour



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

Compiler Version, etc.
PostPosted: Tue Sep 28, 2004 4:19 pm     Reply with quote

PCM 3.137 on the compiler. I'll definitely take advantage of the #USE directive, that sure makes things cleaner.
_________________
To watch plants grow, blink more slowly.
Leif Steinhour



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

PostPosted: Tue Sep 28, 2004 4:29 pm     Reply with quote

Ttelmah wrote:
You say that the code is written to handle the fact that a watchdog 'continues', from a sleep, but it doesn't really look like it is.
As it stands, the code will have sit looping in the sleep, delaying 100mSec, then going to sleep, waking, executing the allready fetched loop instruction, delaying 100mSec, sleeping again etc..
If you want the chip to restart from the watchdog, you need to sit in a loop for a couple of seconds or more (remember the watchdog 'times' are very approximate), without the sleep instruction, which will then force the watchdog, to trigger a restart. Simply coding 'while(true);' will force a watchdog restart if it is enabled. Otherwise, if you want it to continue (which you then seem to show), code with a layout like:
initialise.
sleep
dummy instruction (delay_us(1))
If you get here the chip has woken from the watchdog.

Best Wishes



It's waiting for a button press, and once it gets one (making pressnumber=1) it exits the loop. All that stuff works, the problem is with the AN1 line. No matter what I do the line seems to get tied low, and I'm sure it's not because of a short, having tested it out pretty thoroughly. I've also tried a couple of different chips and they all seem to be exhibiting this same behaviour, so I'm reasonably sure it's something the program is doing...
_________________
To watch plants grow, blink more slowly.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Sep 28, 2004 6:11 pm     Reply with quote

Code:

int pwm=0, duty=0;

int1 start=0, lamp_on=0;

#INT_TIMER0
void PWMoutput()
{
pwm++;
if (pwm == 256) {
                  pwm=0;
                  if (lamp_on) { output_high(BULB); }
                }


You know that an int is 8 bits in CCS, right?? PWM won't ever get to 256.



Code:

 value=read_adc();

         dummy=constant/value;
         dummy=dummy/value;


What happens when value == 0!
Leif Steinhour



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

Int problem
PostPosted: Wed Sep 29, 2004 10:48 am     Reply with quote

Surre, that's definitely a typo and a problem, thanks for bringing that to my attention. Having said that, it will skip over that line as it goes past, which is unrelated to the problem I'm worried about: it's grounding AN1 and shouldn't be. I'm pretty sure it shouldn't be having a problem with that line, and yet it is.
_________________
To watch plants grow, blink more slowly.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 29, 2004 11:43 am     Reply with quote

My suggestion is to make a small program that only tests for
the AN1 problem. If you still can't make it work, then post
the test program.
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Wed Sep 29, 2004 12:06 pm     Reply with quote

You need to delay after changing the ADC channel. Try 20uS.
_________________
David
Leif Steinhour



Joined: 28 Sep 2004
Posts: 6

View user's profile Send private message

Fixed it
PostPosted: Wed Sep 29, 2004 4:32 pm     Reply with quote

Thank you, that was it. If anyone else has this problem, the symptom is an intermittent tie to ground.
_________________
To watch plants grow, blink more slowly.
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