Using gyro.c with other analog sensors no go

I’m going through the interupt routine in gyro.c to figure it out, and I believe I found a major issue with it. Kevin: Please check!

In the interupt routine, it does the following things (in order):

  1. Initialize i and accum if calculating bias

  2. Set old_calc_gyro_bias to calc_gyro_bias

  3. Reads ADC value

  4. Adds it to the accumulator

  5. Begins another ADC conversion

  6. Adds to accumulator.

  7. Does biasing code

The problem with this is if you try to read an analog channel (and clear the ADC) outside of the interupt. For this to work correctly, *the gyro

must

be the

only

sensor connected to your analog inputs*.

The Details:
The ADC converter works asyncronously from the controller. To use it, you have to:

  1. Set the channel or open it and wait for it to settle
  2. Tell it to begin a conversion
  3. Wait until it finishes
  4. Read the value
  5. Close it (?)

If anything is changed during a conversion, you have to start over from #2. The interrupt assumes that the conversion finnished successfully, and that the value in the registers is the one from the gyro. If you read a value, it will likely read the value from the last sensor you used.

Is there any fix to this? This seems to be a large blocker, since the gyro code is dependent on it.

And yes, I did update my code.

Did you read the readme.txt file. No? Well, here’s a paragraph that might interest you:

This software makes the assumption that when it’s running, it
solely controls the analog to digital conversion hardware and
that only the gyro, on analog input one, is being sampled.
Calling Disable_Gyro() will disable the gyro software and allow
you to use the ADC for other purposes.

One way around this is to double the timer 2 interrupt rate and then interleave your ADC measurements within the timer 2 ISR. If there’s interest, I can modify the code to include accelerometer measurements too.

-Kevin

I would like to see an example of how you would interleave the measurements. Not necessarily for the accelerometer but for a potentiometer mounted to our arm.

We have a similar situation, where we would like to juggle inputs from a pot and the gyro.

Once you call Disable_Gyro(), can you turn it back on again? In autonomous mode we’d be perfectly content to read only from the gyro while turning, then read from our pot on the straightaways, and then go back to reading from the gyro for a bit.

Is doing that more complicated than writting a complimentary function to Disable_Gyro() that just flips those two interupt bits? Or would we need a call to Initialize_Gyro()? Or do neither of those options work?

Can we not simply use a standard analog input for the gyro? Why is it necessary to use the ADC as set up in the example code?

Thanks - Jeff

Sure, if you only need angular rate of change.

For those that need heading too, you need to integrate the gyro’s output, which means that you must also know the amount of time between ADC samples. The way I look at it, reading and restarting the ADC during a timer interrupt service routine is the simplest and most elegant way to solve the problem short of using external hardware.

-Kevin

Doesn’t get_analog() obtain a reading when requested since it is off the FRC, or is it only updated once per master loop?

In which case how about I use the timer only to gain an accurate measure of the master loop interval?

I want to run several other analog inputs along with the Gyro, and heading is important as I am using your robot code. Slightly modified to handle a steered front wheel and counting every trigger from the encoders, since they are only 16 pulse.

I really appreciate the ability to start with your code and tweak from there!!

Thanks - Jeff

After reading some more out of the PIC18C manual, and doing some testing, here’s what I did:

Using the EDU, I made meassurements of how long it takes to read the analog input, from start to finnish. (Using timer 1 with 1:8 prescaler.) It averaged around 138.8586 clock cycles to go through, or about 0.111087 milliseconds (which is a bit long with all the extra instructions and the overhead to get the timer value).

Based on this value, and the relative rarity that the gyro timer goes off (about 400Hz if the comments are correct), we decided it was ok to switch channels and wait and everything inside the interupt. If anyone encounters problems doing this, please say so.

All right guys I need some help

Me and my team are planning on hooking up some switches and arm feedback as analog inputs, but when we run the program the gyro “hogs up all the space” for lack of better words. Any way around this or to fix this???

Asking Jim42’s question from above:

Once you call Disable_Gyro(), can you turn it back on again?

We need to know!!!

Just call initialize_gyro again, or if you didn’t do anything with the timer, adc, etc you can just turn on timer2 again.

