Arduino and Absolute encoder.

Ok, I am to the point I need help on this.

I have a Gurley VJ11 Absolute Encoder. http://www.gurley.com/Encoders/rotabs.htm

25 bits of data must be read.

I am using a TI SN75178BP to convert CLOCK+ CLOCK- to D and DATA+ DATA- to R.

I have generated a pulse and read the chip using the following code. however I am not getting data back it seems.

I put the oscilloscope on the R lead and its throwing me for a loop. I have check all the leads, and its wired right.

One thought I had was that I am pulsing it wrong and it is causing an issue.

Help?

  boolean clockPin = 7;
  boolean dataPin = 8;
  int bufferSize = 25;
  boolean incomingDataBit = 0;
  unsigned long int inputBuffer = 0;
  static unsigned long int dataValue = 0;
  static unsigned long int outputValue = 0;
  int bitPosition;
  boolean statusBit =0;
  boolean signalQualityBit = 0;
  boolean quadratureBit = 0;
  boolean VA_errorBit = 0;
  boolean parityBit = 0;
  char TF;
  #define PD2 2
  int outPin = 2;

void setup() {

  pinMode(clockPin, OUTPUT);
  digitalWrite(clockPin, HIGH);
  pinMode(dataPin, INPUT);

  // Set up serial communication with host for debugging

  Serial.begin(9600);
  Serial.println("\n\nSerial is working \n");
   pinMode(outPin, OUTPUT);

}

void loop() {
  inputBuffer = 0;
  dataValue = 0;
  for(int loopCount = 0; loopCount < bufferSize; loopCount++) {
    //digitalWrite(clockPin, LOW);
    PORTD &= ~(1<<PD2);    // sets output bit 2 low
    delayMicroseconds(3);
    //digitalWrite(clockPin, HIGH);
    PORTD |= 1<<PD2;       // sets output bit 2 high
    delayMicroseconds(3);
    incomingDataBit = digitalRead(dataPin);

    // add the most recently fetched bit to the buffer
    // As the data is read MSB to LSB, we use the inverse of the loopCount to
//place it in
    // the buffer (e.g. from 'top to bottom')

    bitPosition = (bufferSize - 1) - loopCount;
    bitWrite(dataValue, bitPosition, incomingDataBit);

    // Extract STA status bit
       statusBit = bitRead(dataValue, (bufferSize -1));

    // Extract Flag bits and print them
       quadratureBit = bitRead(dataValue, 4);
       if (quadratureBit == true){TF = 'T';} else {TF = 'F';}
       Serial.print("Quadrature error = ");
       Serial.println(TF);

       signalQualityBit = bitRead(dataValue, 3);
       if (signalQualityBit == true){TF = 'T';} else {TF = 'F';}
       Serial.print("Signal quality bit = ");
       Serial.println(TF);

       VA_errorBit = bitRead(dataValue, 2);
       if (VA_errorBit == true){TF = 'T';} else {TF = 'F';}
       Serial.print("VA_error bit = ");
       Serial.println(TF);

       parityBit = bitRead(dataValue, 1);
       if (parityBit == true){TF = 'T';} else {TF = 'F';}
       Serial.print("parity bit = ");
       Serial.println(TF);

    // Shift remaining bits to the right before output
       outputValue = dataValue >> 4;

    // Send the data to the host computer for display


    //Serial.print("Signal quality bit = ");
   // Serial.println(signalQualityBit);
   // Serial.print("VA error bit= ");
   // Serial.println(VA_errorBit);
   // Serial.print("Parity = ");
   // Serial.println(parityBit);
    Serial.print("Position value = ");
    Serial.println(outputValue);
    delay(500);

    // Strip off non-position bits

  }  }

Hi,

google arduino SSI

Your absolute encoder is SSI output and there are a few solutions to read with arduino.

Tom.... :slight_smile:

Hi, again.

http://forum.arduino.cc/index.php?topic=156812.0

In post #3, I used this with some mods to read a 25bit stream, holding CLOCK high for 20uS is the important step to start the bit stream.

Tom... :slight_smile:

@ke5awf There was no link to a VJ11 on the Gurley website. Can you provide a link to the data sheet of the encoder you are trying to read?

As Tom George says, if the output format is SSI then you can clock and read it directly with the Arduino.

I am using a TI SN75178BP to convert CLOCK+ CLOCK- to D and DATA+ DATA- to R.

I'm not familiar with this interface, but your code looks wrong for SSI. Typically, using the clock pulse/read in the "for loop", you would read the data into an array, (or use bit shifting to compose the 25 bit data stream into a long value) before doing the extractions.

The bracketing arrangement in you code has you reading a bit into dataValue, performing some bit extractions, and bit shifting dataValue>>4 all before the complete data has been read into dataValue.

cattledog:
@ke5awf There was no link to a VJ11 on the Gurley website. Can you provide a link to the data sheet of the encoder you are trying to read?

As Tom George says, if the output format is SSI then you can clock and read it directly with the Arduino.

I'm not familiar with this interface, but your code looks wrong for SSI. Typically, using the clock pulse/read in the "for loop", you would read the data into an array, (or use bit shifting to compose the 25 bit data stream into a long value) before doing the extractions.

