[ SOLVED ] SPI reading of a sensor with uno

Hi
I am stuck and after 2 days of google and self struggle I am at a lost. Pretty sure i got the wiring, spi mode, MSBit and 10mHz settigs rite. When sending read "command' with adress with receiving data, it fails.
When I have the data in I can bit shift it to get desired data and work it into angular degress and carry on from there......but i am stuck at reading the data trough SPI.

Extract from programming manual
SPI Interface
The ...SPI interface...utilizing SPI mode 3.... two communication protocols. SPI
is selected when ISEL is brought to a logic high. This is easily accomplished by tying the ISEL pin directly to the BYP pin of the A1335, which provides a constant ≈2.8 V. .... maximize data throughput, up to fSCLK(max) of 10 MHz.

Extract from programming manual, this is where I am stuck.

Read Cycle Overview
Read cycles have two stages: a Read command, selecting a serial register address, followed by another Read command to transmit the data from the selected register. Both commands consist of a
1-bit sync (low), a 1-bit R/W asserted low, 6 address bits identifying the target register, and 8 data bits (all zeros because no data is
being written).

It goes on in folowing paragraph. pages 22,23 Link to manual

And my code attempt:

/* ******************************************************************************
 *  SPI read 3x A1335 rotation sensor chips with UNO and display on serial monitor 
 *  Slave select pins 10 >ss1, 9 >ss2, 8 >ss3
 */
#include <SPI.h>

  // set slave pins and variables
  const int ss1 = 10;
  const int ss2 = 9;
  const int ss3 = 8;
  uint16_t Ang_ss1 = 0;
  uint16_t Ang_ss2 = 0;
  uint16_t Ang_ss3 = 0;

/*SPI settings here and not declared globaly for attaching different
  spi devices with difrent settings. Call transaction,begin with new
  settings*/
    
SPISettings settingsA(10000000,MSBFIRST,SPI_MODE3);
 
  
void setup() {
   //set slave pins High and as outputs
  
  pinMode (ss1,OUTPUT);
  digitalWrite (ss1,HIGH);
  pinMode (ss2,OUTPUT);
  digitalWrite (ss2,HIGH);
  pinMode (ss3,OUTPUT);
  digitalWrite (ss3,HIGH);
  
  SPI.begin();           
  Serial.begin(9600);
  
}

void loop() {
  

SPI.beginTransaction(settingsA);

//select sensor 1 to 3 and read registers 0x20 and 0x21

digitalWrite (ss1,LOW);                // sensor one read and store two bite data in ANG_ss1
Ang_ss1 = SPI.transfer(0b00100000);    //read commnd "00" (00 & 0x20) adress register > did not work
Ang_ss1 = Ang_ss1 <<8;                //shift over MSB's
Ang_ss1 |= SPI.transfer(0);           //Fill lower bite
/*Ang_ss1 = SPI.transfer(0X20);       //read first bite, shift and read second bite
Ang_ss1 = Angle_ss1 <<8;
Ang_ss1 =Ang_ss1 &SPI.transfer(0x21); //> did not work*/
digitalWrite (ss1,HIGH);             //end read sensor one
/*digitalWrite (ss2,LOW);            //repeat read for sensor two
Ang_ss2 = SPI.transfer(0x20);
digitalWrite (ss2,HIGH);
digitalWrite (ss3,LOW);              // repeat for sensor three
Ang_ss3 = SPI.transfer16(0);
digitalWrite (ss3,HIGH);*/

SPI.endTransaction();

//De-bug code: display values from sensors
Serial.print(Ang_ss1);              //Serial.print(Ang_ss1,BIN);
Serial.print("ss1     ");
Serial.print(Ang_ss2,BIN);
Serial.print("ss2     ");
Serial.print(Ang_ss3,BIN);
Serial.println("ss3");

// convert received angle values to angular degrees
// might have to bit shift or mask 4 MSB angle register
Serial.print(Ang_ss1*(360/4096));
Serial.print(" DEG   ");
Serial.print(Ang_ss2*(360/4096));
Serial.print(" DEG   ");
Serial.print(Ang_ss3*(360/4096));
Serial.println(" DEG");
delay (1000);                       // to read serial monitor for debugging
}

Note: When I attached MSO 5102D 's logic analyzer the slave select goes low and about 2 clock cycles later it goes Hi.

Short Video of whats going on.

Update: used a smaller sec/dev: slave select is not the problem my code does not transfer data ? new analyzer video

Progress, it seems the uno does not have enough umph (5v) to run three sensors.
results are more promissing with just one. Here is a video and the code as it stands now. Still need help with it,please !!!

/* ******************************************************************************
 *  SPI read 3x A1335 rotation sensor chips with UNO and display on serial monitor 
 *  Slave select pins 10 >ss1, 9 >ss2, 8 >ss3
 */
#include <SPI.h>
//SPI.setMOSI(11)
//SPI.setMISO(12)
  // set slave pins and variables
  const int ss1 = 10;
  const int ss2 = 9;
  const int ss3 = 8;
  uint16_t Ang_ss1 = 0;
  uint16_t Ang_ss2 = 0;
  uint16_t Ang_ss3 = 0;

