A/D speed
Posted: Wed Aug 29, 2012 1:39 pm
As previously reported here http://www.matrixmultimedia.com/mmforum ... f=5&t=8622 and http://www.matrixmultimedia.com/mmforum ... 967#p38967 I had been struggling to get an interrupt triggered A/D on a PIC to speed up. Was partly solved with your help, v5 and a faster 8 bit processor.
Now I find that someone using an Arduino to do something similar to me suggests:
“I use a timer interrupt to drive the sample rate. The standard Arduino library ADC read function is blocking and takes over 110µs, which is most of the available 156µs sample period (interrupt time). So, the ADC read is split into 2 parts, start conversion, and read result. By reading the previous result then starting again in each timer interrupt, the conversion can take place in the background. This frees up the time required to get the ADC reading.” Not quite sure what he means by “blocking” but I assume it means nothing else can be done until that routine is finished which is the problem I have.
The core Arduino C code for this is:-
// kick off a slow conversion. Read it next interrupt.
i_adc.start_conversion();
// read ADC started on previous cycle.
const int i = i_adc.read();
although there are probably more lines that just those.
Do you think it would be difficult for me to alter the order of your C Code in your ADC_RAW_Sample_Channel_Int routine to read the result for the previous sample before starting a new one and jumping back to main code whilst it executes? It’s the 11 A/D clock cycles needed to convert the voltage that is the main cause of slow speed, but these would now be done in the background. Is there any reason why the PIC can not get on with sampling in the background and not be at all affected by foreground activities like other interrupts and the main code? I assume the register that stores the A/D result is not reused for other things in between A/D samples thus wiping the saved value.
As you suggested to speed it up I am not precharging the sampling capacitor every time as only measuring one A/D channel.
The C Code for RAW_Sample seems to be just one line:-
MX_UINT16 FCD_ADC1_ADC_RAW_Sample_Channel_Int()
{
return FC_CAL_Sample_ADC( 1 ); //Perform Sample - Return as MX_UINT16
So not much scope for reordering that into a different order.
ReadAsInt is more promising:-
MX_UINT16 FCD_ADC1_ReadAsInt()
{
MX_UINT16 retVal;
//Configure & Enable ADC Channel
FC_CAL_Enable_ADC ( ADC_3_MX_ADC_CHANNEL , ADC_3_MX_ADC_CONVSP , ADC_3_MX_ADC_VREFOP , ADC_3_MX_ADC_ACTIME );
retVal = FC_CAL_Sample_ADC( 1 ); //Perform Sample - Return as MX_UINT16
FC_CAL_Disable_ADC ();
return (retVal)
but not clear how to start the sampling going and jump back to main loop as FC_CAL_Sample_ADC presumably does it all and won’t allow anything else to happen until the sampling is finished.
What exactly is the difference between a RAW_Sample and a ReadAsInt?
Now I find that someone using an Arduino to do something similar to me suggests:
“I use a timer interrupt to drive the sample rate. The standard Arduino library ADC read function is blocking and takes over 110µs, which is most of the available 156µs sample period (interrupt time). So, the ADC read is split into 2 parts, start conversion, and read result. By reading the previous result then starting again in each timer interrupt, the conversion can take place in the background. This frees up the time required to get the ADC reading.” Not quite sure what he means by “blocking” but I assume it means nothing else can be done until that routine is finished which is the problem I have.
The core Arduino C code for this is:-
// kick off a slow conversion. Read it next interrupt.
i_adc.start_conversion();
// read ADC started on previous cycle.
const int i = i_adc.read();
although there are probably more lines that just those.
Do you think it would be difficult for me to alter the order of your C Code in your ADC_RAW_Sample_Channel_Int routine to read the result for the previous sample before starting a new one and jumping back to main code whilst it executes? It’s the 11 A/D clock cycles needed to convert the voltage that is the main cause of slow speed, but these would now be done in the background. Is there any reason why the PIC can not get on with sampling in the background and not be at all affected by foreground activities like other interrupts and the main code? I assume the register that stores the A/D result is not reused for other things in between A/D samples thus wiping the saved value.
As you suggested to speed it up I am not precharging the sampling capacitor every time as only measuring one A/D channel.
The C Code for RAW_Sample seems to be just one line:-
MX_UINT16 FCD_ADC1_ADC_RAW_Sample_Channel_Int()
{
return FC_CAL_Sample_ADC( 1 ); //Perform Sample - Return as MX_UINT16
So not much scope for reordering that into a different order.
ReadAsInt is more promising:-
MX_UINT16 FCD_ADC1_ReadAsInt()
{
MX_UINT16 retVal;
//Configure & Enable ADC Channel
FC_CAL_Enable_ADC ( ADC_3_MX_ADC_CHANNEL , ADC_3_MX_ADC_CONVSP , ADC_3_MX_ADC_VREFOP , ADC_3_MX_ADC_ACTIME );
retVal = FC_CAL_Sample_ADC( 1 ); //Perform Sample - Return as MX_UINT16
FC_CAL_Disable_ADC ();
return (retVal)
but not clear how to start the sampling going and jump back to main loop as FC_CAL_Sample_ADC presumably does it all and won’t allow anything else to happen until the sampling is finished.
What exactly is the difference between a RAW_Sample and a ReadAsInt?