SPI Communication to a AD2S1210 Eval Card with Arduino MKR Wifi1010

Hi.
Hope this is where this goes. I need help.

I am trying to interface a Arduino MKR Wifi1010 to a AD2S1210 Analog Devices Eval Card through SPI.

The AD2S1210 card is connected to an electric motor, and this card reads of the resolver on the motor (Cos, Sin, Exc). What I am looking for is the position of the motor. I know the card works, due to it reading fine over the parallel interface to another card that translates and communicates through USB to the computer to the Analog Devices Program.
I want that information to the arduino, over SPI, to HW align the motor with automation without having a pc connected.

I think i have the correct settings: SPISettings settingsA(2000000, MSBFIRST, SPI_MODE2);
(maby wrong speed)
Read it Here

Datasheet on the chip Here

Datasheets and schematic0s on the AD2S1210 Board here

I re-soldered 2 components on the original board.
LK2, from C pos to B pos, to set CS to low, as stated on page 28 of the datasheet "The CS input is not required for the serial interface and should be held low"
LK9, from A pos to B pos to set SOE low, as stated on page 28 of the datasheet " The serial interface is selected by holding the SOE pin low"

I also moved jumpers LK4 and LK5 to keep A0 and A1 to low (pos b), making it Normal mode, Position (page 20)

And jumpers on LK6 and LK7 (Res0 and Res1 (resolution, see page 20)) to Low, pos b. I have tried moving them around due to it stating it should also be set up in settings, but does not state default. (no difference in result no matter position)

I have connected (from AD2S1210 to Arduino MKR Wifi1010):
SDI to MOSI
SDO to MISO
SCLK to SCK
DGND to GND
SAMPLE to DI7

So i made 2 codes, first is a hack job from another forum post that was working on the same thing, tried editing it, due to I was using a different board (then the Analog devices one). Forum post Here

Code here:

const int AD2S1210_SAMPLE = 7;  // Toggle to refresh data
const int AD2S1210_SDO    = 10;  // Serial output from AD2S1210
const int AD2S1210_SDI    = 8;   // Serial Input of AD2S1210
const int AD2S1210_SCK    = 9;   // Serial clock output

#define SCLK_H digitalWrite(AD2S1210_SCK, HIGH)
#define SCLK_L digitalWrite(AD2S1210_SCK, LOW)
#define SDI_H digitalWrite(AD2S1210_SDI, HIGH)
#define SDI_L digitalWrite(AD2S1210_SDI, LOW)
#define SAMPLE_H digitalWrite(AD2S1210_SAMPLE, HIGH)
#define SAMPLE_L digitalWrite(AD2S1210_SAMPLE, LOW)
#define SDO digitalRead(AD2S1210_SDO)

void AD2S1210_WRITE(uint8_t addr,uint8_t data);
uint8_t AD2S1210_READ(uint8_t addr);
uint16_t READ_Position(void); //read position

uint16_t Position;
uint8_t reg[10];
uint8_t Fault;
uint8_t test;
uint16_t Dos_temp;

void setup() {
  Serial.begin(115200);
  
  pinMode(AD2S1210_SAMPLE, OUTPUT);
  pinMode(AD2S1210_SDO, INPUT_PULLUP);
  pinMode(AD2S1210_SDI, OUTPUT);
  pinMode(AD2S1210_SCK, OUTPUT);

  SAMPLE_L;
}

void loop() {
  Position=READ_Position();
  Serial.print("Position: "); 
  Serial.println(Position);

  delay(200);
    
}

uint16_t READ_Position(void)//read position
{
  uint16_t position;
  SAMPLE_H;
  SAMPLE_L;
  position=AD2S1210_READ(0x80);
  position<<=8;
  position|=AD2S1210_READ(0x81);
  return position;
}

uint8_t AD2S1210_READ(uint8_t addr)
{
  uint8_t temp;
  SCLK_L;
  temp=addr;
  int data=0;
  for(uint8_t s=0;s<8;s++)
  {
    SCLK_H;
    if(temp&0x80){SDI_H;}
    else{SDI_L;}
    SCLK_L;
    temp<<=1;
    if(SDO){data++;}
    if(s<7){data<<1;}
  }
  
  SCLK_H;
  delay(1);
  SCLK_L;
  
  temp=0;
  for(uint8_t s=0;s<8;s++)
  { 
    SCLK_H;
    SCLK_L;
    temp<<=1;
    if(SDO){temp++;}
  }
  
  SCLK_H;
  return temp;
}

