Arduino UNO and CUI encoder (SPI )

Good Day ALL

I am trying to interface an absolute encoder with the Arduino. I have never worked with SPI, I have read information and understand the concept. I am just unclear when it comes to setting the code up. I found an example that someone had posted for the encoders they were working with , so I took the code and tried modifying it to work with the CUI encoder but am a bit lost. Please lend me a hand if you can. Note the code may not make much sense as it has some pieces of the old code basically I added the pins for MOSI , MISO, and CS.

const int PIN_CS = 4;
const int PIN_CLOCK = 13;
const int PIN_MOSI =11;
const int PIN_MISO = 12;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_MOSI, OUTPUT);
  pinMode(PIN_MISO, INPUT);

  digitalWrite(PIN_CLOCK, HIGH);
  digitalWrite(PIN_CS, LOW);
}


//byte stream[16];
void loop() {

  digitalWrite(PIN_CS, HIGH);
  digitalWrite(PIN_CS, LOW);
  int pos = 0;
  for (int i=0; i<10; i++) {
    digitalWrite(PIN_CLOCK, LOW);
    digitalWrite(PIN_CLOCK, HIGH);
    
    byte b = digitalRead(PIN_MOSI) == HIGH ? 1 : 0;
    pos += b * pow(2, 10-(i+1));
  }
  for (int i=0; i<6; i++) {
    digitalWrite(PIN_CLOCK, LOW);
    digitalWrite(PIN_CLOCK, HIGH);
  }
  digitalWrite(PIN_CLOCK, LOW);
  digitalWrite(PIN_CLOCK, HIGH);
  Serial.println(pos);
}

I appreciate any help/examples that you guys can offer.

JH

encoder http://www.cui.com/Product/Components/Encoders/Absolute_Encoders/Modular/AMT203-V

I am working on similar stuff (Connecting arduino to AMT203-V). arduino as the master and AMT203-V as slave. The goal is to display the encoder reading.

I still can't figure out how or where to read in the manual AMT203-V and get the necessary information for SPI connection.

The codes That i fill up so far

//Include the SPI library
#include <SPI.h>

//Set the slave select pin
//Other SPI pins are set automatically
int SS=10; //Any pin can be used for SS(slave select) signal. 
//we choose 10 here

void setup()
{
  Serial.begin(9600);
  //Set SS Pin Directions 
  //Others are Handled Automatically 
  pinMode(SS,OUTPUT);
  SPI.setBitOrder(MSBFIRST); //Most significent bit or use
  //LSBFIRST least significent bit
  //Initialize SPI
  SPI.begin();
  
}

void loop()
{
  int encoder_value=EncoderRead()
  Serial.println(encoder_value);
  delay(1000);
}

