This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Help with setting up an ADS1234 with 4 load cells to an Arduino Uno or a Raspberry Pi 3

Other Parts Discussed in Thread: ADS1231, ADS1234

Hey guys,

I am a mechanical engineer being pressed into service as an electrical/computer/software engineer, so I am still learning a tremendous amount. Anyways, I am trying to create a system that uses four load cells. My goal is to connect these to a Raspberry Pi 3 and I am trying to use a 24bit 4 channel ADC to do it. I didn't know which ones to use so I ordered an ADS1234, 4 ADS1231's, and an MCP3304.

I have hooked up the ADS1234 with all four load cells and connected it to the SPI interface on an Arduino Uno (for testing). I am having some trouble getting it to work and I was hoping you  all could help. I followed Figure 42 in the ADS1234 datasheet, but to no avail. Also, this is the first time I am using SPI, so I really have no idea what I am doing.

I have attached the code that I am using in arudino as well as a schematic of how I have hooked them up. If you all could help me out I would greatly appreciate it!

Thanks!

PS: My VIN is 5V. Forgot to put that into the image.

 

#include <SPI.h>

#define MISOPIN 12
#define SCLKPIN 13

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

void setup()
{
 Serial.begin(9600);
 
 pinMode(SCLKPIN, OUTPUT); pinMode(MISOPIN, INPUT);
 // corresponding to SCK pin and DRDY/DOUT pin on ADC
 
 reset_adc();
 // put ADC on reset at the outset
 
 SPI.begin();
 // initialize SPI (with default settings, including...
 // CPOL = 0: so that SCLK is normally LOW
 // CPHA = 0: data sampled on rising edge (LOW to HIGH)
 // perhaps try changing CPHA ??
 
 digitalWrite(SCLKPIN, LOW);
 // release ADC from reset; now we're at a known point
 // in the timing diagram, and just have to wait for
 // the beginning of a conversion cycle
}

void loop()
{
 if (digitalRead(MISOPIN) == HIGH) read_adc();
 // "sort of" an interrupt to go to read_adc routine;
 // can use hardware interrupt in future but now just poll
}

void reset_adc()
// to reset ADC, we need SCLK HIGH for min of 4 CONVCYCLES
// so here, hold SCLK HIGH for 5 CONVCYCLEs = 1440 usec
{
 digitalWrite(SCLKPIN, HIGH);
 delayMicroseconds(1440);
}

void read_adc()
{
 drdy_wait();
 // go to drdy_wait routine, where we wait for
 // DRDY phase to pass, and thus for DOUT phase to begin

 byte1 = SPI.transfer(0x00);
 byte2 = SPI.transfer(0x00);
 byte3 = SPI.transfer(0x00);
 // read in adc data (sending out don't care bytes)
 // and store read data into three bytes */

 Serial.println(byte1, DEC);
 Serial.println(byte2, DEC);
 Serial.println(byte3, DEC);
 Serial.println();
 // print out data;
 // will these instructions eat into time significantly?
 // possible improvement: store all data from multiple cycles
 // into array, and print out only later at end.
}

