![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
dronix
Joined: 18 Jun 2010 Posts: 5
|
delay in the adc_read 18f2550 |
Posted: Fri Jun 18, 2010 8:25 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19360
|
|
Posted: Fri Jun 18, 2010 8:55 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
dronix
Joined: 18 Jun 2010 Posts: 5
|
|
Posted: Fri Jun 18, 2010 10:08 am |
|
|
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 .
Thank you for your help :D |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19360
|
|
Posted: Fri Jun 18, 2010 10:14 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|