/*SPI settings here and not declared globaly for attaching different
  spi devices with difrent settings. Call transaction,begin with new
  settings*/
  SPISettings settingsA(10000000,MSBFIRST,SPI_MODE3); //moved into setup ,moved back 

  
void setup() {
 /* SPI.setClockDivider (SPI_CLOCK_DIV2); 
SPI.setDataMode (SPI_MODE3);
SPI.setBitOrder (MSBFIRST);*/
  
   //set slave pins High and as outputs
 
  pinMode (ss1,OUTPUT);
  digitalWrite (ss1,HIGH);
  pinMode (ss2,OUTPUT);
  digitalWrite (ss2,HIGH);
  pinMode (ss3,OUTPUT);
  digitalWrite (ss3,HIGH);

  //set up register once and receive data in loop
  Serial.begin(9600);
  SPI.begin();           
  SPI.beginTransaction(settingsA);
  digitalWrite (ss1,LOW);
  SPI.transfer(0x20);
  SPI.transfer(0);
  digitalWrite(ss1,HIGH);
  SPI.endTransaction();
  
}

void loop() {
  

SPI.beginTransaction(settingsA);

//select sensor 1 to 3 and read registers 0x20 and 0x21

digitalWrite (ss1,LOW);      // sensor one read and store two bite data in ANG_ss1
Ang_ss1 = SPI.transfer(0x20); //0x20 and 0x21 angle register
//Ang_ss1 = SPI.transfer(0); // receive data 0x20 high byte
Ang_ss1 = Ang_ss1 <<8;
Ang_ss1 |= SPI.transfer(0);//receive low byte
digitalWrite(ss1,HIGH);

SPI.endTransaction();

//De-bug code: display values from sensors
//Serial.print(Ang_ss1,BIN);              //Serial.print Ang_ss1 in binary
Serial.print(Ang_ss1);
Serial.println(" ss1     ");
Ang_ss1 = Ang_ss1 <<4;  //first 4 bytes are not part of angle
Ang_ss1 = Ang_ss1 >>4;
Serial.print(Ang_ss1);Serial.println(" ss1 shifted");
//Serial.print(Ang_ss1,BIN);Serial.println(" ss1 shifted"); // Ang_ss1 shifted in binary


Serial.print(Ang_ss1 * 360/4096 );  // formula from programming manual for sensor, removed '(' from (360/4096)
                                    // need help here the formula in manual is n*(360/4096)
Serial.println(" DEG   ");

delay (1000);                       // to read serial monitor for debugging

}

Assuming your wiring is correct for SPI communication between the A1335 and your Arduino, the code you posted does not seem quite right basing myself on the MikroElektronika_Angle_click. you can find its library here

If I was you, I would have coded something along those lines for SPI communication:

(code compiles but not tested!)

#include <SPI.h>

/* Error register status */
const uint8_t _ANGLE_ERROR_REG_MASK = 0x34;
const uint8_t _ANGLE_EXTENDED_ERROR_REG_MASK = 0x36;
const uint8_t _ANGLE_EXTENDED_ERROR_REG = 0x26;
const uint8_t _ANGLE_ERROR_REG = 0x24;
const uint8_t _ANGLE_STATUS_REG = 0x22;

const uint8_t _ANGLE_SETTINGS_REG = 0x1E;

/* Change Processor State */
const uint16_t _ANGLE_CDS_NO_CHANGLE = 0x0000 << 13;
const uint16_t _ANGLE_CDS_IDLE_MODE  = 0x0002 << 13;
const uint16_t _ANGLE_CDS_RUN_MODE   = 0x0003 << 13;

/* Hard reset */
const uint16_t _ANGLE_HDR_RESET_0   = 0x0000 << 12;
const uint16_t _ANGLE_HDR_RESET_1   = 0x0001 << 12;

/* Soft Reset */
const uint16_t _ANGLE_SFR_RESET_0   = 0x0000 << 11;
const uint16_t _ANGLE_SFR_RESET_1   = 0x0001 << 11;

/* Clear Status registar */
const uint16_t _ANGLE_CSR_STA_0   = 0x0000 << 9;
const uint16_t _ANGLE_CSR_STA_1   = 0x0001 << 9;

/* Clear Extended Error register*/
const uint16_t _ANGLE_CXE_0 = 0x0000 << 8;
const uint16_t _ANGLE_CXE_1 = 0x0001 << 8;

/* Clear Error register */
const uint16_t _ANGLE_CER_0 = 0x0000 << 7;
const uint16_t _ANGLE_CER_1 = 0x0001 << 7;

//SPI Slave Select pins
const uint8_t ss1 = 10, ss2 = 9, ss3 = 8;

void angle_setConfig(uint8_t ss, uint16_t setValue)
{
  digitalWrite(ss, LOW);
  SPI.transfer(0x1E);
  SPI.transfer((uint8_t)(setValue >> 8));
  SPI.transfer((uint8_t)(setValue & 0x00FF));
  digitalWrite(ss1, HIGH);
  delay(100);
}

