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

Nonresponding ADC...help?

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



Joined: 23 Nov 2008
Posts: 3

View user's profile Send private message

Nonresponding ADC...help?
PostPosted: Sun Nov 23, 2008 3:37 pm     Reply with quote

I have drafted and tested the firmware for a color-fading cube toy that will change R, G and B duty cycles based on the input from an analog accelerometer to the ADC. In summary, Timer1 interrupts are responsible for slowly fading the duty cycles to the accelerometer values. Timer0 is in charge of setting the ADC channel and reading off values. The main function is in charge of PWM on the three LEDs. I have the AD interrupt commented out, but I was attempting something clever there: interrupt on completion of ADC conversion, read value, set channel, start next conversion, end interrupt. I would like to use the AD interrupt, but right now the LEDs do not respond even with the simpler scheme, and I'm at a loss. Please, if somebody with more know-how has an idea, I could use some help.

compiler version: 4.038
target mc: 16f684
Standard run mode
Voltage is ~3.3
Oscillator is at 4Mhz
Code:

#include "C:\Program Files\PICC\Projects\tiltycubecolors.h"
 #define RED   PIN_A0
 #define GREEN   PIN_A1
 #define BLUE   PIN_A2
 #define X   PIN_C0
 #define Y   PIN_C1
 #define Z PIN_C2
 unsigned int Rduty, Gduty, Bduty, speed, counter;
 unsigned int Racc, Gacc, Bacc;
 unsigned int channel;
 
 #int_TIMER1
 void  TIMER1_isr(void)
 {
      if(Racc>Rduty&& Rduty < 128)
         Rduty++;
      else
         Rduty--;
 
      if (Bacc>Bduty && Bduty < 128)
         Bduty++;
      else
         Bduty--;
 
      if (Gacc>Gduty&& Gduty < 128)
         Gduty++;
      else
         Gduty--;
 }
 
 #int_TIMER2
 void  TIMER2_isr(void)
 {
 
 
 }
 
 #int_TIMER0
 void  TIMER0_isr(void)
 {
  set_adc_channel(4);
  delay_us(10);
  Bacc = read_adc();
 
  set_adc_channel(5);
  delay_us(10);
  Racc=read_adc();
 
  set_adc_channel(6);
  delay_us(10);
  Gacc = read_adc();
 
 }
 
 #int_AD
 void  AD_isr(void)
 {
 
 /*
        int temp;
         temp = read_adc(adc_read_only);
         temp = temp/2;
 
  //       if (channel == 4)
            Racc = temp;
         else if (channel == 5)
            Bacc = temp;
         else
            Gacc = temp;
 
  //       if (channel == 6)
            channel = 4;
  //       else
   //         channel++;
 
 
         set_adc_channel(0);
         delay_us(10);
         read_adc(adc_start_only);
       */
 }
 
 void main()
 {
   enable_interrupts(INT_AD);
   setup_adc_ports(setup_adc_ports(sAN4|sAN5|sAN6|VSS_VDD););
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_wdt(WDT_576MS);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
  //  setup_timer_2(T2_DIV_BY_16,0,1);
  //  setup_comparator(NC_NC_NC_NC);
 //   setup_vref(FALSE);
   enable_interrupts(INT_TIMER1);
  //  enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_4MHZ);
 
   // TODO: USER CODE!!
   channel = 4;
   while(1){
 
 
 
 
      counter++;
 
   if (counter<Gduty)
      output_high(GREEN);
 
   else
      output_low(GREEN);
 
   if (counter<Rduty)
      output_high(RED);
   else
      output_low(RED);
 
   if (counter<Bduty)
      output_high(BLUE);
   else
      output_low(BLUE);
 
   if (counter > 128)
      counter = 0;
   }
 }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Nov 23, 2008 3:50 pm     Reply with quote

1. Post your #include, #fuses, and #use delay() statements.


Quote:
Voltage is ~3.3

2. Post if this is from a voltage regulator.


3. Can you make the PIC do anything ? Can you make it blink an LED ?
Ttelmah
Guest







PostPosted: Sun Nov 23, 2008 4:07 pm     Reply with quote

First, get rid of int_ad, and enabling this.
Interrupts cannot be called inside one another. You are performing the AD conversions inside an interrupt already.
Do a search here, only a very few days ago, and several times in the past, I have posted why you don't want to use int_ad.
It actually takes _longer_ to get into and out of an ADC interrupt, than it does to handle it outside. The only reasons to ever use the ADC interrupt, are, first as a method of waking from sleep, when performing the ADC conversion with the processor suspended, and secondly, if you are triggering the ADC, using a CCP timer.
This latter could be used by you, but with difficulty, because of wanting to read multiple channels.
If you try to use the ADC interrupt as you show, you will never get out of the interrupt. The ADC will have finished conversion, before you return to the main code, and wll be called again...
Second comment, don't use ADC_CLOCK_INTERNAL.
Note4, Table9.1 in the data sheet.
For your clock speed, use the /8 divider.
Third comment. Use less interrupts. Just have one heartbeat timer. Have this at a frequency you can support. At present, you have too many things going on. Timer0, is interrupting every 256 instructions. It takes probably something over 180 instruction times to be called, execute, and return. Not much time for anything else.
Get rid off all the interrupts except Timer0. Halve it's frequency. Then have it run a state machine. On the first call, it selects the first ADC channel, and exits. On the second call, it starts the ADC conversion. On the third, it reads the first value, and selects the second ADC channel. On the fourth call it starts the conversion for the second channel. On the fifth call, it reads the second value, and selects the third channel. Have this go through all the channels required. On each call, you only perform either a reading, and a channel selection, or a trigger for the next channel. When you have completed the whole sequence, write the values to the PWM, and start the sequence again.
By selecting the channel in one call, the settling time needed is provided by the interval to the next. Then similarly, triggering the conversion, on the next call the conversion has finished, and the value is ready for you to read. Let the hardware work _for_ you, performing jobs while your main code does other things.

Best Wishes
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