Go Down

Topic: interfacing encoder to arduino (Read 1 time) previous topic - next topic

octopuz

Hi guys, I just bought this encoder

http://usdigital.com/assets/datasheets/E7P_datasheet.pdf?k=634861190727125957

and I'm trying to use it in my robot by using this code:

Code: [Select]
// Define pin locations and delay time between each query
#define EncoderPinA  3
#define EncoderPinB  5
#define DELAY_TIME 500

// Define some physical constants
#define WHEEL_CIRCUMFERENCE 0.9 // In meters
#define WHEEL_TICKS 244         // The number of 'ticks' for a full wheel cycle

// Create a variable in memory that the interrupt code can access
// Also create the change value globally
volatile unsigned int EncoderPos = 0;
double dVal = 0;

// Initialize
void setup()
{
  // Set input pin state for the line sensors
  pinMode(EncoderPinA, INPUT);
  pinMode(EncoderPinB, INPUT);

  // Register a hardware interupt function for pin 3 (which is indexed by value 1)
  // This function sets the EncoderEvent() function to be called whenever a line detector detects a change
  attachInterrupt(1, EncoderEvent, CHANGE);

  // Start serial communication
  Serial.begin (9600);
}

// Program loop
void loop()
{
  // Find the before and after value between the delay times
  unsigned int OldPos = EncoderPos;
  delay(DELAY_TIME);
  unsigned int NewPos = EncoderPos;

  // If an integer overflow occures, throw out the new value
  if(abs(NewPos - OldPos) < 30000)
    dVal = ((double)(NewPos - OldPos) / (double)DELAY_TIME) * 1000.0;

  // Convert between angular velocity to velocity
  double angVel = dVal / (double)WHEEL_TICKS;
  double velocity = (angVel * WHEEL_CIRCUMFERENCE);

  // Print data
  Serial.print("Velocity: ");
  PrintDouble(velocity, 5);
}

// Encoder event for the interrupt call
void EncoderEvent()
{
  // Read for data and bit changes
  // This is gray-code logic
  if (digitalRead(EncoderPinA) == HIGH)
  {
    if (digitalRead(EncoderPinB) == LOW)
      EncoderPos++;
    else
      EncoderPos--;
  }
  else
  {
    if (digitalRead(EncoderPinB) == LOW)
      EncoderPos--;
    else
      EncoderPos++;
  }
}

// Print a double value onto the serial stream
// This is from the Arduino.cc forum
void PrintDouble( double val, byte precision)
{
  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
mult *=10;

    if(val >= 0)
frac = (val - int(val)) * mult;
    else
frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
padding--;
    while(  padding--)
Serial.print("0");
    Serial.println(frac,DEC) ;
  }
}


However, when I turned on the motor and run the wheel, the serial monitor can only detect velocity = 0.000. I don't know what went wrong. Appreciate your help. Thanks

LarryD

Not knowing about this device, I would first see if I was getting an output form the encoder.
Would you confirm with a scope that the signal going to the Arduino is indeed there?
Also, show us your schematic for this project.
The way you have it in your schematic isn't the same as how you have it wired up!

kf2qd

Not knowing what type of outputs your encoder has. Are they TTL (5V) or are they differential? Differential outputs may not have enough voltage swing. If that is the situation then you would need a differential reciever to convert to a 5V TTL level signal for the Arduino.

I have used that code with an encoder so I know it works.

retrolefty


Not knowing what type of outputs your encoder has. Are they TTL (5V) or are they differential? Differential outputs may not have enough voltage swing. If that is the situation then you would need a differential reciever to convert to a 5V TTL level signal for the Arduino.

I have used that code with an encoder so I know it works.


The spec sheet shows the differential outputs working at the same output voltages as the single ended outputs, both TTL levels. So he only needs to wire up to the A+ and B+ output signal lines to the arduino if he indeed has the differential output model and it will then operate just like the single ended output model.

Lefty

MarkT

The min output HIGH is 2.4V, not enough, although typical figure is 3.4V (just enough), for the single-ended or
differential output version.

The ATmega needs a minimum of 3V to guarantee reading HIGH.  In general TTL levels are not compatible with CMOS
without a level shifting circuit or intermediate 74HCT buffer chip (a 74HCT14 schmitt-trigger inverter is often used
to map TTL to CMOS levels at 5V).  The 74HCT family of CMOS logic has TTL-compatible input thresholds.

Having said all that we I'm talking worst-case here - it is likely to work as is, but its worth checking with a meter that
the HIGH output voltage level is more like 3.5V than 2.4V
[ I won't respond to messages, use the forum please ]

octopuz


The min output HIGH is 2.4V, not enough, although typical figure is 3.4V (just enough), for the single-ended or
differential output version.

The ATmega needs a minimum of 3V to guarantee reading HIGH.  In general TTL levels are not compatible with CMOS
without a level shifting circuit or intermediate 74HCT buffer chip (a 74HCT14 schmitt-trigger inverter is often used
to map TTL to CMOS levels at 5V).  The 74HCT family of CMOS logic has TTL-compatible input thresholds.

Having said all that we I'm talking worst-case here - it is likely to work as is, but its worth checking with a meter that
the HIGH output voltage level is more like 3.5V than 2.4V


Do you mean that I need to increase the output voltage from the encoder to make it work?

dc42

The worst-case high level output (2.4V) is given at 20mA load, whereas the Arduino presents only a tiny load. So I very much doubt that insufficient high level output voltage is the problem. Nevertheless, I suggest you change the pin mode of the two encoder input pins to INPUT_PULLUP to be safe.

My guess is that one of the four wires between the encoder and the Arduino is not properly connected.

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

michinyon

I've seen it recommended,  that the variable accessed in the interrupt routine should be declared  "volatile",   although whether it matters in this case,  I don't know.

MarkT


I've seen it recommended,  that the variable accessed in the interrupt routine should be declared  "volatile",   although whether it matters in this case,  I don't know.


If a variable is used both in an interrupt routine and in the rest of the sketch you make it volatile - otherwise
the compiler might do the wrong thing.
[ I won't respond to messages, use the forum please ]

octopuz

I have checked the output voltage of the encoder using a scope and it is shown that the output voltage is always at 3.7 V, regardless the position of the wheel. What could be the cause of this problem?

dc42

Are saying that when the code wheel rotates relative the mounting base of the encoder, the outputs don't change? If so, check that the ground connection between the encoder and the Arduino is good.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

octopuz


Are saying that when the code wheel rotates relative the mounting base of the encoder, the outputs don't change? If so, check that the ground connection between the encoder and the Arduino is good.


Checked the ground and the outputs work just fine from the scope, however the serial output still says 0 velocity


kf2qd


Go Up