This only gives 65535.

And then i made a code using the SPI.h lib.
With this code i get some data, but it is not correct. either 0, 32768, 49152, 65472 or 65535 when i rotate the axle, but not rising or falling according to rotation.

#include <SPI.h>
 
 const int AD2S1210_SAMPLE = 7;
 const int AD2S1210_SCK    = 9;   // Serial clock output
 
 uint16_t Position;
 
 #define SAMPLE_H digitalWrite(AD2S1210_SAMPLE, HIGH)
 #define SAMPLE_L digitalWrite(AD2S1210_SAMPLE, LOW)
 #define SCLK_H digitalWrite(AD2S1210_SCK, HIGH)
 #define SCLK_L digitalWrite(AD2S1210_SCK, LOW)
 
 SPISettings settingsA(2000000, MSBFIRST, SPI_MODE2);
 
 void setup() {
   pinMode (AD2S1210_SAMPLE, OUTPUT);
 
   SPI.begin();
 }
 
 void loop() {
 
   Position=READ_Position();
   
   Serial.print("Position: "); 
   Serial.println(Position);
 
   delay(200);
 }
 
 uint16_t READ_Position(void)//read position
 {
   uint16_t position;
   SAMPLE_H;
   SAMPLE_L;
   position=AD2S1210_READ(0x80);
   position<<=8;
   position|=AD2S1210_READ(0x81);
   return position;
 }
 
 uint8_t AD2S1210_READ(uint8_t addr)
 {
   SPI.beginTransaction(settingsA);
   uint8_t temp;
   SCLK_L;
   
   temp = SPI.transfer(addr); 
   
   SCLK_H;
   SPI.endTransaction();
   return temp;
 }

So I have no idea what I am doing wrong.
I have done other code for SPI before, but i just can not wrap my head around the datasheet and make sense of it.

I find no code or others that has done this, so I cant backward engineer something, like i use to do.

PS I am in no means a programmer, just way to interested in stuff with little to no knowledge of it. :stuck_out_tongue: I know mechanical, and basic electrical.

Hope someone can help me.

Try using SPI MODE0. I don't recall what the difference is (no time to look it up rn) but I looked at some code I have and I am using mode 0.

Funny thing is, my code I just checked takes in a 0-10V position signal and generates a resolver output from it :slight_smile:

Didn't I just reply to you on a different thread about another project?

Not that i know of.

But Thanks, i will try that and come back with the results.
(It was in my mind, but since the forum thread said Mode 2 i did not question it)

Hi Amish,

Did you manage to get it to work by changing the SPI mode?
I'm struggling as well!

Hi all,

for anyone still wondering, I managed to get my serial interface to work!

So, first, keep the CS low at all times and then use the following to initiate SPI communication:

  SPI.begin();
  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));

Following that, you can read from any register using this

uint8_t SPIRead(const byte Reg) {

  uint8_t res = 0;

  Serial.print(F("Reading resgiter 0x")); Serial.println(Reg, HEX);

  setMode(CONFIGURATION);

  digitalWrite(_WR, LOW);
  SPI.transfer(Reg);
  digitalWrite(_WR, HIGH);


  digitalWrite(_WR, LOW);
  res = SPI.transfer(0x00);
  digitalWrite(_WR, HIGH);

  setMode(NORMAL_VELOCTY);

  Serial.print(F("\t Bin val: 0B")); Serial.println(res, BIN);
  Serial.print(F("\t Hex val: 0X")); Serial.println(res, HEX);
  Serial.print(F("\t Dec val: "));   Serial.println(res);

  return res;

}

the setMode(CONFIGURATION); just sets A1 and A0 high, which is needed to read/write directly from a register using serial mode.

here is the Serial Port output I got after reading the control register and fault register after the initial startup:

(The error bit in the fault register is because I haven't actually connected the resolver yet)

I hope this helps people in future!

1 Like

Nice. Will have to look into it again soon.
It was put on hold, and we/I will most likely not be using this method of reading the resolver.
(My company makes our own cards to run the motor and read the resolver, but did not send the resolver data out on our own interface due to "safety" reasons, or some BS. But after discussing it with SW, they will make a new SW for my purposes so i do not need to use the AD Eval card)

But i will look into it and test more when i get time, since i love learning. :smiley:
I did get it to work but I had a bunch of errors while reading the bits and the first bits was always 1, making the number wierd. I did see increase and decrease in the number when rotating the resolver.

And i also think my settings where wrong on the resolution.

But thats for another time. :smiley:

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