SSI data bit manipulation. I'm so bad!

After some misunderstanding and head bashing I have managed to read SSI data from an absolute encoder using SPI. I had it working just bit banging it out switching a clock pin on and off. I wasn't great but by stealing ideas and some bits of code from this forum I got it working ok(ish).

The SPI examples I found here never worked for me so I started from scratch and now it works really well. No errors and a reading every 50ms(ish).

#include <SPI.h>

  unsigned int receivedVal;
  unsigned int receivedVal2;
  unsigned int result;
  int temp;


void setup() {
  Serial.begin(115200);
  SPI.begin();
  delay(100);
}

void loop() {
  
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
receivedVal = SPI.transfer(0xFF);
receivedVal2 = SPI.transfer(0xFF);

temp = bitRead(receivedVal, 6);
bitWrite(result, 12, temp);
temp = bitRead(receivedVal, 5);
bitWrite(result, 11, temp);
temp = bitRead(receivedVal, 4);
bitWrite(result, 10, temp);
temp = bitRead(receivedVal, 3);
bitWrite(result, 9, temp);
temp = bitRead(receivedVal, 2);
bitWrite(result, 8, temp);
temp = bitRead(receivedVal, 1);
bitWrite(result, 7, temp);
temp = bitRead(receivedVal, 0);
bitWrite(result, 6, temp);
temp = bitRead(receivedVal2, 7);
bitWrite(result, 5, temp);
temp = bitRead(receivedVal2, 6);
bitWrite(result, 4, temp);
temp = bitRead(receivedVal2, 5);
bitWrite(result, 3, temp);
temp = bitRead(receivedVal2, 4);
bitWrite(result, 2, temp);
temp = bitRead(receivedVal2, 3);
bitWrite(result, 1, temp);
temp = bitRead(receivedVal2, 2);
bitWrite(result, 0, temp);

float angle = result * 0.04395;

Serial.println(angle);
delay(50);
 
}

My problem is that I can't work out how to manipulate the bits from the two bytes to extract the relevant data. I resorted to using bitRead and bitWrite but I am sure there must be a better way.

Neither byte seems to be used entirely, bits 6 to 0 from the first byte and bits 7 to 2 from the second byte. I have spent time looking at all the bit manipulation commands and looked at examples but I just haven't managed to make it work.

The encoder is Kubler type 8.5873.5320.B301.S003

I have a Nano and I am interfacing through a SN75179BC line transceiver.
wiring scaled

Any help with the bits would be appreciated.

Image looks bad so here it is again. The actual line trasceiver I bought is extremely small so you should probably find an alternative if you want to do this. Pay close attention to the dimensions before ordering, these are 5 x 3.5mm with 8 SM pins, really not easy to solder wires to it :rofl:

You say 2 bytes, but you are reading 2 16 bit unsigned integers through SPI....

The easiest way to combine them is to use the bit shift operators

// assume receivedVal and receivedVal2 as above
unsigned int result = 0;
result = receivedVal & 0x3F;  // bits 6..0
result = result << 8;  // but in top byte
result = result + (receviedVal2 & 0xFC);  // bits 7..2

Needs a six-bit shift to the left to put receviedVal 6 through 0 into result 12 through 6 and a two-bit shift to the right to put receviedVal2 7 through 2 into result 5 though 0.

// assume receivedVal and receivedVal2 as above
unsigned int result = (receivedVal & 0x3F) << 6;  // bits 6..0 -> 12..6
result |= (receviedVal2 & 0xFC) >> 2;  // bits 7..2 -> 5..0

Or use or… addition works here because there is no possibility of a carry operation. But might as well keep it all logical

Or

result |= receviedVal2 & 0xFC;

At least get to recognize it when you reading code.

And also get it right, if I follow @johnwasser's version.

a7

OK I think I understand what you are all doing with the bits, the & 0x3F is the part I need to understand better but I will work it out.

Both of the versions return the wrong result but that is ok. I wanted to know how to do it and debugging it will help me to understand it better.

Thanks very much for the help. If I get really stuck I will come back for more help.

Do, and also when you get it all sorted.

It helps to me draw pictures of the variables in binary.

It also helps to verify the contents of the variables informing the bit manipulation, you know GIGO. If you don't have those twelve bits where you think, they will never end up where you want.

No shame in copious serial printing.

Lastly, it helps (me) to do experiments far away from any other things going on. For this, I recommend using the wokwi simulator and testing with tiny sketches what do only assignment and the bit manipulation and printing.

a7

That looks real useful, I will definitely check it out when I get time but it might be so useful for this if you can't simulate the device I am trying to listen to.
I might not get back to look at this until next week, I also have some real work to do inbetween these little projects and unfortunately they take priority.

I did have a lot of print statements at one point and then slowly rotated the encoder while trying to understand the order of the bits. Thats how I got to where I am. I will definitely be back to show my results.

Cheers

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.