Hi
I have a pretty strange problem with my AMT absolute encoder. For the most part it works great using the code I got from this forum. But for some reason the values jump every now and again. I have tried shaking the cable (1m) to see if that a loose connection or something causes it but it doesnt seem to have any correlation. It jumps randomly by up to 100 degrees in some cases (see image attached) .
I am not sure if anyone experienced anything similar.
My code is attached below. It uses an interrupt for the reading. I have also reduced the time to about 50ms interrupts which is the maximum I need for my application and it still jumps randomly. Could this be noise related ?
#include <SPI.h>
#define CS 10 //Chip or Slave select
uint16_t ABSposition = 0;
uint16_t ABSposition_last = 0;
uint8_t temp[2]; //This one.
uint8_t recieved = 0xA5; //just a temp vairable
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);
delay(2000);
SPI.end();
Serial.begin(115200);
Serial.println("starting");
Serial.flush();
read_encoder_position();
if ((deg < 358.0) && (deg > 2))
{ set_zero();}
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; //
OCR1A = 3125; // compare match register 16MHz/256/2Hz - 50ms
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
read_encoder_position();
Serial.println(deg); //send position in degrees
}
uint8_t SPI_T (uint8_t msg) //Repetive SPI transmit sequence
{
uint8_t msg_temp = 0; //variable 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()
{
// Serial.println("Loop Started");
delay(1000); //wait a bit till next check
}
void read_encoder_position()
{
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
// Serial.println("ChkPoint_1");
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
// Serial.println("ChkPoint_2");
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
//}
}
bool set_zero()
{
uint8_t lcl_received;
int lcl_count = 1024;
SPI.begin(); //start transmition
digitalWrite(CS,LOW);
SPI_T(0x70); //issue zero point command
do
{
lcl_received = SPI_T(0x00);
lcl_count= lcl_count-1;
}
while(lcl_count>1 && lcl_received != 0x80);
digitalWrite(CS,HIGH); //just to make sur
SPI.end(); //start transmition
if (lcl_count>1)
{
Serial.println("Zero Position Set!");
}
else
{
Serial.println("Zero Position Set Failed!");
}
}