Single Axis Gyroscope Help (ENC-03MB)

Not sure if this is the correct board to ask about this but...
I have a ENC 03MB single axis gyro, which uses an output voltage and a reference voltage to output the angular velocity in voltage.
As per the datasheet, this is the formula they use:
Output voltage = V0 + Sv*w
Where the output voltage is the voltage out to the OUT pin, V0 is the voltage out to the OUT pin when not moving, and Sv is the scaling factor, according to the datasheet this is 0.67mV.
So naturally I read the voltage out and the reference, stored it as adcIn and ref respectively, and designed the following equation:
rate=(adcIn-ref)/(0.67/1000.0);
adcIn and ref have been properly divided by 1023 to give the voltage output in Volts, and since 0.67 is in mV i had to divide by 1000 there. I'm using this along with time to get a value for the heading.
For some reason, it doesn't work at all. The value sometimes never increases, or increases randomly, or jumps randomly, or just does not respond to any motion.
Here's my code:

double adcIn, ref, rate, initTime, rot=0;

void setup() {}

void loop() {
  initTime = millis();
  adcIn = analogRead(0)/1023.0;
  ref = analogRead(1)/1023.0;
  if(((1000*adcIn)-(1000.0*ref))>10) //deadzone of +/- 10mV
    rate=(adcIn-ref)/(0.67/1000.0); //change the rate correctly
  else 
    rate = 0;
  rot+=rate*(millis()-initTime)/1000.0; //apply the rate to the heading
  Serial.print(rot);
  Serial.println(" deg");
  Serial.print(rate);
  Serial.println(" deg/s");
  Serial.print(adcIn*1000);
  Serial.println(" mV ADC");
  Serial.print(ref*1000);
  Serial.println(" mV Reference");
  Serial.println();
  Serial.println();
}

Any idea as to where I'm going wrong? or am I completely reading this datasheet wrong? There's a datasheet here.

The sensitivity is 0.67 mV/deg/sec, which is a dividing scale factor.
Rearrange the equation to (output voltage - V0)/Sv = w,
so to get degrees/sec, divide the (output voltage - V0) in mV by 0.67.

Unrealistic example: the ADC output after subtracting V0 is 1000 mV. The rotation rate is 1000/0.67 = 1492 degrees/sec

jremington:
The sensitivity is 0.67 mV/deg/sec, which is a dividing scale factor.
Rearrange the equation to (output voltage - V0)/Sv = w,
so to get degrees/sec, divide the (output voltage - V0) in mV by 0.67.

Unrealistic example: the ADC output after subtracting V0 is 1000 mV. The rotation rate is 1000/0.67 = 1492 degrees/sec

Just tried it, it still increases without bound/doesn’t work like it should. Turning it does nothing, it seems to increase constantly.
Here’s a sample output:

4.48 deg
0.00 deg/s
0.00 mV ADC
0.00 mV Reference


5.08 deg
0.00 deg/s
0.00 mV ADC
0.00 mV Reference


5.78 deg
0.00 deg/s
0.00 mV ADC
0.00 mV Reference


6.43 deg
0.00 deg/s
0.00 mV ADC
0.00 mV Reference

Post the latest code. Also, just print out the raw ADC values while moving the chip. You should see obvious changes.

jremington:
Post the latest code. Also, just print out the raw ADC values while moving the chip. You should see obvious changes.

The raw ADC seems to be correctly outputted, it increased voltage clockwise and decreased counter clockwise (relative to the ref). But for some reason it still increases indefinitely.

double adcIn, ref, rate, initTime, rot=0;

void setup() {}

void loop() {
  initTime = millis();
  adcIn = analogRead(0)/1023.0;
  ref = analogRead(1)/1023.0;
  if(abs((1000*adcIn)-(1000.0*ref))>10) //deadzone of +/- 10mV
    rate=((adcIn-ref)*1000)/0.67; //find difference, convert to mV, divide
  else 
    rate = 0;
  rot+=rate*(millis()-initTime)/1000.0; //apply the rate to the heading
  Serial.print(rot);
  Serial.println(" deg");
  Serial.print(rate);
  Serial.println(" deg/s");
  Serial.print(adcIn*1000);
  Serial.println(" mV ADC");
  Serial.print(ref*1000);
  Serial.println(" mV Reference");
  Serial.println();
  Serial.println();
}

Some observations:
I’m interested to know how your serial interface knows what rate to run at.
“millis()” returns an unsigned long, not a floating-point number.
What’s with the divide by 1023.0?

As AWOL pointed out, the use of floats for millis() is an obvious problem. Calculate the time difference between two unsigned longs before doing other calculations.

Also, is ref constant, and equal to adcIn if the chip is stationary?

You need to calibrate a gyro when not rotating, the exact offset varies from device to device
and until its calibrated you will get a lot of drift.

Ideally you average a lot of readings with the thing stationary, to get sub-LSB resolution on the
calibrated value.

AWOL:
Some observations:
I’m interested to know how your serial interface knows what rate to run at.
“millis()” returns an unsigned long, not a floating-point number.
What’s with the divide by 1023.0?