int EncoderRead() {
  // take the SS pin low to select the chip:
  digitalWrite(SS,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(SS,HIGH); 
}

Still no luck with the codes

I try ignoring the SPI library and use shiftin instead and still no luck

here is my updated codes

void setup()
{
  pinMode(4,OUTPUT);//CLock Pin
  pinMode(5,OUTPUT);//Data Pin
  pinMode(3,OUTPUT);//Slave Select
  Serial.begin(9600);
}

byte incoming;

void loop()
{ 
digitalWrite(3,LOW);
byte incoming =  shiftIn(5,4,LSBFIRST);
Serial.println(incoming);
digitalWrite(3,HIGH); 
delay(1000);
 
}

I am getting all zero reading...

Is it possible that you have to ask the decoder for something first? Perhaps absolute position? or that it might require some kind of calibration/initialization or reset first time it's used or powered up?

Doc

My updated codes still no luck

#include <SPI.h>
void setup()
{
  SPI.begin();
  pinMode(3,OUTPUT);//Slave Select
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  Serial.begin(9600);
}



void loop()
{ 
digitalWrite(3,LOW);
 byte response = SPI.transfer(0);
Serial.println(response);
digitalWrite(3,HIGH); 
delay(1000);
}

From datasheet

The msb data out on MISO is valid soon after CSB goes low. The MOSI data is valid soon after the falling edge
of SCK. The Encoder drives data out on MISO as long as CSB is low.
Normally, CSB goes low, then after 8 clocks the command is interpreted. CSB high resets the
clock counter, and terminates any command sequence.

which can be found here http://www.cui.com/product/resource/amt203.pdf

Running this code i get 0, 255 no idea why...
it is weird i am expecting a byte and i am getting 0 or 255.

Docedison:
Is it possible that you have to ask the decoder for something first? Perhaps absolute position? or that it might require some kind of calibration/initialization or reset first time it's used or powered up?

Doc

I found this doc http://www.cui.com/product/resource/amt203-appnote.pdf
it tells you exactly what to send here is the updated code i am using
.

#include <SPI.h>
void setup()
{
  SPI.begin();
  pinMode(3,OUTPUT);//Slave Select
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  digitalWrite(3,LOW);
 byte response = SPI.transfer(0x00);
 digitalWrite(3,HIGH); 
  Serial.begin(9600);
}



void loop()
{ 
digitalWrite(3,LOW);
 byte response = SPI.transfer(0x10);
 digitalWrite(3,HIGH); 
     Serial.print("I received: ");
     Serial.print(response, BIN);
     Serial.print("  this has an ASCII value of ");
     Serial.println(response ,DEC);  
delay(2000);

}

I am still getting weird numbers...

I found out the datasheet page 4 of it with all information needed http://www.cui.com/product/resource/amt203-appnote.pdf

i still can't figure what why my code is not working

I got the code working

here is the update code

#include <SPI.h>
void setup()
{
  SPI.begin();
  pinMode(3,OUTPUT);//Slave Select
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  digitalWrite(3,LOW);
 byte response = SPI.transfer(0x00);
 digitalWrite(3,HIGH); 
  Serial.begin(9600);
}

void loop()
{ 
digitalWrite(3,LOW);
 byte response = SPI.transfer(0x10);
 digitalWrite(3,HIGH); 
     Serial.print("I received: ");
     Serial.println(response ,DEC);  
     
delay(1000);
}

I am getting 3 reading and the buffer doesn't reset after each reading. 2 of the reading are junk or i am not sure what they are.

I looked at the encoder data sheet and it state this

Command 0x10: rd_pos
This command causes a read of the current position.
The sequence is as follows:

  1. issue read command, receive idle character
  2. issue NOP, receive idle character 0xA5 or 0x10
  3. repeat step 2 if it is 0xA5
  4. issue NOP and receive MSB position (4 bits valid data)
  5. issue NOP and receive LSB position (8 bits valid data)
    Note that it is possible to overlap commands, so instead of NOP is several steps above
    the user could start another operation. The read and write FIFOs for the PCI streams are
    16 bytes long and it is up to the user to avoid overflow

full datasheet can be found here
http://www.cui.com/product/resource/amt203.pdf

So the code gives what i expect it to receive. How to work with buffer? or how to select certain thing to be displayed instead of displaying everything. I think it display the position then MSB and LSB which i don't know how to remove them and just keep the display for the position. Also, I have 1 second delay, let say i rotate the encoder after couple of second i get the right position reading. as if the data was in a buffer and it send old data. so, is there a way to reset the buffer for each reading ? I don't want to get old data....

I figured out what the 3 bytes are

Here is the update code

//#define 3 3 //Slave select pin

#include <SPI.h>

float response[2];

void setup()
{
 
  pinMode(3,OUTPUT);//Slave Select
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  digitalWrite(3,HIGH);
  Serial.begin(9600);
  delay(5000);
 // byte answer[2];
  
}

void loop()
{ 
  // Serial.flush();
  digitalWrite(3,HIGH);
   SPI.begin();
   //For LOOP START HERE
    for (int i=0; i <= 2; i++){
     digitalWrite(3,LOW);
     response[i] = SPI.transfer(0x10);
     Serial.print(response[i] ,DEC); 
     Serial.print("  ");
     digitalWrite(3,HIGH); 
     delay(50);
   }//END FOR
   
   //Calculation NICK WAY BITS TO DEGREE
   delay(200);
     float total;
     total=((response[0]*256)+response[1])*360/4096;
     Serial.print(total,DEC);   
     Serial.println("  ");
   //END OF CALCULATION 
   digitalWrite(3,HIGH);
   SPI.end();

}

It work fine, The only problem i have is the bytes come everytime i start the program differently.
For example, byte1 byte2 byte3 comes in this expected order
lets say i run it again, i get byte3 byte1 byte2.

I was thinking about clearing the buffer like doing Serial.flush();
i am not sure how to fix it

Unwanted Results

182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000  
182.0000000000  16.0000000000  2.0000000000  4096.4062500000

First 3 columns I get from the Encoder, I do simple calculation to get the angle between 0-360 as you can see in column 4 the angle value is not right. since, the order i received was mixed up.

Keep closing and opening the serial monitor till i have the right one. and here it is.
Desired results

2.0000000000  182.0000000000  16.0000000000  60.9960937500  
2.0000000000  182.0000000000  16.0000000000  60.9960937500  
2.0000000000  182.0000000000  16.0000000000  60.9960937500  
2.0000000000  182.0000000000  16.0000000000  60.9960937500

Any expert (or ideas) in byte order will be greatly appreciated

I figured it out,

So what i was receiving was 3 bytes, 4bits, 8bits, and a constant number 16.

I used the 16 as my reference point because after number 16 I get 4bits and 8bits always

So my codes work fine now.

If anyone stuck with cui inc encoder I can help.

Here is the codes for cui inc encoder that I wrote.

I feel this code can undergo alot of improvements for example efficient wise. like faster running.

Any idea where to start. All idea are appreciated.

#define CS 3 //Chip or Slave select 
#include <SPI.h>

float response[2];
float Wheel_Diameter=6.615; //mm

void setup()
{
  pinMode(CS,OUTPUT);//Slave Select
  digitalWrite(CS,HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  Serial.begin(9600);
  Serial.flush();
  delay(2000);
  SPI.end();
  

}

void loop()
{ 
   digitalWrite(CS,HIGH);
   SPI.begin();
   
     //For LOOP START HERE
    for (int i=0; i <= 2; i++){
     digitalWrite(CS,LOW);
     delay(5);
     response[i] = SPI.transfer(0x10);
    // Serial.print(response[i],DEC); 
     //Serial.print("  ");
     digitalWrite(CS,HIGH);  
   }//END FOR
   if (response[0]==16.0)
   {
     if(response[1]==16.0)
     {
     }
     else if(response[2]==16.0)
     {
     }
     else
     {
     float total;
     total=((response[1]*256)+response[2])*360/4096; 
     Serial.print(total,DEC);   
     Serial.println("  ");
     }
   }
   else if (response[1]==16.0)
   {
     if(response[0]==16.0)
     {
     }
     else if(response[2]==16.0)
     {
     }
     else
     {
     float total;
     total=((response[2]*256)+response[0])*360/4096; 
     Serial.print(total,DEC);   
     Serial.println("  ");
     }
   }
  else if(response[2]==16.0)
   {
     
     if(response[0]==16.0)
     {
     }
     else if(response[1]==16.0)
     {
     }
     else
     {
     float total;
     total=((response[0]*256)+response[1])*360/4096; 
     Serial.print(total,DEC);   
     Serial.println("  ");
     }
   }
   

   
   digitalWrite(CS,HIGH);
   SPI.end();
 
}//END LOOP

Hay Ya, thanks for posting your code, it helped me get started.
not sure about the order mix up issue you have a, i don't seem to have it.

here is what i did anyway and don't seem to have any issues
cheers

#include <SPI.h>

#define CS 3 //Chip or Slave select 

uint16_t ABSposition = 0;
uint16_t ABSposition_last = 0;
uint8_t temp[1];

float deg = 0.00;

void setup()
{
  pinMode(CS,OUTPUT);//Slave Select
  digitalWrite(CS,HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  Serial.begin(115200);
  Serial.println("starting");
  Serial.flush();
  delay(2000);
  SPI.end();

}
uint8_t SPI_T (uint8_t msg)    //Repetive SPI transmit sequence
{
   uint8_t msg_temp = 0;  //vairable to hold recieved data
   digitalWrite(CS,LOW);     //select spi device
   msg_temp = SPI.transfer(msg);    //send and recieve
   digitalWrite(CS,HIGH);    //deselect spi device
   return(msg_temp);      //return recieved byte
}

void loop()
{ 
   uint8_t recieved = 0xA5;    //just a temp vairable
   ABSposition = 0;    //reset position vairable
   
   SPI.begin();    //start transmition
   digitalWrite(CS,LOW);
   
   SPI_T(0x10);   //issue read command
   
   recieved = SPI_T(0x00);    //issue NOP to check if encoder is ready to send
   
   while (recieved != 0x10)    //loop while encoder is not ready to send
   {
     recieved = SPI_T(0x00);    //cleck again if encoder is still working 
     delay(2);    //wait a bit
   }
   
   temp[0] = SPI_T(0x00);    //Recieve MSB
   temp[1] = SPI_T(0x00);    // recieve LSB
   
   digitalWrite(CS,HIGH);  //just to make sure   
   SPI.end();    //end transmition
   
   temp[0] &=~ 0xF0;    //mask out the first 4 bits
    
   ABSposition = temp[0] << 8;    //shift MSB to correct ABSposition in ABSposition message
   ABSposition += temp[1];    // add LSB to ABSposition message to complete message
    
   if (ABSposition != ABSposition_last)    //if nothing has changed dont wast time sending position
   {
     ABSposition_last = ABSposition;    //set last position to current position
     deg = ABSposition;
     deg = deg * 0.08789;    // aprox 360/4096
     Serial.println(deg);     //send position in degrees
   }   

   delay(10);    //wait a bit till next check
 
}

Wonderful! Thanks a lot to all the contributors.
Uaefame, I suppose you already fix the problem but for future readers the problem was, very probably, that the AMT encoder expects for a specific order of commands (as jamiec code's show).

Just a detail with the jamiec code, the temp variable must be an array of two elements, I think:

.
.
.
uint16_t ABSposition = 0;
uint16_t ABSposition_last = 0;
uint8_t temp[2];    //This one.

float deg = 0.00;
.
.
.

Thanks again.

Is it possible to have this code record continuous revolutions, rather than resetting after each full revolution?

Guys, great work. I got the CUI 203 encoder working straight away using the code from this thread.

This works great and is exactly what is needed for quickly getting encoder data.

The only modification I made was changing to temp[2] as JLuisMX suggested.

JLuisMx:
Wonderful! Thanks a lot to all the contributors.
Uaefame, I suppose you already fix the problem but for future readers the problem was, very probably, that the AMT encoder expects for a specific order of commands (as jamiec code's show).

Just a detail with the jamiec code, the temp variable must be an array of two elements, I think:

.

.
.
uint16_t ABSposition = 0;
uint16_t ABSposition_last = 0;
uint8_t temp[2];    //This one.

float deg = 0.00;
.
.
.




Thanks again.

Hi,
I know this is an old topic, and if I don't get a response I'll make a new one, but I was hoping to get help from the good people that were here before. Me and my team are working on an apparatus that will perform a fly fishing cast for people in wheelchairs. Our code and machinery MOSTLY work, but basically
our encoder (the same one from this forum and using code borrowed from it as well) freaks out when it hits zero and refuses to change direction. As long as we don't go near the zero point we're ok, but it also resets where zero is each time its turned off. I looked at the data sheet and it said there was a way to zero the encoder....period stop, it said it can be done, nothing on HOW.....sob.... Anyway, I'm hoping there's a way to change that in the code. Here's what we have:
//Note I tried posting my whole code, it was too long, if you need more let me know.

  float encoder_read()
 { 
   uint8_t recieved = 0xA5;    //just a temp vairable
   ABSposition = 0;    //reset position vairable
   SPI.begin();
   digitalWrite(CS,LOW);
   
   SPI_T(0x10);   //issue read command
   
   recieved = SPI_T(0x00);    //issue NOP to check if encoder is ready to send
   
   while (recieved != 0x10)    //loop while encoder is not ready to send
   {
     recieved = SPI_T(0x00);    //check again if encoder is still working 
     delay(2);    //wait a bit
   }
   
   temp[0] = SPI_T(0x00);    //Recieve MSB
   temp[1] = SPI_T(0x00);    // recieve LSB
   
   digitalWrite(CS,HIGH);  //just to make sure   
  SPI.end();    //end transmition
   
   temp[0] &=~ 0xF0;    //mask out the first 4 bits
    
   ABSposition = temp[0] << 8;    //shift MSB to correct ABSposition in ABSposition message
   ABSposition += temp[1];    // add LSB to ABSposition message to complete message
    
   if (ABSposition != ABSposition_last)    //if nothing has changed dont wast time sending position
   {
     ABSposition_last = ABSposition;    //set last position to current position
     deg = ABSposition;
     deg = deg * 0.08789;// aprox 360/4096
    
return(deg);
   delay(10);    //wait a bit till next check
   }
    Serial.println(deg);     //send position in degrees
   return;}

Hey guys,
I navigated to the web page for the 203-V

From there i found sample programming code for arduino here

I modified the "SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));" to 1000000 for faster response and have sucessfully got it working.

Encoder values can be read faster than shown in the CUI example and previous posts. Encoder stores position values in its buffer, as described in the datasheet:

Note that it is possible to overlap commands. For instance, instead of issuing nop_a5 for steps 3 and 4, you could begin another read
position sequence since the position data is already in the buffer. The read and write FIFOs for the streams are 16 bytes long and it is
up to the user to avoid overflow

I wrote a sketch (attached below) which uses this method, but there is a problem - position values sent from encoder are from several readings ago and are 3-4 degrees lower. Once the movement stops, values must be read from encoder until they catch up to encoder's real position (from my experiments it takes 5 to 20 reads), so use this at your own caution.

/*
  https://forum.arduino.cc/index.php?topic=158790.15
*/

//include SPI library
#include <SPI.h>
//this is the serial baud rate for talking to the Arduino
#define baudRate 500000
//SPI commands used by the AMT20
#define nop 0x00            //no operation
#define rd_pos 0x10         //read position
#define set_zero_point 0x70 //set zero point
//set the chip select pin for the AMT20
const int CS = 53;
double deg;
long distance; //to check if stepper has moved a step, accelstepper doesnt have this function while using .run();

#include <AccelStepper.h>
long positions[1]; // Array of desired stepper positions
AccelStepper stepper1(1, 54, 55);//(1 for A4988, Step pin, Dir pin), im using a 200 step stepper set to microstep size of 2

void setup()
{

  //  //Set I/O mode of all SPI pins.
  //  pinMode(SCK, OUTPUT);
  //  pinMode(MOSI, OUTPUT);
  //  pinMode(MISO, INPUT);
  //  pinMode(CS, OUTPUT);
  //Initialize SPI using the SPISettings(speedMaxium, dataOrder, dataAMode) function
  //For our settings we will use a clock rate of 500kHz, and the standard SPI settings
  //of MSB First and SPI Mode 0
  // SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
  //Using SPI.beginTransaction seems to require explicitly setting the beginning state
  //of the CS pin as opposed to the SPI.begin() function that does this for us.
  //  digitalWrite(CS, HIGH);
  SPI.begin();
  SPIWrite(set_zero_point); //issue set 0 point command
  while (SPIWrite(nop) != 0x80)    //
  {
  }
  SPI.end(); //cause device to power cycle, needs to set new 0 position
  delay(100);


  // Configure each stepper
  stepper1.setEnablePin(38);
  stepper1.setPinsInverted(false, false, true); //invert logic of enable pin
  stepper1.enableOutputs();
  stepper1.setMaxSpeed(50);
  stepper1.setAcceleration(50);

  //Initialize the UART serial connection
  Serial.begin(baudRate);
  Serial.println("starting");
  delay(3000);

  positions[0] = 100;

}

void loop() //moves the motor 90 deg and back twice, reading encoder value after each step, then stops completely
{
  stepper1.move(positions[0]);
  //  long a = millis();
  while (stepper1.distanceToGo() != 0) {
    stepper1.run();
    if ( distance != stepper1.distanceToGo() ) {
      distance = stepper1.distanceToGo();
      encoderBuff();
    }
  }
  Serial.println("buffer check begin");
  double oldDeg = deg;
  encoderBuff();
  //  dpr(deg);  dpr(oldDeg);
  while (oldDeg != deg)
  {
    oldDeg = deg;
    encoderBuff();
  }
  //  Serial.println(millis() - a); //check how much time it moved
  delay(1000);
  Serial.println("90 deg should be here");
  //  a = millis();
  stepper1.move(-positions[0]);
  while (stepper1.distanceToGo() != 0) {
    stepper1.run();
    if ( distance != stepper1.distanceToGo() ) {
      distance = stepper1.distanceToGo();
      encoderBuff();
    }
  }
  //  Serial.println(millis() - a); //check how much time it moved
  delay(1000);
  Serial.println("end");

  stepper1.move(positions[0]);
  //  long a = millis();
  while (stepper1.distanceToGo() != 0) {
    stepper1.run();
    if ( distance != stepper1.distanceToGo() ) {
      distance = stepper1.distanceToGo();
      encoderBuff();
    }
  }
  Serial.println("buffer check begin");
  oldDeg = deg;
  encoderBuff();
  //  dpr(deg);  dpr(oldDeg);
  while (oldDeg != deg)
  {
    oldDeg = deg;
    encoderBuff();
  }
  //  Serial.println(millis() - a); //check how much time it moved
  delay(1000);
  Serial.println("90 deg should be here");
  //  a = millis();
  stepper1.move(-positions[0]);
  while (stepper1.distanceToGo() != 0) {
    stepper1.run();
    if ( distance != stepper1.distanceToGo() ) {
      distance = stepper1.distanceToGo();
      encoderBuff();
    }
  }
  //  Serial.println(millis() - a); //check how much time it moved
  delay(1000);
  Serial.println("end");

  while (1);
}



void encoderBuff() //order the encoder to start another position reading right after finishing the current reading
{
  uint8_t recieved;    //just a temp vairable
  uint16_t ABSposition;

  // SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
  SPI.begin();
  recieved = SPIWrite(nop);    //issue NOP to check if encoder is ready to send

  if (recieved == rd_pos)    //check if encoder is ready to send
  {
    //Obtain the upper position byte. Mask it since we only need it's lower 4 bits, and then
    //shift it left 8 bits to make room for the lower byte.
    ABSposition = (SPIWrite(nop) & 0x0F) << 8;

    //OR the next byte with the current position
    ABSposition |= SPIWrite(rd_pos);

    deg = ABSposition * 0.08789;    // aprox 360/4096
    Serial.println(deg, DEC); //current position in decimal
  }
  else
  {
    recieved = SPIWrite(rd_pos);    //cleck again if encoder is still working

    while (recieved != rd_pos)    //sometimes works very slowly
    {
      recieved = SPIWrite(nop);    //cleck again if encoder is still working
    }

    //Obtain the upper position byte. Mask it since we only need it's lower 4 bits, and then
    //shift it left 8 bits to make room for the lower byte.
    ABSposition = (SPIWrite(nop) & 0x0F) << 8;

    //OR the next byte with the current position
    ABSposition |= SPIWrite(rd_pos);

    deg = ABSposition * 0.08789;    // aprox 360/4096
    Serial.println(deg, DEC); //current position in decimal
  }
  SPI.end();

}

void encoderWithoutBuff() //works almost the same as the previous examples in the thread, without the encoder to read position at the end of each reading (so it wouldnt buffer it)
{
  // SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
  SPI.begin();

  uint8_t data;               //this will hold our returned data from the AMT20
  uint16_t currentPosition;   //this 16 bit variable will hold our 12-bit position

  //send the rd_pos command to have the AMT20 begin obtaining the current position
  data = SPIWrite(rd_pos);

  //we need to send nop commands while the encoder processes the current position. We
  //will keep sending them until the AMT20 echos the rd_pos command, or our timeout is reached.
  //    while (data != rd_pos && timeoutCounter++ < timoutLimit)
  while (data != rd_pos)
  {
    data = SPIWrite(nop);
  }

  //We received the rd_pos echo which means the next two bytes are the current encoder position.
  //Since the AMT20 is a 12 bit encoder we will throw away the upper 4 bits by masking.

  //Obtain the upper position byte. Mask it since we only need it's lower 4 bits, and then
  //shift it left 8 bits to make room for the lower byte.
  currentPosition = (SPIWrite(nop) & 0x0F) << 8;

  //OR the next byte with the current position
  currentPosition |= SPIWrite(nop);

  deg = currentPosition * 0.08789; // aprox 360/4096
  Serial.println(deg, DEC); //current position in decimal

  SPI.end();

}


//We will use this function to handle transmitting SPI commands in order to keep our code clear and concise.
//It will return the byte received from SPI.transfer()
uint8_t SPIWrite(uint8_t sendByte)
{
  //holder for the received over SPI
  uint8_t data;

  //the AMT20 requires the release of the CS line after each byte
  digitalWrite(CS, LOW);
  data = SPI.transfer(sendByte);
  digitalWrite(CS, HIGH);

  //we will delay here to prevent the AMT20 from having to prioritize SPI over obtaining our position
  delayMicroseconds(21);

  return data;
}