uint16_t angle_getAngle(uint8_t ss)
{
  uint16_t AngleDeg = 0;
  uint16_t AngleVal = 0;

  digitalWrite(ss, LOW);
  SPI.transfer(0x20);
  delay(100);
  AngleVal = SPI.transfer(0x00);
  AngleVal = (AngleVal << 8) | SPI.transfer(0x00);
  digitalWrite(ss1, HIGH);

  AngleDeg = (uint16_t)( AngleVal * (360 / 4096.0));
  return AngleDeg;
}

void setup() {
  Serial.begin(115200);
  SPI.beginTransaction(SPISettings(10000000,MSBFIRST,SPI_MODE3));
  pinMode(ss1, OUTPUT);
  digitalWrite(ss1, HIGH);
  //pinMode(ss2,OUTPUT);
  //digitalWrite(ss2,HIGH);
  //pinMode(ss3,OUTPUT);
  //digitalWrite(ss3,HIGH);

  angle_setConfig(ss1, _ANGLE_CDS_NO_CHANGLE | _ANGLE_HDR_RESET_1 | _ANGLE_SFR_RESET_1 | _ANGLE_CSR_STA_1 | _ANGLE_CXE_1 | _ANGLE_CER_1);
  //angle_setConfig(ss2,_ANGLE_CDS_NO_CHANGLE | _ANGLE_HDR_RESET_1 | _ANGLE_SFR_RESET_1 | _ANGLE_CSR_STA_1 | _ANGLE_CXE_1 | _ANGLE_CER_1);
  //angle_setConfig(ss3,_ANGLE_CDS_NO_CHANGLE | _ANGLE_HDR_RESET_1 | _ANGLE_SFR_RESET_1 | _ANGLE_CSR_STA_1 | _ANGLE_CXE_1 | _ANGLE_CER_1);

}

void loop() {
  Serial.print("Angle1(deg): ");
  Serial.println(angle_getAngle(ss1));

  /*
    Serial.print(Angle2: );
    Serial.println(angle_getAngle(ss2));
    Serial.print(Angle3: );
    Serial.println(angle_getAngle(ss3));
  */

  delay(500); //arbitrary delay
}

if is does work, I would then try getting rid or reduce the 'delay(100);' with the aim making the code more responsive.

Hope that helps

Thanks sherzaad

I will have another look at angle -click code. Just seems they use a lot of the chips others features as well as getting the angle from it.

I can hardly understand how to get the angle, so incorporating everything else this chip offers is a lot to understand for me.

Hi all

Still no joy, Thanks sherzaad, tried your code and went through angle click again but cant get it to work.

Any help please

Could not post in original because I ran out of characters for message.

Success: The uno can only run 1x A1335 on SPI when second sensor connects it fails does all kind of weirdness. When I connect them through I2C one works a treat and when second connects it works buggy.

New Video on SPI.

new code: With one sensor............ :angry: just relised I did not save code for 2 sensors

/* ******************************************************************************
 *  SPI read 3x A1335 rotation sensor chips with UNO and display on serial monitor 
 *  Slave select pins 10 >ss1, 9 >ss2, 8 >ss3, UNO: SCL 13, Miso 12, mosi 11.
 *                                                  pink     yelo       orange
 **********************************************************************************/
#include <SPI.h>

  const int ss1 = 10; const int ss2 = 9; const int ss3 = 8;          //slave select pins
  uint16_t Ang_ss1 = 0;  uint16_t Ang_ss2 = 0; uint16_t Ang_ss3 = 0; //store 16bit register
  float Chip1; float Chip2; float Chip3;                             //after math valaue with commas( deg out of 360)

  SPISettings settingsA(10000000,MSBFIRST,SPI_MODE3);               //Spi settings

  
void setup() {
                                    
  pinMode (ss1,OUTPUT);                       //set slave pins High and as outputs
  digitalWrite (ss1,HIGH);
  pinMode (ss2,OUTPUT);
  digitalWrite (ss2,HIGH);
  pinMode (ss3,OUTPUT);
  digitalWrite (ss3,HIGH);

  Serial.begin(9600);
  SPI.begin();           

}

void loop() {
  

SPI.beginTransaction(settingsA);

//select sensor 1 and read 0x20 and 0x21 registers

digitalWrite (ss1,LOW);                          // sensor one read and store two bite data in ANG_ss1
Ang_ss1 = SPI.transfer(0x20);                              //0x20 and 0x21 angle register
Ang_ss1 = Ang_ss1 <<8;
Ang_ss1 |= SPI.transfer(0);                               //receive low byte 0x21
digitalWrite(ss1,HIGH);

SPI.endTransaction();

Ang_ss1 = Ang_ss1 <<4;                                    //first 4 bytes are not part of angle
Ang_ss1 = Ang_ss1 >>4;
Chip1 = (float) Ang_ss1 / 16;                             // change binary to desimal
Chip1 = (float)Ang_ss1 /4096.0 * 360.0;                  //  formula in manual is n*(360/4096)

Serial.print(Chip1);               
Serial.println(" DEG   ");

//delay (2000);                       // to read serial monitor for debugging

}