ADC LTC2433-1 on Leonardo

Hey

I have made a bord with a ADC LTC2433-1 connected to 4 strain gauge
http://cds.linear.com/docs/en/datasheet/24331fa.pdf

I use the SPI bus conected to a Leonardo

The CS is tied low because it is a prototype.

I cant understand the output, but I think the layout works.

Output Data Format
The LTC2433-1 serial output data stream is 19 bits long.
The first 3 bits represent status information indicating the
conversion state and sign. The next 16 bits are the conver-
sion result, MSB first. The third and fourth bit together are
also used to indicate an underrange condition

Here is the program
#include "SPI.h"

byte byte1; byte byte2; byte byte3;
// declare 3 bytes = 24 bits

void setup(){
SPI.begin(); // wake up the SPI bus.
SPI.setBitOrder(MSBFIRST);
Serial.begin(19200);
}

void loop()
{
delay(3000);

byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);
byte3 = SPI.transfer(0);

Serial.println(byte1, BIN);
Serial.println(byte2, BIN);
Serial.println(byte3, BIN);
Serial.println();
}

And the output
There is no weigt on the strain gauge so i cant understand the output.

100000
10
111111

100000
0
1011111

11111
11110100
1111111

11111
11111101
111111

100000
0
11111111

How do I get the status bit separately, and the 16 bits are the conver-
sion result in one variable

I think der is a big timing problem, so I have tried to change
SPI.setDataMode and SPI.setClockDivider
but without result

The data sheet shows the first bit that is bit 18 always should be 0 I always get 1 first.

And I also do not understand why I do not always get 19 bit, and why I do not get the same result

spi1.png

I use the SPI bus conected to a Leonardo

Which pins exactly do you use?

And use code tags next time you post code!

Your value is constructed this way:

uint16_t v = byte1;
v <<= 11;
v |= ((uint16_t) byte2) << 3;
v |= byte3 >> 5;
int16_t value = (byte1 & 0x20) ? -v : v;

And I also do not understand why I do not always get 19 bit, and why I do not get the same result

You always got 19 bits, you even got 24 bits. Displaying a binary value is not the same as displaying bits!

On Leonardo dere is a dedicated spi bus.
I have conected:

Leonardo ADC LTC2433-1
ICSP-1 SDO
ICSP-3 SCK

#include "SPI.h"

byte byte1; byte byte2; byte byte3;
// declare 3 bytes = 24 bits

void setup(){
 SPI.begin(); // wake up the SPI bus.
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE3);
 Serial.begin(19200);     
}


void loop()
{
delay(2000);

byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);
byte3 = SPI.transfer(0);

uint16_t v = byte1;
v <<= 11;
v |= ((uint16_t) byte2) << 3;
v |= byte3 >> 5;
int16_t value = (byte1 & 0x20) ? -v : v;

Serial.println(value);
}

I can not understand my output, maybe there is a hardware failure.
Here, the output with no load

-29
-24
-49
-150
-5
-110
-3

And with 5 kg load

-27
-2
-54
-56
-19
-3
-26
-132

spi2.png

 SPI.setDataMode(SPI_MODE3);

According to the datasheet the LTC is using SPI mode 0 (rising edge, active high) and not 3.

Now I have changed SPI mode

SPI.setDataMode(SPI_MODE0);

It does not make much difference
Here, the output with no load

-21
-35
-29
-42
-63
-57
-74

And with 5 kg load

-22
-8
-37
-161
-26
-94
-58
-70

I just saw you connected CS to GND. That way the chip does not know when to do a conversion and when to start a transmission. Take a look at the timing diagram on page 13 of the datasheet. The CS pin is needed in my reading of the datasheet.

I think you're right, but on page 15 is shown with CS to GND.
Change it on the job at tomorrow

Yes, but then you must monitor the DSO line for the EOC (End Of Conversion) state and you don't do that. I would even turn off SPI after each transfer, set PB3 to GPIO input, pull CS low and wait until PB3 gets low. Then activate SPI and read the bytes. Maybe it's easier to do that without the hardware SPI and use just the shiftIn() functions.

Hello pylon

I've got chip select on, it did not change anything.
I have a big problem, there must be a hardware problem.
Hope I can get help on the job tomorrow, then I will return.

I've added setClockDivider because the LTC2433 can not run more than 4MHz, DIV32 gives 500KHz

