PaulStoffregen / Encoder

Quadrature Encoder Library for Arduino
http://www.pjrc.com/teensy/td_libs_Encoder.html
540 stars 239 forks source link

Z signal detection #16

Open siamect opened 7 years ago

siamect commented 7 years ago

Thanks Paul for a very useful library. Would it be possible to add another interrupt from the Z signal to preset a position value? This would be useful when dealing with positioning systems etc.
I have looked through your code but it is way over my level of knowledge.

Thanks again! /Martin

PaulStoffregen commented 7 years ago

What (precisely) is "Z signal"?

Without a datasheet or solid technical specification of this signal, there's no hope of even talking about how it might be done.

siamect commented 7 years ago

Dear Paul
The Z signal is just a one pulse per turn reference signal so that you know where you are. Some systems presets the position to a certain value when this pulse arrives, (the first time, or after a command) and the pulse counting start from there. other systems just record the current counter value when this pulse arrives and you can use it to calculate you preset value. There is an explanation on https://en.wikipedia.org/wiki/Rotary_encoder. If you scroll down a bit there is an illustration on the right side.
/Martin

tankmz commented 5 years ago

I edited Paul's library and was able to add the ability to count Z Signal or Index. I am very limited in my knowledge, so please take a look.

I changed EncoderIndex.h and put my demo code in the examples folder.

There are currently two main issues which I am aware of.

  1. The index double counts when it passes over
  2. The index has the ability to miscount if there are small oscillations around the index mark

Please help me to refine this further. I'm very new to C/C++, but I really wanted to make this one work because it seems to be the fastest code out there. (Great work Paul!)

Thanks,

EncoderIndex.zip

tankmz commented 5 years ago

Also, I couldn't even touch the assembly portion. So if AVR is defined, I don't think anything will work. Since its looking for 3 pins, but can't make use of them.

tankmz commented 5 years ago

Alright, I fixed those index counting issues. However, it only works for the type of index that my encoder uses. Which is an index that matches a Channel B pulse. Like the picture:

index signal

Encoders which have an index of different location or width, might need the switch case statement to be modified. Also, the order of the pins in the main sketch now matters. They have to be entered in format (A, B, Z).

" // Pins must be in order of A, B, Z (index) // Otherwise, index will count improperly Encoder XEncoder(24, 25, 26); // Encoders need to have 3 pins otherwise, it doesn't compile "

Can someone help with the assembly part? And proof my edits?

Thanks! PS: change the .txt to .h in the attached file

EncoderIndex.txt

drf5n commented 3 years ago

If you just want to use a shaft encoder's index signal Z to reset the count to a fixed position, like TopDeadCenter on a motor timing pulley meaning 0°, you could assign an Interrupt Service Routine on the Z pin and reset the count:

/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(5, 5);
//   avoid using pins with LEDs attached

// Setup for optical encoder index signal 
// See https://www.dynapar.com/technology/encoder_basics/incremental_encoder/
const int ENC_Z = 7;
volatile bool index_triggered = false;
void index_ISR(){
  index_triggered = true;
  // or reset to zero directly:
  // myEnc.write(0);
}

void setup() {
  Serial.begin(9600);
  pinMode(ENC_Z,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENC_Z), index_ISR, RISING);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  if(index_triggered){
    myEnc.write(0); 
    index_triggered = false;
  }
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

Depending on how one would want to use the index signal, (reset to constant, check if you missed steps, set to the nearest full 1000/4000PPR rotation, add/subtract a full revolution, etc....) it would be hard to write a general handler into the library.

drf5n commented 3 years ago

Paul -- the Z signal is a common name for the X signal on the AMT102-V (Datasheet: https://www.mouser.com/datasheet/2/670/amt10_v-1775837.pdf) in the https://www.youtube.com/watch?v=2puhIong-cs video in your README.

It looks like the AMT102-V X index pin is attached to the testbed as "GREEN" in the video.