LS7366R advice

Hi guys and girls,

Hopefully you can help me. Ive been trying all day to solve this and i think im currently stuck.
Ive got a teensy 3.5 on spi1 linked to a LS7366R and it should have a 4 byte counter. but no matter what i do it only ever seems to count on the first 2 bytes and nothing more (other than rolling over). Does anyone have any experience with this chip to tell me where im going wrong at all?

Ive tried lots of different examples and they all act exactly the same, this is the values coming back from each of the 4 bytes returned and no matter what the first two stay at 0, 0 or 255, 255 if it rolls over.

255, 255, 4, 224 Reading, 4294903008 Status, 4
255, 255, 3, 20 Reading, 4294902548 Status, 4
255, 255, 2, 13 Reading, 4294902285 Status, 4
255, 255, 0, 9 Reading, 4294901769 Status, 4
255, 255, 254, 9 Reading, 4294966793 Status, 4    << why did this happen its like the first two never change
255, 255, 252, 15 Reading, 4294966287 Status, 4
255, 255, 250, 11 Reading, 4294965771 Status, 4
#include <SPI.h>

#define SS1 24


// These hold the current encoder count.
signed long encoder1count = 0;

void initEncoders() {

  // Set slave selects as outputs
  pinMode(SS1, OUTPUT);


  // Raise select pins
  // Communication begins when you drop the individual select signsl
  digitalWrite(SS1, HIGH);


  SPI1.begin();

  // Initialize encoder 1
  //    Clock division factor: 0
  //    Negative index input
  //    free-running count mode
  //    x4 quatrature count mode (four counts per quadrature cycle)
  // NOTE: For more information on commands, see datasheet
  digitalWrite(SS1, LOW);       // Begin SPI conversation
  SPI1.transfer(0x88);                       // Write to MDR0
  SPI1.transfer(0x03);                       // Configure to 4 byte mode
  digitalWrite(SS1, HIGH);      // Terminate SPI conversation
}

long readEncoder() {

  // Initialize temporary variables for SPI read
  unsigned int count_1, count_2, count_3, count_4;
  long count_value;
  
  digitalWrite(SS1, LOW);     // Begin SPI conversation
  SPI1.transfer(0x60);                     // Request count
  count_1 = SPI1.transfer(0x00);           // Read highest order byte
  count_2 = SPI1.transfer(0x00);
  count_3 = SPI1.transfer(0x00);
  count_4 = SPI1.transfer(0x00);           // Read lowest order byte

  digitalWrite(SS1, HIGH);    // Terminate SPI conversation

  // Calculate encoder count
  count_value = (count_1 << 8) + count_2;
  count_value = (count_value << 8) + count_3;
  count_value = (count_value << 8) + count_4;
  Serial.print(count_1);
  Serial.print(" ");
  Serial.print(count_2);
  Serial.print(" ");
  Serial.print(count_3);
  Serial.print(" ");
  Serial.print(count_4);
  Serial.print("\n");
  return count_value;
}

void clearEncoderCount() {

  // Set encoder1's data register to 0
  digitalWrite(SS1, LOW);     // Begin SPI conversation
  // Write to DTR
  SPI1.transfer(0x98);
  // Load data
  SPI1.transfer(0x00);  // Highest order byte
  SPI1.transfer(0x00);
  SPI1.transfer(0x00);
  SPI1.transfer(0x00);  // lowest order byte
  digitalWrite(SS1, HIGH);    // Terminate SPI conversation

  delayMicroseconds(100);  // provides some breathing room between SPI conversations

  // Set encoder1's current data register to center
  digitalWrite(SS1, LOW);     // Begin SPI conversation
  SPI1.transfer(0xE0);
  digitalWrite(SS1, HIGH);    // Terminate SPI conversation

}


void setup() {
  Serial.begin(9600);      // Serial com for data output

  initEncoders();       Serial.println("Encoders Initialized...");
  clearEncoderCount();  Serial.println("Encoders Cleared...");
}