SPI.setClockDivider(SPI_CLOCK_DIV32);

Here is the entire code

#include "SPI.h"

byte byte1; byte byte2; byte byte3;
// declare 3 bytes = 24 bits

//Setup the CS
int CSPin = 10;


void setup(){
  pinMode(CSPin, OUTPUT);
  digitalWrite(CSPin, HIGH);
 SPI.begin(); // wake up the SPI bus.
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE0);
 SPI.setClockDivider(SPI_CLOCK_DIV32); //32 = 500KHz  Må max være 2MHz
 Serial.begin(19200);     
}



void loop()
{
delay(2000);
digitalWrite(CSPin, LOW);
delay(1);

byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);
byte3 = SPI.transfer(0);
delay(1);
digitalWrite(CSPin, HIGH);

uint16_t v = byte1;
v <<= 11;
v |= ((uint16_t) byte2) << 3;
v |= byte3 >> 5;
int16_t value = (byte1 & 0x20) ? -v : v;

Serial.println(value);
}

I would implement the Test EOC condition (pull CS low and check the SDO line, start when SDO is low).

Yes but I have no ability to do that.

Why?

I'm not clever enough

Ah, you think you don't have the skills for it. So let's try if I can help a bit:

#include "SPI.h"

byte byte1; byte byte2; byte byte3;
// declare 3 bytes = 24 bits

//Setup the CS
byte CSPin = 10;
byte MISOPin = 12;

void setup() {
  pinMode(CSPin, OUTPUT);
  digitalWrite(CSPin, HIGH);
  Serial.begin(19200);     
}



void loop() {
  delay(2000);
  digitalWrite(CSPin, LOW);
  uint32_t startTime = millis();
  pinMode(MISOPin, INPUT);
  while (digitalRead(MISOPin) && millis() - startTime < 300); // wait for EOC (end of conversion)
  
  if (digitalRead(MISOPin)) {
    Serial.println("Error: EOC never reached");
  } else {
    SPI.begin(); // wake up the SPI bus.
    SPI.setClockDivider(SPI_CLOCK_DIV32); //32 = 500KHz  Må max være 2MHz
    byte1 = SPI.transfer(0);
    byte2 = SPI.transfer(0);
    byte3 = SPI.transfer(0);
    digitalWrite(CSPin, HIGH);
    SPI.end();

    uint16_t v = byte1;
    v <<= 11;
    v |= ((uint16_t) byte2) << 3;
    v |= byte3 >> 5;
    int16_t value = (byte1 & 0x20) ? -v : v;

    Serial.println(value);
  }
}

This waits for max. 300ms to reach the EOC state and returns an error if that state isn't detected in that time.

Yes you have been a great help.
I thought I could just connect the IC and so it worked. It did not :frowning:

Here is the output, it looks like the other times.
This means that there is a connection to the LTC2433?

-201
-22
-59
-22
-58
-75
-207
-96
-112
-80
-99

And a problem with the input to the LTC2433 ?

Perhaps I have found the error, there does not seem that there is a supplay for the 4 strain gauge.

If I put my fingers on the input I get the following

-20840
-18899
-11663
-13768

Now I've got it working :slight_smile:
There was no Vcc to the 4 strain gauge

0 kg is about -3295
5 kg is about -4477
Me on the top is about -18087
About 236 each kg

But why is the number negative ?

You must have many thanks for your help pylon.
It was never succeed without you.

But why is the number negative ?

Because the ADC can convert positive and negative voltages. You can change that either in the hardware or just remove the addition of the sign in the code, e.g. this line:

    int16_t value = (byte1 & 0x20) ? -v : v;

make this line looking like this:

    int16_t value = v;

and you have positive values.

Thank you once again, you've been a great help

I still have a problem
The result can not be greater than 32768

I have changed the code, but that has not solved the problem.
I think it has something to do with unsigned

void loop()
{
delay(2000);
digitalWrite(CSPin, LOW);
delay(1);

byte1 = SPI.transfer(0);
byte2 = SPI.transfer(0);
byte3 = SPI.transfer(0);
delay(1);
digitalWrite(CSPin, HIGH);

unsigned int v = byte1;
v <<= 11;
v |= ((unsigned int) byte2) << 3;
v |= byte3 >> 5;


//v = (v-1340)/59;

Serial.println(v);

}