Reset Encoder Count

Hi guys..

I'm working on a segway project and for the turning mechanism I'm using an incremental encoder (omron e6j-cwz 600ppr) coupled to the handle bar. So when I turn the bar the left or right the segway turns too.

The encoder (initial position set to 0) keeps track of this displacement and a proportional controller calculates the voltage to the motors.

The thing is, the movement of the handle bar is not very smooth and sometimes after turning bar and it returning the the zero position, the count of the encoder dosen't really go back to 0, but some value around -15 to 15 counts.

So the vehicle tries to turn even though the bar is straight.

I've tried fine tunning some boundaries around the 0 count, like after 2.5sec if the count is +-5 then just reset to 0.

It works sometimes but it's not really a solution, when the count is 6 the problem arises again.

I could keep making my boundaries bigger but the I need big displacements of the bar for turning the vehicle.

Any ideas to handle this?.

Thanks

L.

IMG_6692.JPG

Have you considered modifying your code so that any value a little bit either side of 0 counts as zero - perhaps +/- 15?

...R

So you're counting too many "ticks" turning or loosing some "ticks" on going back to straight (as you write the encoder is "incremental").

First thing is to try and work out if it is hardware or software that is miscounting. Electrical noise on the input? Is the counting of encode pulses done in a software test from loop() or an interrupt? Now you asked in the programming section, so lets see the code you read the encoder with.

As I understand, the encoder type only gives impulses and no absolute position.

First you should check, why u are missing some of the rotary events. Maybe you must implement a higher scan rate. I prefer a timer interrupt for regular high fequency checking of the rotary encoder. (see ElBanquos_AlarmClock/input.ino at master · mattywausb/ElBanquos_AlarmClock · GitHub how I do it) But this is for simple input of a clock, nothing that critical as your segway.

Second, you can compensate the error also with a second button or sensor, that informs you about reaching the middle position so you can adjust your encoder value.

3dprinter:
Now you asked in the programming section, so lets see the code you read the encoder with.

This is part of the code, just the turning part, it's going to be too long otherwise.

These are the variables

#define c_TurnEncoderPinA 15           //just the pins
#define c_TurnEncoderPinB 14
#define TurnEncoderIsReversed         // check direction
volatile bool _TurnEncoderBSet;         // _TurnEncoderBSet=digitalRead(pinB)
volatile long _TurnEncoderTicks = 0;  // primary counter
short TurnAngular = 0;                     // the encoder count is stored in this variable

The setup function runs this.

void setUpEncoders()
{
  // Turn encoder
  pinMode(c_TurnEncoderPinA, INPUT_PULLUP);      // sets pin A as input
  pinMode(c_TurnEncoderPinB, INPUT_PULLUP);      // sets pin B as input
  attachInterrupt(digitalPinToInterrupt(c_TurnEncoderPinA), HandleTurnMotorInterruptA, RISING);
 }

The interrupt function.

void HandleTurnMotorInterruptA()
{
  _TurnEncoderBSet = digitalRead(c_TurnEncoderPinB);   
 
  #ifdef TurnEncoderIsReversed
    _TurnEncoderTicks -= _TurnEncoderBSet ? -1 : +1;
  #else
    _TurnEncoderTicks += _TurnEncoderBSet ? -1 : +1;
  #endif
}

The main loop function updates all measurements coming from the sensors and sets the motors every 10ms.

void loop() {
  currentTime = micros();                                  // this hole part if for working every 10ms
  timeDifference = currentTime - previousTime;
  if (timeDifference > samplingTime) 
  {
    previousTime = currentTime;
    sampleImu();                              //gyro and acc
    sampleEncoders();                      // 3 encoders, one for each wheel and the handle bar
    setMotors();                              // feedback control law, pwm to motors.
    print();                                    //prints relevant data 
  }
}
void sampleEncoders() {
  TurnAngular = _TurnEncoderTicks; //update encoder reading.
  // read the other encoders and calculate speeds.
}

Robin2:
Have you considered modifying your code so that any value a little bit either side of 0 counts as zero - perhaps +/- 15?

...R

Yes I've tried. The problem is that, sometimes the error is like +/- 20 and if I set this to zero, much of the range is lost.
Also the turning becomes to aggressive since 21 counts corresponds to 50% of turning effort (just an example not the real number). I could change the proportional controller gain, but I can't find that sweet spot.

bobaFetty:
This is part of the code, just the turning part, it's going to be too long otherwise.

Please don't post pieces of code as the problem may be in the other parts. If the program is too long then add your .ino file as an attachment.

...R

bobaFetty:
Yes I've tried. The problem is that, sometimes the error is like +/- 20 and if I set this to zero, much of the range is lost.

I wonder if that means that some pulses are being missed - can you do some tests to check that?

Have you data about the range of the pulse count for max movement of the control?

My original question was based on the possibility that the hardware was OK and the problem was due to the user not being able to centre the control precisely.

Another thought is that the "gearing" between the control and the encoder is not suitable - too few pulse between 0 and max.

...R

Robin2:
I wonder if that means that some pulses are being missed - can you do some tests to check that?

Have you data about the range of the pulse count for max movement of the control?

My original question was based on the possibility that the hardware was OK and the problem was due to the user not being able to centre the control precisely.

Another thought is that the "gearing" between the control and the encoder is not suitable - too few pulse between 0 and max.

...R

The count range is about +/-22 counts, I map that to 0 to 100% power.
I believe the problem is mechanical, its a big robust handle bar, lots of friction, probably never really goes back to the same home position exactly.
Previously I used a 10k potentiometer which was just an analog signal. It work fine but my tutor wants an endoder.
I think the encoder is too sensitive and the error is too noticeable compared to the pot.
Maybe I should change the direct coupling.
Also I now think this may not a be programming related issue.

I'm gonna post the full code later today. Just a few comments so people can understand better.
Here are some other pictures so you can see the problem better.

IMG_6699.JPG

IMG_6700.JPG

Please display your image(s) in your post so we can see it(them) without downloading it(them). See this Simple Image Guide

From Reply #8

The count range is about +/-22 counts, I map that to 0 to 100% power.

That suggests to me that you are expecting an unreasonable level of accuracy in positioning the controller. How many degrees of rotation of the encoder are needed to produce 22 pulses? And how accurately (in degrees) can the user be expected to position of the control handle (or whatever it is) at the zero point.

...R