The bracketing arrangement in you code has you reading a bit into dataValue, performing some bit extractions, and bit shifting dataValue>>4 all before the complete data has been read into dataValue.

I can't seem to find another copy of the manual online, other than the one that was emailed to me.

clock is over RS422
DATA is over RS422

I am using the TI chip to make CLOCK+ CLOCK- to just CLOCK and DATA+ DATA- to just DATA

Here are some of the documents

I am using a TI SN75178BP to convert CLOCK+ CLOCK- to D and DATA+ DATA- to R.

Is that a bidirectional interface chip? How do you have it connected?

I've seen reference to SN65HVD179 http://www.ti.com/lit/ds/symlink/sn65hvd179.pdf

Hi
Refer post #2, did you try the sketch I refered to?
Or at least looked at how it works, it is very well commented.
Are you using 120R resitors across the pairs?
Tom... :slight_smile:

@Tom George The link you posted returns "web page not available" when I click it.

boolean clockPin = 7;
boolean dataPin = 8;

[...]

pinMode(clockPin, OUTPUT);
digitalWrite(clockPin, HIGH);
pinMode(dataPin, INPUT);

Unusual use of Boolean. And to think I've been limiting myself to just true and false values.

(you might want to read up more on data types)

Regards,

Brad.

TomGeorge:
Hi
Refer post #2, did you try the sketch I refered to?
Or at least looked at how it works, it is very well commented.
Are you using 120R resitors across the pairs?
Tom... :slight_smile:

I did try your code you linked, it does not work, looking at the scope, I think I am possible running into timing issues on the Arduino and that it might not be a viable platform for this unit.

If I am understanding the documentation correctly, I have to pulse the unit 25 times in 15Microseconds at max. with each pulse being at least 120NanoSeconds.

If I am understanding the documentation correctly, I have to pulse the unit 25 times in 15Microseconds at max. with each pulse being at least 120NanoSeconds.

No each clock pulse has to be completed within 15 us, and the minimum H or L time is 120 ns. digitalRead() and digitalWrite() are about 3-4 us each, and time out well with SSI.

Your port manipulation and delayMicroseconds(3) should be equivalent and should work as the clock pulse.

Ok I have it getting data back now... someone unplugged my Negative lead, I didn't see it till today.

I used the code in the other page linked, and then modified it.

const int CLOCK_PIN = 5; //CLOCK to RS422 CHIP
const int DATA_PIN = 6; //DATA from RS422 CHIP
const int BIT_COUNT = 25; //BITS needed to be read from encoder
static unsigned long int outputValue = 0;
void setup() {
  pinMode(DATA_PIN, INPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  
  digitalWrite(CLOCK_PIN, HIGH);

  Serial.begin(115200);
}

void loop() {
  long int reading = readPosition();
//  outputValue = reading >> 0;
  Serial.println(reading);
  delay(200);
}

//read the current angular position
float readPosition() {
  unsigned long sample1 = shiftIn(DATA_PIN, CLOCK_PIN, BIT_COUNT);
  delayMicroseconds(30);  // Clock must be high for 20 microseconds before a new sample can be taken
  return sample1; 
}

//read in a byte of data from the digital input of the board.
unsigned long shiftIn(const int data_pin, const int clock_pin, const int bit_count) {
  unsigned long data = 0;

  for (int i=0; i<BIT_COUNT; i++) {
    data <<= 1; // shift all read data left one bit.
    //digitalWrite(clock_pin,LOW);
    PORTD &= ~(1 << 5); // clock pin goes low
    delayMicroseconds(1);
    data |= digitalRead(DATA_PIN);
    //digitalWrite(clock_pin,HIGH);
    PORTD |= (1 << 5); // lock pin goes high
    delayMicroseconds(1);

    //data |= digitalRead(DATA_PIN); // cat the new read bit to the whole read data.
  }
  return data;
}

The only problem now is I cannot get a 0 result to come back from this encoder.

It should be 19Bit(524,288)

If I drop the BIT_COUNT to 19 I get numbers in the range I expect but I get to 524,288 and the next thing that shows up is its half and it starts all over again.
Am I reading the data wrong somewhere? Am I missing a sign bit?

If I put the BIT_COUNT to 25, I get numbers like 16756079

I think I'm running into a stuck bit. not sure how to get around it though

Ok, so as long as I have the oscilloscope attached it is consistent on these values. However as soon as I take the oscilloscope out, I am getting values changing randomly, could this be due to a ground loop?

I am grounding the oscilloscope lead to the bread board and then looking at port 2 which is the R port on the RS422 chip.

Did somebody unplug the ground wire again?

No, I can actually lift the oscilloscope and watch the values change. I will look at this tomorrow I guess.

Here is what I did with this code so far, holds a fixed place, and adjusts for weight etc.

Hi,
Check how you are reading the bits in, MSB or LSB first.
Can you provide a link to your particular encoder VJ11 does not compute.
Tom... :slight_smile:

I am reading it MSBFIRST, I will upload the VJ11 Manual and send it as a link, they no longer have it on their site.

If I am reading the oscilloscope correctly, its a stuck bit from the encoder, which doesn't make sense to me. It may be possible I need to introduce a 1K resister on the read line, but for how short the link is, I did not think I would need it.