SSI Protocol and Clock Errors

Hey everyone in the Forum,
i’m currently trying to develop a angular movement measurement tool for a specific test, that I have to perform every once in a while.

So far, I have set up the following assembly:
A angular encoder called ECN413 from the company Heidenhain. This sensor can be interfaced using the SSI „protocol“. On the other end there is an Arduino Uno running software, that uses this SSI standard to obtain absolute angular position data from the sensor. I’m able to obtain values that are correct. But every 6 or 7 readings, that readout is corrupt, meaning that the value is wrong.

I attached a picture of the SSI Protocol (Synchronous Serial Interface) and an oszilloscope reading of my data and clock line (TTL-level, so before and after the actual RS-485 conversion). I nailed the problem down to the fact, that whenever there is a slight hick-up in the clock, there is a misreading in the data. According to the manufacturer of the sensor there should only be a problem if the time the clock stays high during those clock cycles is bigger than what they call monoflop-time (20µs). This resets the sensors and a new value is read in and then send with the next falling slope of the clock level. As far as I can tell, there are also problems when the low level period is longer than average / „normal“.

I also atteched my current source code. I have so far disabled the interrupts when the readout starts and reenable them when the readout is over. Furthermore I noticed, that when I deactivated all interrupts in the setup function, so to speak for the complete program, the normal „dealy()“ function stops working properly. I read in the forum, that there was an issue with delayMicroseconds and Interrupts, but I removed all calls to that function as well from the readout.

Simply put, I’m quite out of ideas as to why the clock becomes irregular every couple readings. Every idea is appreciated.
I will also try to use the standard SPI-library to read the data (like readin two bytes and truncating the last 3 bits, so I only keep the 13 with the information. The sensor starts to resend the value, when the monoflop time is not reached after the complete send of the value).

If you have any question or need additional figure or graphs to have a better idea of what my problem is, please ask via post and I will try to provide them as soon as possible. As I said, every help is appreachiated.

Attachments:
The picture TEK0001.JPG shows a graph 1 / yellow the TTL-level clock signal triggered with the first falling slope marked with the little black arrow in the top left corner. In the mint-color is the data TTL-level signal which would be all zero for the whole clock-period, as the sensors was set to zero. But with the third rising slope of the clock the data starts, the clock being high for some time already, to go up to high instead of staying low. And from my reading of the clock’s third high period this period is roughly 13 µs, so not even close to the 20µs Monoflop-Time.

The picture TEK0004.JPG shows pretty much the same situation, but this time the low period of the clock is longer than average and right after that the data starts to be wrong (again the sensor was set to zero).

Thank you so much of all the help!
All help is very much appreciated !

Kind regards
Niels Göran

// Niels Göran Blume
// Protractor

#include <MI0283QT2.h>
#include <SPI.h>
#include <stdlib.h>
#include <stdint.h>

// PIN-Usage:
// =========================================
// PIN 13  SCL of SPI-Bus
// PIN 12  SDO of SPI-Bus
// PIN 11  SDI of SPI-Bus
// PIN 10  Ethernetshield   CS_PIN W5100
// PIN 09  MI0283QT-02      LED_PIN
// PIN 08  MI0283QT-02      RST_PIN
// PIN 07  MI0283QT-02      CS_PIN Display
// PIN 06  MI0283QT-02      CS_PIN Touch
// PIN 05  SSI_CLOCK_1_PIN
// PIN 04  SSI_DATA_1_PIN
// PIN 03  SSI_CLOCK_2_PIN
// PIN 02  SSI_DATA_2_PIN
// PIN 01  SERIAL_TX
// PIN 00  SERIAL_RX
// =========================================

#define SSI_CLOCK 3
#define SSI_DATA 2

MI0283QT2 lcd;

int counter = 0;
float angle = 0;
unsigned int readinbytes = 0;
int status_transfer;
char sensor0char[15];
float angleRead = 0;

float readSensor(void)
{
  readinbytes = 0;
  
//  delayMicroseconds(40);

  // Disable interrupts
  noInterrupts();  
  for (counter = 0; counter < 14; counter++) // 14 ?? initial bit=1, but how many bits overall??
  {  
     // Create falling edge on clock
     digitalWrite(SSI_CLOCK, LOW);
     
     readinbytes = (readinbytes << 1);
     
     // delayMicroseconds(2);
     
     // Read the port data (when CLOCK is LOW !!!!)
     if( (digitalRead(SSI_DATA)) && (counter != 0) )
     {
       readinbytes = readinbytes | 0x01;
     }
     
     // Create rising edge on CLOCK-pin for start of trasmission of next bit
     digitalWrite(SSI_CLOCK, HIGH);
     
     // delayMicroseconds(1);
  }
  // Re-enable interrupts
  interrupts();
  
  Serial.print("Readin-Bits as binary before decode: ");
  Serial.println(readinbytes, BIN);
  
  // Gray code obtained, transformed to binary code
  readinbytes ^= (readinbytes >> 16);
  readinbytes ^= (readinbytes >> 8);
  readinbytes ^= (readinbytes >> 4);
  readinbytes ^= (readinbytes >> 2);
  readinbytes ^= (readinbytes >> 1);

  Serial.print("Readin-Bits after decode: ");
  Serial.println(readinbytes, BIN);
  
  angle = ((float)readinbytes / 8192 * 360);
  
  if (angle > 180)
  {
    angle = (float)angle - 360;  
  }
  
  Serial.print("Messwert: ");
  Serial.println(angle,4);  
  
  return angle;
}

void setup()
{ 
  
  // Init Serial port
  Serial.begin(38400); 
  Serial.println("Init Arduino...");
  // End Init Serial

  // Init Display
  Serial.println("Init Display and SSI-Port");
  lcd.init(2); //spi-clk = Fcpu/2
  lcd.led(60); //backlight 0...100%
  //clear screen
  lcd.clear(RGB(255,255,255));

  lcd.drawTextPGM(5, 40, PSTR("Encoder-Values"), 1, RGB(0,0,0), RGB(255,255,255));
  lcd.drawTextPGM(5, 55, PSTR("Enc 1:"), 2, RGB(0,0,0), RGB(255,255,255));
  // End Init Display

  // Initialize SSI-Port
  pinMode(SSI_DATA, INPUT);
  pinMode(SSI_CLOCK, OUTPUT);
  // SSI-Port is idle high
  digitalWrite(SSI_CLOCK, HIGH);
  // End Init SSI-Port
  delay(100);
  lcd.drawText(5, 180, "Initialization completed...", 1, RGB(0,0,0), RGB(255,255,255));
}


void loop()
{   
  angleRead = 0;
  
  angleRead = readSensor();
  
  dtostrf(angleRead,6,4,sensor0char);
  strcat(sensor0char, "\xF8   ");
  
  lcd.drawText(140,55, sensor0char, 2, RGB(0,0,0), RGB(255,255,255));
  
  Serial.println("Cycle finished....");    
  
  delay(1500);
}

schematic_2010_12_07.png

ssi.png

TEK0001.JPG

TEK0004.JPG

One more graph, which I couldn’t add to the previous post due to the 4 attachments only limitation:

The picture TEK0019.JPG shows the situation mentioned for picture TEK0001.JPG a liitle more up close. It is clearly visible that, the high period is a little longer than average, but a maximum of 14 µs, which again is definitely less than 20µs.
I also attached the schematics of the board that I put on top of the Arduino to also proper level-changing from TTL to RS-485. I hope everything is ok there. If that would be the problem, I would be really devistated. SO feel free to have a look at that, too.

Thank you !

Kind regards
Niels Göran

TEK0019.JPG