I am trying to integrate the voltages from this gyro and it seems like I am getting different angular rates in clockwise vs counter-clockwise rotation direction! When i start this code, it reads 0, when i rotate in one direction, the counts increase and decreases in the opposite direction. The problem is that when I return to the same physical position the count does not return to zero. It seems to get more negative each time I move it and return to the starting position. Any help or insight would be greatly appreciated. He is my code:
//CCS C Compiler
#include <18F252.h> //PIC Chip
#device ADC=8 *=16 //10 Bit A/D - 16 bit address
#use delay(clock=16000000,restart_wdt) //Running @ 16mhz
#use rs232(restart_wdt,baud=9600,bits=8,parity=n,xmit=PIN_C6,rcv=PIN_C7,stream=DSP) //Serial to LCD Display
#DEFINE YAW 1
signed int16 glYaw_Offset;
signed int16 giYaw = 0;
#int_TIMER1 //10ms timer interrupt
giYaw = giYaw + (long) read_adc() - glYaw_Offset;
set_timer1(-10000); //Set timer
void get_gyro_offset() //Calculate gyro offset once
int iNumAvgs = 100;
signed int16 iTemp;
set_adc_channel(YAW); //Yaw select channel
delay_us(15); //Settle time
iTemp = 0;
for (i=0;i<iNumAvgs;i++) //Average data
iTemp = iTemp + read_adc();
glYaw_Offset = (long) iTemp / iNumAvgs; //Get average from 100 readings
//*********************************** Setup Timer ***********************************
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
//********************** Initialize On-chip A/D *************************
//Gyro Ch1 = Yaw from Gyro chip Ch3 = 3.3v ref from Gyro Chip
setup_adc_ports(AN0_AN1_AN2_AN4_VSS_VREF); //Ch1 = Yaw Ch3 = 3.3V ref
setup_adc(ADC_CLOCK_DIV_32); //For 16-20Mhz Crystal - A/D Clock rate
delay_ms(250); //Wait to stabilize
get_gyro_offset(); //get offset to use in interrupt routine
enable_interrupts (INT_TIMER1); //Elapsed Timer1
enable_interrupts (GLOBAL); //Enable Interrupts
I think there could be a number of things responsible for what you’re seeing. For example, mounting the gyro IC onto the sensor PCB can affect the factory calibration IC, so you might need to do some additional calibration in your code. Also, are you being careful not to rotate the board more quickly than the gyro can measure?
One of our customers posted a fairly detailed write-up, including code, of using our gyro to track the rotation of his robot. You might find this post helpful:
Ben, thanks for the quick response. I soldered the header pin to the board and it is plugged into a mother board containing the PIC micro. I have wired the yaw and pitch axis (Z & X (not 4Z & 4X) analog output from the gyro to the A/D channels of the PIC. Also, the 3.3 volt output from the gyro is wired to V+ref of the PIC, so I am using the full dynamic range of the PICs A/D, but I am only using 8 bit A/D mode instead of 10 bit. Looking at the raw analog values when the board is not in motion, it is rock steady - no jitter and is the correct value. (in the 10 bit A/D mode, I see about a 1 count jitter).
Upon power up, I am holding the mother board steady so that the offset value can be averaged out. Then within the 10ms timer1 interrupt routine I am integrating the counts. I am moving it very slowly to prevent overloading the gyro. The values do increment & decrement as I rotate, but it doesn’t return to the starting value.
The PIC has 5 channels of A/D, but I am using only one in the code so settling time of the A/D mux should not be a factor. I also moved the wires (about 2" long) from the gyro to the PIC around to see if there was any cross-talk on the signals. I did solder a jumper from grd to the low power pad on the gyro. The self test pad is left open. I am using +5 power of the PIC to power the gyro at Vin. There are no other sensors on the mother board - just +5v supply, the PIC and this gyro. Put a DVM on the output pin showed a steady 1.23v when the board was still.
I did also try the same code on the pitch axis with the same result - it appears the the angular rate is different between the clockwise & counter-clockwise rotation but I am more inclined to believe that I am missing something critical here.
You mentioned additional calibration that I could try. Could you elaborate on this?
It looks like you’re already doing software calibration by using the voltage measured at steady-state as your offset. I’m concerned by your, well, concern, that it’s not returning back to “zero”, because that’s not a very realistic outcome (error will accumulate as you integrate). A more useful discussion would be about the magnitude of that error. Instead of adding raw ADC values, I suggest you compute an actual gyro angle and see how far off that is from 0 degrees when you conduct your test. Also, you are doing the simplest form of numerical integration to compute your angle. A more advanced algorithm should do a better job of keeping the error down.
The error that I am seeing seems to be too large as it never really returns to zero. Subsequent movements and returning to the same position continues to get worse - getting increasing negative but counts of 30-50!. Here’s a link on another forum that discusses this problem on another gyro in the same family. It is having to do with the HP filter used.
The thread you link to refers to a similar gyro board that Sparkfun apparently botched by including both the recommended low-pass filter and the optional high-pass filter (they have since released a revision removing the HP filter). Our carrier boards do not have external high-pass filters.
I still don’t understand why you expect something to “return to zero”. When you integrate to obtain a solution, your error grows over time, and your answer gets more and more inaccurate as time goes on. Also, what does “counts of 30-50” mean? Can you convert your answer to degrees?
I think I wasn’t clear on my observations, so let me try again.
When I start the app (with the board aligned parallel to the edge of my desk), I get a yaw reading of 0 which is great. No jitter in the data, just a solid zero. Now when I rotate the board slowly by just 20 or 30 degrees, I can see the integrated values increment to some value. When I stop the rotation, the value remains steady, again with no jitter. Now when I rotate in the opposite direction, I can see the values decrementing. However, when I reach the original starting position (parallel to the edge), the value I read is quite a bit negative but I believe should be close to zero. Now when I do this whole procedure once again, the value I get at the original position becomes even more negative and continues with each interation! This just is not right! I am moving very slowly as not to exceed the 100deg/sec rating of this gyro.
Converting the counts to degrees won’t really help any because it would just be a linear transformation to another set of numbers. The fact that it continues to to decrease monotomically after iteration tells me that I am doing something wrong.
I understand that your observations are not what you think they should be, but I have no way of evaluating whether what you think they should be is reasonable. Can’t you see how your observation of “the value I read is quite a bit negative” is completely unhelpful? The reason I’m asking for a measurement in degrees is because I am trying to gauge the magnitude of your error. An answer in degrees lets me do that; one in ADC counts does not (at least not without my knowing all sorts of details about your specific implementation). The sensor’s datasheet tells you how the output voltage relates to degrees per second. I suggest you perform that conversion in your code and then perform some tests so you can understand better what is going on. For example, try turning the sensor 90 degrees to the right and see what it says. Try turning it 90 degrees to the left and see what it says. Try turning it at various rates and see what happens to the error (part of your problem could be that you are turning it too slowly). If there is something fundamentally asymmetric or wrong in your implementation, it should jump out at you when you perform these tests (e.g. when I turn 90 degrees to the right, it says 82 degrees, but when I turn 90 degrees to the left it says 41 degrees!). Also, make sure that your integration result isn’t overflowing.
You definitely should not be surprised that your answer gets more and more off as time goes on. This is what happens when your answer is the result of numerical integration (as I mentioned in an earlier post, there are specialized algorithms to help keep the error from growing as quickly).
I agree with Ben that you should be telling us the magnitude of this problem. But the fact that you do not see any jitter means that you are not doing a precise enough reading. If you get exactly zero at rest, there will also be a range of slow speeds that read as exactly zero and therefore do not contribute to your average. That means that any rotation done at these speeds - such as the beginning and end of a test rotation - simply does not get included in your totals.
The range of speeds that measure as zero can be asymmetric (e.g. -1 deg/s to +2 deg/s), and that would cause exactly the behavior you have described. If this is the probably, you will see, for example, that turning more slowly just makes the problem worse!
I recommend trying 10-bit ADC. Also, you should probably use Vref as a reference - that way you do not have to hold the board still for calibration.
Ok, converted to degrees. Here are the results.
Align to edge of desk - start app and 0 deg displayed
Rotate board 90 deg CW and display shows 90.1 deg
Rotate board -90 CCW and displays shows -10.3 deg
Rotate board again 90 deg CW and display shows 99.5 deg
Rotate boardagain -90 CCW and displays shows -21.3 deg
Shifts by 10 deg for each rotation cycle.
Pretty much same result with 10 bit but with more noise.
In10 bit mode, the raw A/D change by a count of 1 bit. The mother is laying flat on my desk and I am rotating about the yaw - x axis. I beginning to think maybe its a impedance mismatch between the micro and gyro. The A/D impedance is 2.5K pic 18f252 and the gyro is 33K? Maybe I’ll try the 4Z buffered output next.
I do not understand your turning procedure - what is “the mother”? If you are touching connections or tilting the board while rotating you could be getting inaccurate readings. Try putting it on a turntable of some sort (maybe an office chair?) if that might be the problem.
You might also be on to something with the output impedance, but “impedance mismatch” is not really the right term. If you are just following the example in the PIC datasheet of how to calculate the minimum acquisition time for a 2.5k source, that is likely to be a problem. Can you increase the acquisition time a lot?
Paul & Ben,
Thanks for all your help on this. It WAS the low input impedance of the 18f series PIC that I am using. (the 16F series has a 10K vs the 2.5K of the 18F). Anyway, I connected the A/D to the 4Z input of the gyro and it all works fine now. The 4Z output from this board goes through an OP amp which drops the apparent source impedance low enough to be compatible with the PIC. I believe I could use the Z output if I just push it through a unity gain rail-to-rail OP amp. On the software side, I did change the offset calculation to average 1000 readings and averaged 5 readings for each. I can now rotate the board to 90 degrees and back about 8-10 times and perhaps get a 1 deg error upon returning to zero. I have an accelerometer now which I will try to use to try to reduce the drift of the gyro.