I have scavenged an industrial servo with its attached ballscrew linear actuator from an old large format scanner, and I am trying to figure out how to make a 'servo drive' aka 'servo driver' aka 'servo controller'.

I'm a total novice at arduino, and am mostly a copy/paste coder - so of course this makes my goal harder.

I can find a lot of information on how to read a simple AB offset encoder that needs _**four**_ wires to work, but the encoder I have has eight wires: 

A+, A-, B+, B-, Z+, Z-, +5v, 0v(aka GND)

With +5v supplied to it's wire and GND connected to 0v, rotating the motor shaft by hand, my meter reads:

 - A+: +3.97v as the 'high' and +.036v as 'low' 
 - A-: same
 - B+: same
 - B-:    same
 - Z+: same - but only goes high at one location on the 360 degree   
     rotation
 - Z-: same - but only goes high at one location on the 360 degree
   rotation - the same location as Z+

NOTE: Both Z pulses coincide with pulses on A+, B+, and B- ... but those are NOT coincident on A-. So maybe A- has the Z+/- trigger in it's place? I don't know. It was VERY challenging to stop rotating the shaft AT a pulse because of the tiny size of the divisions.

All voltages seen by my digital multimeter were positive voltages.


I do not understand how to properly use the encoder with so many wires. I can sort of understand that the positive and negative are probably opposite signals from each other, sort of error protection or something? I know that the Z= and Z- are roattion counters at either 90, 180, or some other offset angle to allow ticking full rotations. But am unsure about this all and am reading a lot of material that is beyond me. I'm stumped.

I can install the following code on an UNO and the UNO reads the encoder just fine off the A+ and B+ lines, with increasing count for one direction of rotation and decreasing count for the other direction. So it is reflecting the movement as it should... 

BUT- I am getting 8000 pulses per shaft revolution rather than the 2000 pulses per revolution in the documentation. So something's not right here. I should see 2000 pulses per revolution... is this because of the lack of use of the other wires? Or something else?

Code i'm using for just A+ and B+:

        /*
    *Quadrature Decoder 
    */
    #include "Arduino.h"
    #include <digitalWriteFast.h> 
    
    // Quadrature encoders
    // Left encoder
    #define c_LeftEncoderInterruptA 0
    #define c_LeftEncoderInterruptB 1
    #define c_LeftEncoderPinA 2
    #define c_LeftEncoderPinB 3
    #define LeftEncoderIsReversed
    
    volatile bool _LeftEncoderASet;
    volatile bool _LeftEncoderBSet;
    volatile bool _LeftEncoderAPrev;
    volatile bool _LeftEncoderBPrev;
    volatile long _LeftEncoderTicks = 0;
    
    void setup()
    {
      Serial.begin(9600);
    
      // Quadrature encoders
      // Left encoder
      pinMode(c_LeftEncoderPinA, INPUT);      // sets pin A as input
      digitalWrite(c_LeftEncoderPinA, LOW);  // turn on pullup resistors
      pinMode(c_LeftEncoderPinB, INPUT);      // sets pin B as input
      digitalWrite(c_LeftEncoderPinB, LOW);  // turn on pullup resistors
      attachInterrupt(c_LeftEncoderInterruptA, HandleLeftMotorInterruptA, CHANGE);
      attachInterrupt(c_LeftEncoderInterruptB, HandleLeftMotorInterruptB, CHANGE);
    }
    
    void loop()
    { 
      Serial.print("Encoder Ticks: ");
      Serial.print(_LeftEncoderTicks);
      Serial.print("  Revolutions: ");
      Serial.print(_LeftEncoderTicks/2000.0); //2000 Counts Per Revolution, per the engineering manual
      Serial.print("\n");
    }
    
    
    // Interrupt service routines for the left motor's quadrature encoder
    void HandleLeftMotorInterruptA(){
      _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
      _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);
      
      _LeftEncoderTicks+=ParseEncoder();
      
      _LeftEncoderAPrev = _LeftEncoderASet;
      _LeftEncoderBPrev = _LeftEncoderBSet;
    }
    
    // Interrupt service routines for the right motor's quadrature encoder
    void HandleLeftMotorInterruptB(){
      // Test transition;
      _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
      _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);
      
      _LeftEncoderTicks+=ParseEncoder();
      
      _LeftEncoderAPrev = _LeftEncoderASet;
      _LeftEncoderBPrev = _LeftEncoderBSet;
    }
    
    int ParseEncoder(){
      if(_LeftEncoderAPrev && _LeftEncoderBPrev){
        if(!_LeftEncoderASet && _LeftEncoderBSet) return 1;
        if(_LeftEncoderASet && !_LeftEncoderBSet) return -1;
      }else if(!_LeftEncoderAPrev && _LeftEncoderBPrev){
        if(!_LeftEncoderASet && !_LeftEncoderBSet) return 1;
        if(_LeftEncoderASet && _LeftEncoderBSet) return -1;
      }else if(!_LeftEncoderAPrev && !_LeftEncoderBPrev){
        if(_LeftEncoderASet && !_LeftEncoderBSet) return 1;
        if(!_LeftEncoderASet && _LeftEncoderBSet) return -1;
      }else if(_LeftEncoderAPrev && !_LeftEncoderBPrev){
        if(_LeftEncoderASet && _LeftEncoderBSet) return 1;
        if(!_LeftEncoderASet && !_LeftEncoderBSet) return -1;
      }
    }

.
.
.
Can someone explain the function of, and how to use, all eight wires? Explain why I'm getting 4X the counts that I should with that code above? PLEASE?
.
.
.

I'm posting images of the pages from the machine's engineering handbook that have info about the servo and encoder. The info there shows that it was more or less controlled like an RC servo from the mainboard's perspective - just PWM. But it had the drive/driver/controller parts right on the mainboard of the machine.

If it will be of use I can post pictures of the encoder board itself, but at this point I did not think that necessary.

[![Piniout of connector][1]][1]
[![Servo encoder resolution][2]][2]
[![Specs part 1][3]][3]
[![Specs part 2][4]][4]


  [1]: https://i.sstatic.net/z5FDM.jpg
  [2]: https://i.sstatic.net/PsWWz.jpg
  [3]: https://i.sstatic.net/DnQAx.jpg
  [4]: https://i.sstatic.net/bVwIX.jpg