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);
}