Everyone serious about autonomous and capping this year needs a gyro and some kind of arm feedback (ie, potentiometer) yet I couldn’t find any real code on reading two analog inputs. So, assuming the sample rate is doubled (800 Hz), will this code work?
Our RC is a few thousand miles away in some spooky Caribbean harbor and our EDU is locked up somewhere over at the school, so I can’t really test it. :yikes:


void Timer_2_Int_Handler(void)
{
	unsigned int adc_result;
	unsigned int adc_result_2;


	if (last_conversion == POTENCIOMETRO)
	{
	ADCON0bits.CHS0 = 0;
	ADCON0bits.CHS1 = 0;
	ADCON0bits.CHS2 = 0;
	ADCON0bits.CHS3 = 0;

	// get the latest ADC conversion
	adc_result = ADRESH;
	adc_result <<= 8;
	adc_result += ADRESL;

	// add the ADC data to the accumulator
	accum += adc_result;

	// increment the sample counter
	samples++;

	// start another analog to digital conversion
	ADCON0bits.GO = 1;

	// check to see if we've got a full sample set
	if(samples >= GYRO_SAMPLES_PER_UPDATE)
	{
		// should the completed sample set be used to calculate the gyro bias?
		if(calc_gyro_bias == TRUE)
		{
			// convert the accumulator to an integer and update gyro_bias
			avg_accum += accum;
			avg_samples++;
		}
		else
		{
			// update the gyro rate
			gyro_rate = (int)accum - gyro_bias;

			// integrate the gyro rate to derive the heading 
			gyro_angle += (long)gyro_rate;
		} 

		// reset the accumulator to zero
		accum = 0;

		// start a fresh sample set
		samples = 0;
	}

	last_conversion == GYRO;
	}
	else
	{
	ADCON0bits.CHS0 = 1;
	ADCON0bits.CHS1 = 0;
	ADCON0bits.CHS2 = 0;
	ADCON0bits.CHS3 = 0;
	// get the latest ADC conversion
	adc_result_2 = ADRESH;
	adc_result_2 <<= 8;
	adc_result_2 += ADRESL;
	ADCON0bits.GO = 1;
	potenciometro = adc_result_2;
        last_conversion = POTENCIOMETRO;
	}
}

To be safe, you should change the channel after getting the value. Also, be sure to double check the reference manual to make sure you have the bits right for the channel selection, we had some trouble with that when we to alternate between gyro and accelerometer.

In the end, we didn’t use it though; our sensors were giving bad readings, presumably broken. We did come up with two rather ingenuitive ways of solving the direction and arm height problems, though I’m not too sure I’m supposed to share them just yet. :slight_smile: What’s it matter though if we can’t get the robot to drive straight when it’s going for the tetra :frowning:

You can definetely get arm feedback without using two analog inputs. If nothing else you can use an external adc and put it into 8 digital inputs, or however many are practical.

I realize I’m a little late coming to this thread… but I wanted to put in a comment about sampling multiple analog sensors, either to add value to the discussion or to get feedback.

We needed to sample several analog inputs and wanted to use the same sample rate for them all (250 Hz), and ran into the problem with using Get_Analog_Value() more than once in an ISR. The “fix” we used was to have the ISR increment a counter of 4ms tics but not do any analog sampling. Code running in the “fast” routine would then read all the inputs when it saw the non-zero 4ms counter, and decrement the counter. This does cause sample jitter but no lost samples, so the average sample rate remains correct. Our “main loop” code used about 6ms, so about 1 sample every 4 or 5 would be delayed.

The problem with this method is if the main loop code is big compared to the sample rate, many samples will be delayed and the jitter will become a significant problem. For us this seemed to work. Then again, there are lots of reasons why integrated sensor values get “wrong” after a while, and this technique probably contributed to the causes.

Bill

(Sorry to revive old thread)

Has anyone gotten multiple analog inputs to work while using the gyro?
I mean, has anyone actually done all this!!

I forgot about this problem til now, and I was planning to use (probably two) pots and a gyro this season…

Thanks,
~Stephanie

Please read this thread, stickied, at the top of the programming forum: http://www.chiefdelphi.com/forums/showthread.php?t=39537

oops
thanks!