void drdy_wait()
// wait for DRDY to pass and to reach start-point of DOUT
{
 delayMicroseconds(30);
 // to be safe, 30 usec, instead of 27 usec, which is
 // the expected period of DRDY phase
}
  • Hi Ross,

    Welcome to the forum!  My Dad always wanted me to be a mechanical engineer because he said 'they can do it all' and I guess you are proving him correct.  I broke his heart by becoming an electrical engineer.  I'm not sure if you actually built a PCB from your schematic or if you are using your schematic in a prototyping system.  Just a comment about your schematic is I don't see wire junctions at some of the intersections.  You want to make sure that all your wires connect as expected.

    One area of concern is the CLKIN pin.  The device requires a clock, and you can either provide one externally (from an oscillator or crystal) or use the internal clock by setting the CLKIN pin to GND.  I would suggest grounding this pin as currently it is floating.

    I also see that you have connected the SS from the Arduino to the PDWN pin.  You need to make sure this connection is not functioning as a SS pin for the SPI, but rather as a GPIO.  PDWN needs to be set high for the ADS1234 to function otherwise it is in a powered down state. 

    Regarding your code the SPI should be CPOL = 0 and CPHA = 1 as the data will change on the rising edge of SCLK and holds valid to read on the falling edge.

    Also, conversion is complete and ready to ready on the DOUT/DRDY pin when this pin signals completion by making a transition from high to low.

    Best regards,

    Bob B

  • Thanks for the response, but I am still not getting any results.. I added SPI.setDataMode(SPI_MODE1);, and I grounded the clock pin like you suggested.  I am now only get 255 255 255 repeatedly on the serial monitor, though. Also, I have all the pins connected to ground or VIN individually. I didn't use any wire junctions.

    #include <SPI.h>
    
    #define MISOPIN 12
    #define SCLKPIN 13
    #define PDWN 9
    
    byte byte1; byte byte2; byte byte3;
    // declare 3 bytes = 24 bits
    
    void setup()
    {
     Serial.begin(9600);
    
     
     pinMode(SCLKPIN, OUTPUT); pinMode(MISOPIN, INPUT); pinMode(PDWN, OUTPUT);
     // corresponding to SCK pin and DRDY/DOUT pin on ADC
    
    digitalWrite(PDWN, HIGH);
     reset_adc();
     // put ADC on reset at the outset
     
     SPI.begin();
     // initialize SPI (with default settings, including...
     // CPOL = 0: so that SCLK is normally LOW
     // CPHA = 1: data sampled on rising edge (LOW to HIGH)
     // perhaps try changing CPHA ??
    
     
     SPI.setDataMode(SPI_MODE1);
     
     digitalWrite(SCLKPIN, LOW);
     // release ADC from reset; now we're at a known point
     // in the timing diagram, and just have to wait for
     // the beginning of a conversion cycle
    }
    
    void loop()
    {
     if (digitalRead(MISOPIN) == HIGH) read_adc();
     // "sort of" an interrupt to go to read_adc routine;
     // can use hardware interrupt in future but now just poll
    }
    
    void reset_adc()
    // to reset ADC, we need SCLK HIGH for min of 4 CONVCYCLES
    // so here, hold SCLK HIGH for 5 CONVCYCLEs = 1440 usec
    {
     digitalWrite(SCLKPIN, HIGH);
     delay(1000);
    }
    
    void read_adc()
    {
     drdy_wait();
     // go to drdy_wait routine, where we wait for
     // DRDY phase to pass, and thus for DOUT phase to begin
    
     byte1 = SPI.transfer(0x00);
     byte2 = SPI.transfer(0x00);
     byte3 = SPI.transfer(0x00);
     // read in adc data (sending out don't care bytes)
     // and store read data into three bytes */
    
     Serial.println(byte1, DEC);
     Serial.println(byte2, DEC);
     Serial.println(byte3, DEC);
     Serial.println();
     // print out data;
     // will these instructions eat into time significantly?
     // possible improvement: store all data from multiple cycles
     // into array, and print out only later at end.
    }
    
    void drdy_wait()
    // wait for DRDY to pass and to reach start-point of DOUT
    {
     delay(1000);
     // to be safe, 30 usec, instead of 27 usec, which is
     // the expected period of DRDY phase
    }

    
    
  • Hi Ross,

    It sounds like you are using a prototyping system for your evaluation.  I would first verify all my connections.  Second, use an oscilloscope or logic analyzer to verify that DOUT/DRDY is toggling.  If it is not, then you need to find out why, such as PDWN is low and not high.

    If the device appears to be working correctly, then send me scope/logic analyzer shots of the communication.

    Best regards,

    Bob B

  • Hey Bob,

    Yes I am using a breadboard and an arduino uno right now for my evaluation. Good news is I have managed to get the ADC to output readings!  I don't really know what I did, but I got it working. I changed the speed to 80SPS, the voltage to 3.3V and Gain to 128. Also, I hooked up the A0 and A1 to PWM pins on the arduino.

    Although now I have encountered some new problems with the measurements. I have hooked up a load cell to AINP1 & AIN1, but the readings hover around 15 million with no weight and go up to 16.7 million or they hover around 16 million with no load, and go to 0-400,000 with load. I have tried changing the SPIModes and the MSB to LSB, but it is only changing the baseline value.

    Secondly, I can only get one sensor to work with only channel 1. That sensor displays readings on the other channels, and sensors plugged into the other channels don't have any readings.

    If you could help me out with these new problems I would greatly appreciate it.

    All the best,

    Ross

    #include <SPI.h>
    
    #define MISOPIN 12
    #define SCLKPIN 13
    #define PDWN 9
    #define A0 5
    #define A1 6
    
    //MUX Pin Settings
    //    A0    |    A1    |    Inputs
    // Low  (0) | Low  (0) | AINP1 11 AINN1 12
    // Low  (0) | High (1) | AINP2 18 AINN2 17
    // High (1) | Low  (0) | AINP3 13 AINN3 14
    // High (1) | High (1) | AINP4 16 AINN4 15
    
    
    uint32_t byte1; uint32_t byte2; uint32_t byte3; uint32_t finaladc = 0;
    // declare 3 bytes = 24 bits
    
    void setup()
    {
     Serial.begin(9600);
     
     pinMode(SCLKPIN, OUTPUT); pinMode(MISOPIN, INPUT); pinMode(PDWN, OUTPUT);
     // corresponding to SCK pin and DRDY/DOUT pin on ADC
    
     digitalWrite(PDWN, HIGH);
     digitalWrite(A0,LOW);
     digitalWrite(A1,LOW);
     
     reset_adc();
     // put ADC on reset at the outset
     
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE1);
     // initialize SPI (with default settings, including...
     // CPOL = 0: so that SCLK is normally LOW
     // CPHA = 0: data sampled on rising edge (LOW to HIGH)
     // perhaps try changing CPHA ??
     
     digitalWrite(SCLKPIN, LOW);
     // release ADC from reset; now we're at a known point
     // in the timing diagram, and just have to wait for
     // the beginning of a conversion cycle
    }
    
    void loop()
    {
     if (digitalRead(MISOPIN) == LOW) read_adc();
     // "sort of" an interrupt to go to read_adc routine;
     // can use hardware interrupt in future but now just poll
    
     delay(100);
    }
    
    void reset_adc()
    // to reset ADC, we need SCLK HIGH for min of 4 CONVCYCLES
    // so here, hold SCLK HIGH for 5 CONVCYCLEs = 1440 usec
    {
     digitalWrite(SCLKPIN, HIGH);
     delayMicroseconds(1440);
    }
    
    void read_adc()
    {
     drdy_wait();
     // go to drdy_wait routine, where we wait for
     // DRDY phase to pass, and thus for DOUT phase to begin
    
     byte1 = SPI.transfer(0x00);
     byte2 = SPI.transfer(0x00);
     byte3 = SPI.transfer(0x00);
     // read in adc data (sending out don't care bytes)
     // and store read data into three bytes */
    
     finaladc = (byte1 << 16) | (byte2 << 8) | byte3;
     //Serial.print("Binary Value:      "); Serial.println(finaladc,BIN); 
     //Serial.print("Hexadecimal Value: "); Serial.println(finaladc,HEX); 
     Serial.print("Decimal Value:     "); Serial.println(finaladc,DEC);
     Serial.println();
     // print out data;
     // will these instructions eat into time significantly?
     // possible improvement: store all data from multiple cycles
     // into array, and print out only later at end.
    }
    
    void drdy_wait()
    // wait for DRDY to pass and to reach start-point of DOUT
    {
     delayMicroseconds(30);
     // to be safe, 30 usec, instead of 27 usec, which is
     // the expected period of DRDY phase
    }

  • Hi Ross,

    I'm not sure what the channel error is you are seeing, but the data error is due to improper sign extension.  You are reading a signed 24-bit value into an unsigned integer.  The output of the ADS1234 is binary two's complement.  What you are perceiving as a large value is actually a small negative value.

    So you need to store your data as a signed value, and properly sign-extend the 24-bit value to 32-bit.

    Best regards,

    Bob B