Thread: Yaw Sensor
View Single Post
  #21   Spotlight this post!  
Unread 25-02-2004, 15:28
Larry Barello Larry Barello is offline
http://www.barello.net
#0492 (Titan Robotics Club)
Team Role: Mentor
 
Join Date: Jan 2002
Location: Bellevue, WA
Posts: 85
Larry Barello has a spectacular aura aboutLarry Barello has a spectacular aura about
Re: Get_Analog_Value in an ISR

Quote:
Originally Posted by WizardOfAz
...
Your code suffers in a way I was trying to avoid, but may well be insignificant. But here's my issue with it anyway: the "fast" process executes really often, as you say, probably well in excess of 100 kHz, but clearly depending on what you do in it, EXCEPT when data is ready from the master processor. Then the "slow" process is called, and the "fast" process doesn't get called at all while that is happening. In my case that's about 10ms, so I miss a couple of the 4ms interrupts. You code partly deals with this problem, since it counts up 1ms interrupts and later uses them all up, even if more than 10 of them happened without any "slow" process service. ...
Your analysis is correct. You should figure out why you are burning so much tmie in the user code. 10ms is a lot of instructions! Calling the ADC stuff from the interrupt handler should be Ok too as long as that is the only place you call it. Better yet, make the ADC stuff in-line so you don't even need to save .tmpdata or PROD - look at the assembly code and you'll understand why that is a big win (the PIC is terrible when saving context).

I essentially re-wrote all the IFI analog stuff to make it smaller (and to understand the PIC): From "sensor.h"
Code:
enum AdcValues
{
	Gyro,
	ArmPositionFeedback,
	szAdcVal
};
and "sensor.c"
Code:
//*************************** ADC Task ****************************************
// Note: OpenADC configures all the input port bits appropriately.
// Individual conversions, however, just reset the ADC hardware
// as the ADC turns off periodically for some unknown reason.

void Init_ADC_Task(void)
{
    OpenADC( ADC_FOSC_RC & ADC_RIGHT_JUST & (~szAdcVal),
          ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS );
}

int GetADC(enum AdcValues chan)
{
    ADCON1 = ~szAdcVal & 0x0F;	// Configure # channels and vref
    ADCON2 = 0x80 | 0x03;		// Right Justify & internal RC clock
    ADCON0 = (chan<<2) | 0x01;	// Set channel and turn on.
    Delay10TCYx(10);			// Let things settle
    ConvertADC();				// Start conversion 
    while (BusyADC());			// Wait conversion done
    return ReadADC(); 			// Return word
}
Note: my code only allocates the required number of ADC lines, so I can use the other ones for general digital I/O. The main reason I published this is so you can see how to in-line the conversion in your interrupt handler... If you only have three or four channels, it would be relatively efficient and fast to do it that way.