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

delay in the adc_read 18f2550

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



Joined: 18 Jun 2010
Posts: 5

View user's profile Send private message

delay in the adc_read 18f2550
PostPosted: Fri Jun 18, 2010 8:25 am     Reply with quote

hello,

I'm new here and need some advice about how to use efficiently the adc in my pic. I am using pic 18F2550, and need to get data from the adc convert when my motors are rotating ...
I tried directly to read the data in the code.
Code:

void main()
{
   unsigned int8 i;
        int32 dataRead;
   //***************************************
   //***** Configuration du PIC18F2550 *****
   //***************************************
   
// ************ Code que j'ai mis en commentaire empêcher de voir en entrer que le PIN A0 recevait des informations
   setup_adc_ports(AN0_TO_AN3|VSS_VDD);  //Utilisation des entrées analogique AN0 - tension de 0 à Vdd 
   setup_adc(ADC_CLOCK_INTERNAL);     //Utilisation de l'horloge interne pour le conversion en analogique
//   setup_adc(ADC_CLOCK_DIV_4);
   setup_wdt(WDT_OFF);

   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
   setup_timer_2(T2_DIV_BY_16, 124, 1); // 124 = 2Khz
   setup_timer_3(T3_INTERNAL|T3_DIV_BY_4);

   setup_ccp1(CCP_COMPARE_INT_AND_TOGGLE);
   setup_ccp2(CCP_COMPARE_INT_AND_TOGGLE|CCP_USE_TIMER3);

   enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_CCP1);
   enable_interrupts(INT_CCP2);
   if (MotorID !=0){
      enable_interrupts(INT_RDA);
   //   enable_interrupts(INT_AD);
   }
   enable_interrupts(GLOBAL);
   

   //setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_low_volt_detect(FALSE);
   setup_oscillator(False);

   //configuration des ports en entrées/sorties - par défaut, les configurer en entrées
   //set_tris_a(0b00001111);//port A en entrées ('1' = IN, '0' = OUT)
   //set_tris_b(0b00000000);//Pin B4 et B5 en sorties, les autres en entrées
   //set_tris_c(0b00000000);//Pin B4 et B5 en sorties, les autres en entrées
   
   set_tris_a(0b000001);//port A en entrées ('1' = IN, '0' = OUT)
   if (MotorID !=0)
      set_tris_b(0b00000001);//Pin B4 et B5 en sorties, les autres en entrées
      
   //set_tris_b(0b11111111); ::ca c'est moi
   set_tris_c(0b00000000);//Pin B4 et B5 en sorties, les autres en entrées

   //output_drive(PIN_C1);
      
   #use fast_io (A)
   #use fast_io (B)
   #use fast_io (C)
      
   // Initialisation   
   for (i=0;i<4;i++)
   {
      analog_1[i]=0;
      analogFilter[i]=0.0;
      analogFilter_1[i]=0.0;
   }
   for (i=0;i<8;i++)
   {
         outData[i]=0;
         outSensorData[i]=0;
         outDataFlag[i]=0;
         dataZBTran[i]=0;
//         dataRcvCpu[i] = 42;
   }
   dataZBTran[2] = MotorID;
   
   for (i=0;i<33;i++){
      if (i !=1)
         dataZBSend[i] = 0;
      dataZBRcv[i] = 0;
   }
   dataZBSend[2] = MotorID;
   

   timer=0;
   time=0;
   flagWhile = 0;
   
   if (MotorId!=0){
      set_adc_channel(0);
      angleIni = read_adc();
      angleIni = (int32)((angleIni*360)/1024);
      printf("angle Ini :%Lu \n",angleIni);   
   }
   
   
   usb_init();

///********************************************
///******************* Moteurs ***************
///********************************************
   
   // tensions moteurs
   if (MotorID !=0){
      output_high(PIN_B5);
      output_high(PIN_B3);
      output_high(PIN_B6);
      output_high(PIN_B7);
   }

   speedWanted1 =1000;
   CCP_1 = (long)(112500/speedWanted1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
   output_low(PIN_B3);
   output_low(PIN_B2);

   
   while (TRUE)
   {   
               set_adc_channel(0);  // the adc is on the PIN_A0
               dataRead = read_adc();
   } // while
} // main

When I'm using my motors there are stops during the rotation of the motors because when I comment it, it turns at the speed without interruption.
Can someone helps me :D
thanks,

P.S: excuse me for my English I'm a foreigner


Last edited by dronix on Fri Jun 18, 2010 9:59 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 8:55 am     Reply with quote

The ADC conversion takes typically 11 cycles of the ADC clock.
First comment, don't use ADC_CLOCK_INTERNAL. You don't say what your clock rate is, but this ADC clock is not recommended for use about 1MHz.....
This will also be making the timing worse, since with the RC clock selected, the ADC waits for an extra cycle before starting the conversion, and the internal RC source takes typically twice the time that is needed....
You can't sample the ADC continuously. You have the main loop reading the ADC 'non stop', but their is a _requirement_ for a minimum delay of Tacq, _between_ successive read cyles of the ADC.
Now, with these said, Yo need to perform the ADC operations at some point in your interrupts (you don't show these), but taking advantage of existing time delays, and performing the ADC operations 'in parts', with the hardware working while you are doing other things. For example:
Code:


val=read_adc(); //This will pause for 11*ADC_CLOCK.....

//instead.
void timer(void) {
   static int8 state=0;
   switch (state) {
   case 0:
       read_adc(ADC_START_ONLY);
       state=1; //This will trigger the ADC to _start reading_, but not wait.
   case 1:
       //Provided there has been a time interval of at least 11*ADC_CLOCK
       //between successive interrupts, the value can be read _without_
       //delay.
       dataRead=read_adc(ADC_READ_ONLY);
       state=0;
       break;
   }
   //Other interrupt code
}

So you take advantage of an existing timing event to provide both the Tacq delay, and the time for the hardware to read the ADC.

A search here will find a lot of other examples.

Best Wishes
dronix



Joined: 18 Jun 2010
Posts: 5

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 10:08 am     Reply with quote

Thank you for your help,
Because I did not know that the reading would take 11*cycleOfthe ADC
Here in my cas I think that it is about 8-9µs ... So I will try to use your technics.
Just for information I tried to use the interruption of the analogic decoder but it seems that I must stop all the other interruption before using it (tell me if i'm wrong). However, I'm using a clock rate of 20MHz Smile.

Thank you for your help :D
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 10:14 am     Reply with quote

Not sure what you mean by the 'analogic decoder'!...
However the ADC interrupt is only really useable, if you _trigger_ the ADC conversion with the CTC. Doing this, the ADC is triggered by the CTC, then interrupts you, when the conversion is complete. You can then call 'adc_read', with the 'read_only' option to get the result.
However the overhead of getting into and out of the interrupt handler is often more than the time needed to read the ADC.

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