void loop() {
  delay(200);

  // Retrieve current encoder counters
  encoder1count = readEncoder();
  
  Serial.print("Enc1: "); Serial.print(encoder1count);
  Serial.println();
  
}

Thanks in advance Trev

A glance at the data sheet suggests that the following setup is incorrect. At the very least the second comment is wrong. MDR1 is the register that defines the number of counter bytes, and the bottom three bits are set to zero for 4 byte mode.

  SPI1.transfer(0x88);                       // Write to MDR0
  SPI1.transfer(0x03);                       // Configure to 4 byte mode

Setting MDR0 to 3 results in 4x count mode.

Thanks, yes i saw the comments on the example code i used was off sorry about that. By default the chip is meant to start in 4 byte mode as thats the inital value in MDR1.

I did a test where i wrote a 4 byte value to one of the registers on the chip and read it back and that worked fine, but if it let it do its counting thing it only returns 2 byte numbers.

Thanks again

Trev

Try setting it to 4 byte mode, writing to MDR1.

Why do you get 255 from registers that you believe are not being used? This suggests a communications problem.

Hi, well I tried all night again with no joy. I tried setting the register to 4 bit and still the same.

The reason I don't think it's counting right is the first two bytes to the left stay at 255 to toggle to 0 some times (not sure why). But it never counts greater than an int.

I've tried different spi modes and speeds and still the same or no result at all. Like I say it only ever seems to use the two bytes to the left. If I write directly to the registers I can read back what I write but not if I'm reading of the linear scale.

Thank you for your help

Trev

Perhaps you are rotating the encoder shaft in such a way that the total count is negative. In that case, the 4 byte sign extended value will have all ones in the higher registers.

(long) (-1) == 0xFFFFFFFF

Write a program that sets the counter registers to all zeros, then reads them back immediately, and then again after small rotations in either direction.

I just wanted to say thank you for all your help regarding this.

Tonight i finally cracked it. Basically its by far the most complicated thing ive ever made, and as a result i was very much second guessing myself.
The main thing was this project has a glass linear encoder feeding a differential line receiver and then the LS7366r (which has a 40mhz oscillator on it and the chip is at 5v). The microcontroller is a teensy 3.6 which runs at 180mhz (dont worry there are level shifters and what not as the teensys io is 3.3v). So i thought as the oscillator on the LS7366r is 40mhz the spi should handle 16 MHz fine. Also this was back up by the fact that it would read and write fine (but only the first 2 bytes of a 32bit number). So being dumb i started to look as to why thinking the differential driver was the cause (not really logical i know in hind sight). well after messing about tonight, i dropped the spi transaction down to 4000000 and it works great (just as you hinted at in post 3, but i thought it would work or not at all as i was getting the first two bytes reliably as said above). I may try 8000000 and see how i get on.

255 255 48 231  Count: -53017 Value: -265.0850mm
255 255 31 48  Count: -57552 Value: -287.7600mm
255 255 31 15  Count: -57585 Value: -287.9250mm
255 255 31 255  Count: -57345 Value: -286.7250mm
255 255 30 236  Count: -57620 Value: -288.1000mm
255 255 29 127  Count: -57985 Value: -289.9250mm
255 255 27 207  Count: -58417 Value: -292.0850mm
255 255 15 219  Count: -61477 Value: -307.3850mm
255 255 12 254  Count: -62210 Value: -311.0500mm
255 255 7 223  Count: -63521 Value: -317.6050mm
255 255 3 31  Count: -64737 Value: -323.6850mm
255 254 255 251  Count: -65541 Value: -327.7050mm
255 254 254 60  Count: -65988 Value: -329.9400mm
255 254 252 254  Count: -66306 Value: -331.5300mm
255 254 255 55  Count: -65737 Value: -328.6850mm
255 254 248 123  Count: -67461 Value: -337.3050mm
255 254 255 251  Count: -65541 Value: -327.7050mm
255 254 247 255  Count: -67585 Value: -337.9250mm

Its intended to be crazy accurate as its for a dro on my lathe and milling machine.

Thank you loads for you help

Kind regards

Trev