I’m not too sure myself, I just picked it up while testing that setup doesn’t print without the baud specified but loop works fine (I assume it adjusts to every baud because changing the baud doesn’t affect the output). I’m sure there’s a more scientific answer somewhere I’m not aware of.
What kind of error would it being an unsigned long result in? I didn’t think it affected division so I left it. Also, the divide by 1023 is to get the voltage (technically it’s /1023*5 to get the voltage, so I just corrected this, but it still shouldn’t create this trend I’m seeing).

jremington:
As AWOL pointed out, the use of floats for millis() is an obvious problem. Calculate the time difference between two unsigned longs before doing other calculations.

Also, is ref constant, and equal to adcIn if the chip is stationary?

Ref is changing, and according to the datasheet it should be. I noticed something, posted it all the way at the bottom.

MarkT:
You need to calibrate a gyro when not rotating, the exact offset varies from device to device
and until its calibrated you will get a lot of drift.

Ideally you average a lot of readings with the thing stationary, to get sub-LSB resolution on the
calibrated value.

That’s what I originally implemented, but it gave completely random readings so I read the datasheet and it said to implement the above equation.

I just noticed something in Processing, I graphed the OUT pin voltage, the REF pin voltage, and the difference between them.
See the attached images for details - the Blue is the REF pin, the White is the OUT pin, and the red is the difference between them.
First image:
In the first half of the image I was rotating the gyro furiously, but seeing no results. And in the second half, where it dips a bit further down, I moved my hand near the gyro.

Second image:
In the first half I was again rotating the gyro, this time with the REF pin unplugged. As you can see, it still somehow magically reads the values. Not sure at all what is going on here. THe second half of the image is where I touched the side of the gyro (not any metal or components of it, just the side). I’m completely lost for this.

Not sure what this signifies, but the output seems completely unaffected by rotation in any direction, but very affected by my hand near it. Also if I touch the gyro or hold it firmly in position, the errors disappear, which should occur obviously, but the line stays flat even if I rotate the gyro.

Following this, I made a simple arduino sketch to just print out analogRead(0), analogRead(1), and analogRead(0)-analogRead(1) or OUT, REF, and the difference respectively, to the Serial. I observed the same issue - the values seemed unaffected and the difference remained negligible.

Any idea as to what I’m doing wrong? I wired the OUT and REF pins to Analog 0 and Analog 1. Taking both pins out makes all the values negligible (flat lines in Processing), but taking out the VCC power line doesn’t affect the values at all… which should be impossible, no?

Not sure what this signifies, but the output seems completely unaffected by rotation in any direction, but very affected by my hand near it.

This sounds like a ground problem. Do you have the ground pin from the gyro connected to the Arduino ground?

Also, the data sheet says that the reference voltage output must be connected to a 4.7 uF capacitor to ground. Do you have that capacitor installed, or is it on the breakout board?

Edit: never mind about the capacitor, the product page and schematics are here: ENC-03M Single Axis Gyro Module | Open ImpulseOpen Impulse

You probably have a bad connection to Vcc and/or ground.

jremington:
This sounds like a ground problem. Do you have the ground pin from the gyro connected to the Arduino ground?

Also, the data sheet says that the reference voltage output must be connected to a 4.7 uF capacitor to ground. Do you have that capacitor installed, or is it on the breakout board?

Edit: never mind about the capacitor, the product page and schematics are here: ENC-03M Single Axis Gyro Module | Open ImpulseOpen Impulse

You probably have a bad connection to Vcc and/or ground.

Just tested with an LED, it seems fine. Attached an image, basically I have 5V on the arduino → Vcc on the gyro, GND to GND, OUT to A0, and REF to A1.

I just tried accidentally brushed one of the terminals with the led wire, and the LED turned on briefly (no power to the gyro!). I’m guessing that’s the capacitor’s doing, and that it should be discharged hopefully. Now I see three flat lines. When I move it, it resumes it’s erratic pattern from above. Each time I discharge it with the LED it turns into three lines at 0V.

Hi,
Have you got the pins in the gyro PCB soldered in?
I can’t see any in the picture.
sjoints.jpg

Tom… :slight_smile:

woodworksio:
Also, the divide by 1023 is to get the voltage (technically it's /1023*5 to get the voltage, so I just corrected this, but it still shouldn't create this trend I'm seeing).

Technically it's /1024*5 to get the voltage, but you're close enough :wink:

TomGeorge:
Hi,
Have you got the pins in the gyro PCB soldered in?
I can’t see any in the picture.
sjoints.jpg

Tom… :slight_smile:

Nope, just attached for now. I can try soldering.

AWOL:
Technically it’s /1024*5 to get the voltage, but you’re close enough :wink:

Nice catch! I applied zero indexing to normal math :grinning:

Sorry for the late reply - had a busy four days. As far as I can tell, the capacitor on the inside is fully discharged and the gyro seems to return the correct value ( I think ) while it’s discharged-for about half a second. The inside is just logic AND and OR gates, and it says a resistor should be on the board. I tried to create a solution for discharging it, but I want to use this for a robotics competition in which discharging and grounding is against the rules.
Any other ideas? Maybe I’m going about the code all wrong, but as far as I can tell that’s what the equation is indicating.