[solved] receive 12-bit digital signal from amplifier using SPI

Hello there,
I have a CN-0350 ( https://www.analog.com/media/en/reference-design-documentation/reference-designs/CN0350.pdf) circuit that amplifies a signal I receive from an analog sensor. It outputs a 12-bit digital data through SPI. I am using the code below:

#include <SPI.h>
uint16_t spi_bytes;
void setup() {

Serial.begin(38400);
pinMode (13, OUTPUT);
pinMode (12, INPUT);
pinMode (11, OUTPUT);
pinMode (10, OUTPUT);
digitalWrite(SS,HIGH);
SPI.begin();
}

void loop() {
digitalWrite(SS, LOW);
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));
SPI.transfer(&spi_bytes, 2);
digitalWrite(SS, HIGH);
SPI.endTransaction();
Serial.println(spi_bytes,BIN);
}

The serial monitor only Shows 0. only one zero for each print command. Can you tell me what I got wrong?

Maybe the sensor is sending a zero. Have you configured the sensor correctly?

There is no useful information about an SPI connection in the data sheet you linked.

I suggest to follow the directions and try the manufacturer's software on a PC, as described in the linked data sheet.

Check with data sheets if you need to start the conversion (there is a conversion pin for the chip) and then try these codes.

#include<SPI.h>

void setup()
{
   Serial.begin(9600);
   SPI.begin();
   digitalWrite(SS, LOW);
}

void loop()
{
   byte x1 = SPI.transfer(0x00);
   Serial.print(x1, HEX);

   byte x2 = SPI.transfer(0x00);
   Serial.print(x2, HEX);

   byte x3 = SPI.transfer(0x00);
   Serial.print(x3, HEX);              //debug purpose
   digitalWrite(SS, HIGH);

   while(1);
}

HimaSama:
Hello there,
I have a CN-0350 ( https://www.analog.com/media/en/reference-design-documentation/reference-designs/CN0350.pdf) circuit that amplifies a signal I receive from an analog sensor. It outputs a 12-bit digital data through SPI. I am using the code below:

.....

The serial monitor only Shows 0. only one zero for each print command. Can you tell me what I got wrong?

the link you provided has little value for now since your current problem seems to be your CODE not your CIRCUIT.

so...

what ADC are you using? is it the AD7091 as in figure 1 in the CN-0350 document?

GolamMostafa I checked the data sheet, there is no conversion pin or conversition code. (there is a conversion pin in the ADC I believe, but not one of the 12 pins on the CN-0350 circuit). I did try the code, but it provided me with zeros, although the analog input to the ADC was 3.3 V.

sherzaad the ADC integrated in the CN-0350 circuit is AD7091R. Here is a link to the data sheet:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7091R.pdf

HimaSama:
... the ADC integrated in the CN-0350 circuit is AD7091R. Here is a link to the data sheet:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7091R.pdf

thank you for confirming the chip you are using...

BUT... did you even read the datasheet?!

you need to INITIATE the conversion!

so the code you shared in your original post would not work and probably the reason why you always got 0

IMHO your code should look something like this (compiles but untested)

#include<SPI.h>

#define CONVST 9
#define SS 10

void AD7091R_init_conv() {
  digitalWrite(CONVST, LOW);
  delayMicroseconds(1);
  digitalWrite(CONVST, HIGH);
}

void AD7091R_soft_reset() {

  AD7091R_init_conv();
  digitalWrite(SS, LOW);
  SPI.transfer(0x00);
  digitalWrite(SS, HIGH);

  delayMicroseconds(1);

  AD7091R_init_conv();

  delayMicroseconds(1);
}

void setup()
{
  Serial.begin(115200);
  SPI.begin();
  pinMode(CONVST, OUTPUT);
  digitalWrite(CONVST, HIGH);
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH);

  AD7091R_soft_reset();
}

void loop()
{
  AD7091R_init_conv();

  delayMicroseconds(1);

  digitalWrite(SS, LOW);

  uint16_t val = SPI.transfer(0x00); //receive bits 11-4

  byte x = SPI.transfer(0x00); //receive bits 3-0 (will be in bits 7-4 of x)

  digitalWrite(SS, HIGH);

  val = (val << 4) | (x >> 4); //combine the 12 bits read
  val &= 0x0FFF; //optional masking

  Serial.println(val); //this is the 12bit ADC value ie 0-4095

  delay(500); //arbitrary loop delay
}

hope that helps.

sherzaad:
uint16_t val = SPI.transfer(0x00); //receive bits 11-4

While the SPI.transfer(0x00) returns an 8-bit value, then should not it be declared as byte x = SPI.transfer(0x00); to avoid possible confusion with the following function which indeed returns 16-bit?

int value = SPI.transfer16(0x1234);

GolamMostafa:
While the SPI.transfer(0x00) returns an 8-bit value, then should not it be declared as byte x = SPI.transfer(0x00); to avoid possible confusion with the following function which indeed returns 16-bit?

int value = SPI.transfer16(0x1234);

There is no confusion because that function HAS A DIFFERENT NAME.
'value' has to be 16 bits so it doesn't lose data when shifted left by 4 bits:

 val = (val << 4) | (x >> 4); //combine the 12 bits read

Thank you guys! that was more than what I expected of help :slight_smile:

sherzaad special thanks for the code! I am sorry about initializing the conversion thing. It is my first time to use SPI and I had to google how to connect the 12 SPI pins, since the CN-0350 do not show the duty of each pin. unfortunately the website I learned the wiring from shows pin 9 as (unspecified). after reading your comments I found another website talking about how pin 9 in CN-0350 is used for conversion.

Johnwasser thank you for clearing the confusion!

Hi again,
My project developed a lot and Arduino IDE is not fitting my needs exactly now. So I tried to replicate the code in MATLAB. I am not sure if I can post my request here or not, but since I am still using an Arduino, I thought I might give it a shot. I attached the MATLAB code I made, I did not find a good support for the Arduino SPI communication in MATLAB. When I run the code it does not even get stuck in the while loop, and I am sure there are other things wrong with the code as well. Can you please help me gain?

clc;
clear;
   clear a;
   pause on
   a = arduino('COM3', 'Uno', 'Libraries', 'SPI');
   dev = device(a, 'SPIChipSelectPin', 'D10');
   voltage = [0];
   writeDigitalPin(a,'D9',1);
   writeDigitalPin(a,'D10',1);
   soft_reset()
   pause(1)
   go = true;
   while go
       initi_conv();
       pause(0.000001);
       writeDigitalPin(a,'D10',0);
       val = writeRead(dev,dataIn,'uint16');
       x = writeRead(dev,dataIn,'uint8');
       writeDigitalPin(a,'D10',1);
       val = bitshift(val,4) | bitsra(x,4);
       voltage = [voltage;val];
   end
   function initi_conv()
   
   writeDigitalPin(a,'D9',0);
   pause(0.000001);
   writeDigitalPin(a,'D9',1);
   end
   function soft_reset()
   
   writeDigitalPin(a,'D10',0);
   in = writeRead(dev,dataIn,'uint16')
   writeDigitalPin(a,'D10',1);
   pause(0.000001);
   initi_conv();
   pause(0.000001);
   end

Why are you using MATLAB? Write Arduino code that works, and you are done. But start by carefully reading the device data sheet.

Note: this code, from reply #5, won't work. The transition to initiate conversion is HIGH to LOW.

void AD7091R_init_conv() {
  digitalWrite(CONVST, LOW);
  delayMicroseconds(1);
  digitalWrite(CONVST, HIGH);
}

jremington:
Note: this code, from reply #5, won't work. The transition to initiate conversion is HIGH to LOW.

void AD7091R_init_conv() {

digitalWrite(CONVST, LOW);
  delayMicroseconds(1);
  digitalWrite(CONVST, HIGH);
}

if you look at the WHOLE code in reply#5, you would see that the inital state in 'setup' of CONVST pin is HIGH.

so the part of the code you highlighted should work IMHO.

HimaSama:
Hi again,
My project developed a lot and Arduino IDE is not fitting my needs exactly now. So I tried to replicate the code in MATLAB. I am not sure if I can post my request here or not, but since I am still using an Arduino, I thought I might give it a shot. I attached the MATLAB code I made, I did not find a good support for the Arduino SPI communication in MATLAB. When I run the code it does not even get stuck in the while loop, and I am sure there are other things wrong with the code as well. Can you please help me gain?

never used Matlab for Arduino except for the COM interface to get/send data to/from the arduino.

The arduino itself I programmed with the IDE (its light compared to MATLAB anyway! :wink: )

as suggested by @jremington that probably would be the simpler approach

If this is for a uni project or similar you can still show the code you used to program the arduino. unless you have been specifically tasked to ONLY use MATLAB of course! :slight_smile:

so the part of the code you highlighted should work IMHO.

Poor design to assume conditions set elsewhere in the code.