Using an ADS1232 with an Arduino UNO

(I’m new to external ADC’s and SPI in general, so please be patient)

I need an external ADC for a school project as the resolution of the internal ADC of the Arduino UNO/Nano/Mega is just too low. So I decided to buy one on Amazon which was already soldered (See attached picture). It arrived yesterday and I realized that I have no clue how to use it. After some googleing I found these posts:

http://forum.arduino.cc/index.php/topic,128823.0.html

I connected (based on the code I found) the following pins to my Arduino Uno:

Gain0/1 5V
REFP 5V
SPEED 5V
TEMP GND
A0 GND
CLKIN GND
DOUT D12
CLK D13
PDWN D9

The code:

#include <SPI.h>


#define MISOPIN 12

#define SCLKPIN 13

#define PDWN 9

#define A0 5



//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 data[3];
long val = 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);


 

 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


 data[0] = SPI.transfer(0x00);

 data[1] = SPI.transfer(0x00);

 data[2] = SPI.transfer(0x00);

 // read in adc data (sending out don't care bytes)

 // and store read data into three bytes */

if (data[2] & 0x80)
    val = 0xff;
val = (val << 8) | data[2];
val = (val << 8) | data[1];
val = (val << 8) | data[0];

 Serial.println(val);

 // 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

}

(based on: https://e2e.ti.com/support/data-converters/f/73/t/560004?Help-with-setting-up-an-ADS1234-with-4-load-cells-to-an-Arduino-Uno-or-a-Raspberry-Pi-3)

As said in the Datasheet, I can connect the AINN1 pin to ground to measure an unipolar signal on AINP1.
I’m not quite sure what a differential Signal is, so this was the best I can do.

I thought, if I connect AINN1 and AINP1 to Grund (or AINN1 - Gnd & AINP - 5V), I should get a constant number as result.
But thats not the case. I get random numbers starting at around -825242
and ending at ~1713729126.

Somebody knows why?

I think the chip is not a SPI device. It needs a clock pulse from Arduino and then it gives that data bit from data output. Data out also gives a sign when the chip is ready. You must read the databit after rising the clock input. Figure 34 in the datasheets tells that. You can find the datasheet from www.ti.com/lit/ds/symlink/ads1232.pdf

There are other ADCs which have Arduino code, could you not buy some of them?

Firstly:
Thanks for your fast response

Secondly:
I thought that SPI is exactly doing that: giving out a clock pulse and shifting in data.
But anyway:
Based on my understanding of ShiftIn() and the Datasheet of the ADC I wrote a Sketch on my own:

byte volatile Data[3];

int clockPin = 2;
int dataPin  = 3;
int PDWN     = 4;

void setup() {
attachInterrupt(digitalPinToInterrupt(3), read, FALLING);
Serial.begin(115200);

pinMode(clockPin, OUTPUT);
pinMode(PDWN, OUTPUT);
pinMode(dataPin, INPUT);

digitalWrite(clockPin, LOW);
digitalWrite(PDWN, LOW);
delay(50);
Serial.print("---Start---");
digitalWrite(PDWN, HIGH); //Activate the ADC

}

void loop() {

for(int x = 0; x < 3; x++){
  Serial.print(Data[x]);
  Serial.print(",");
}
Serial.println();

}


void read(){
  for(int x = 0;x < 3; x++){

Data[x]= shiftIn(dataPin,clockPin,MSBFIRST);


}
}

This gives the following Outputs:

(AINN1 is connected to ground)

AINP1 → Gnd: 255,255,255
AINP1 → 5V or 3,3V: 127,255,255

I’m pretty sure the the last two bytes aren’t correct (because they aren’t changing), but I don’t know why.

Thirdly:

I really wanted to buy a ADC that is better documented, but there are several reasons I bought that:

  1. Price: anything below 20 €/$
  2. Availability: I live in Germany so not everything is shipped here
  3. Usability: I needed a Board that I can use on the Breadboard
    And probably the most Important:
  4. Precision: I need a 24 Bit-ADC as I need to measure very small voltage changes.

This is the only chip I found which fulfills all these criteria.

Ebay has almost everything. But have you tried to search "delta sigma" from Arduino forums. I got some "hits" which may suit you.

I already knew about delta-sigma modulation (I didn't know the name though), but the problem is the conversion rate. I need 24-bit resolution without waiting more than 10 Minutes until I get a result. And I really want to buy something on Ebay. The problem is money: I'm a 17 year old student (-> bad English)), who gets his money mainly from helping out other students and his parents. I just can't spend 40 € (and thats the price for a 24-bit adc other than the one I have [could also be possible that you mean a different Ebay]) for a chip that I will use once (even then it is for my graduation).

Don't get me wrong, I don't want to be offensive. I'm just a bit nervous as I planned to use it for an experiment I wanted to do as part of my (already mentioned) high school graduation exam (found on G-Translator :wink: ) I wanted to test it, as it is far more illustrative, but I also have a backup plan, that I probably need to use.

Looking at the picture, I see only 5 wires connected. Please post a new photo with all wiring, in initial message there is only 9 pins indicated. What about +5 and +3, where it’s connected?

Edited.

I tested your code, till new pics aren’t ready yet. Also get like random data (SPI code from OP). Investigating an error, I came to conclusion that using SPI with this adc was a bad idea. It may work if “DATA Ready” feature is not effective, but in your case:

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);
}

you are testing DRDO for new data conversion completed, and according to data sheet on adc to make it work 25-clock need to be send to adc. Regular SPI works on 8-bit format, and get out 25-clock is practically impossible w/o pin manipulation. In that case I’d expect even more trouble.
So, here is working code for arduino UNO, that using direct port manipulation. Pin 8 & 9, clock and data.

/*
 **************************  ADS1232 + Arduino UNO   *************************
 * CopyLeft 
 * 2018 Anatoly Kuzmenko.
 * k_anatoly@hotmail.com
 *********************************************************************************************
 */

const    uint8_t      pin_SK1     = 0b00000001;     //PORT B-0, Digital 8
const    uint8_t      pin_DI1     = 0b00000010;     //PORT B-1, Digital 9


         String       in_String       =    "";        
         boolean      end_input       = false;  
         uint8_t      debug_osm       =     0;

unsigned long         previousMillis  =     0;     
const    long         interval        =  1000;     


void setup()
{
  Serial.begin(115200);
  in_String.reserve(200);

  init_ADS1232();
  kalibrovka();
}

void loop()
{
  int16_t  temp = 0;
  char *   pEnd;

  if(debug_osm) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      int32_t back = read_24b();
      Serial.print(F("\n\tread-back: "));
      Serial.print(back, DEC);
      }
    }
      
  serialEvent(); 

  if( end_input) {
    char cmd = in_String[0];
    in_String[0] = '+';
    
    if( cmd == 'd' ) {
      debug_osm = 1 - debug_osm;
      if(debug_osm) Serial.print(F("\nDebug aktiv."));
      else          Serial.print(F("\nDebug de-aktiv."));
      }
          
    if( cmd == 'i' ) {
      int32_t back = read_24b();
      Serial.print(F("\n\tread-back: "));
      Serial.print(back, DEC);
      }
    if( cmd == 'k' ) {
      int32_t back = read_24b();
      Serial.print(F("\n\tread-back do: "));
      Serial.print(back, DEC);
      kalibrovka();
      
      back = read_24b();
      Serial.print(F("\n\tread-back po: "));
      Serial.print(back, DEC);
      }

    if( cmd == 'l' ) {
      kalibrovka();
      }
                  
    in_String = "";
    end_input= false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    in_String += inChar;
    if (inChar == '\n') {
      end_input= true;
    }
  }
}


TAB-2
void kalibrovka(void)
{
  loop_until_bit_is_clear( PINB, 1);

  uint8_t count = 26;
  do {
    PORTB  |=   pin_SK1;                       
    PORTB  &= ~(pin_SK1);
  } while(--count); 
}


int32_t read_24b(void)
{
  uint32_t recv = 0;

  loop_until_bit_is_clear( PINB, 1);   // DI

  uint8_t count = 25;
  do {
    PORTB  |=   pin_SK1;                       
    recv <<= 1;          
    PORTB  &= ~(pin_SK1);
    if(PINB & pin_DI1) { recv++; }                       
  } while(--count); 

// Cast to 19-bits  
//  recv /=32;    
//  if ( recv & 0x00080000) recv += 0xFFF00000; // Convert to negative 19-bit word (2's comp)

  if ( recv & 0x01000000) recv += 0xFE000000; // Convert to negative 24-bit word (2's comp)

  return recv;
}

void init_ADS1232(void) 
{
// ADC - bit-bang
// Set OUPUTS pinmode
  DDRB   &= ~pin_DI1;    
  DDRB   |=  pin_SK1;    
  
  PORTB  &= ~pin_SK1;    // Set LOW                  
}

ads1232_uno_1d.zip (1.87 KB)

I decided to buy one on Amazon which was already soldered

That is not a good solder job. None of the pins on the left side look good. The bottom three pins on the right also look dubious, especially the GND. Those poor connections could be the problem.
Another problem is the jumper wires you are using. Looking at the jumper connected to SCLK, you can see that the metal pin is only about half the width of the breadboard hole. If you push on the wires I'm sure you'll find that the jumpers wiggle around which is also a poor connection.
You need to have the headers soldered to the board properly and use better jumper wires.

Pete

And again I want to say thanks to all replies and the constructive feedback I got. But it looks like I expressed myself wrong. I wanted a chip that is already soldered onto a PCB Board.

el_supremo:
That is not a good solder job. None of the pins on the left side look good. The bottom three pins on the right also look dubious, especially the GND. Those poor connections could be the problem.
Another problem is the jumper wires you are using. Looking at the jumper connected to SCLK, you can see that the metal pin is only about half the width of the breadboard hole. If you push on the wires I’m sure you’ll find that the jumpers wiggle around which is also a poor connection.
You need to have the headers soldered to the board properly and use better jumper wires.

Pete

The headers are soldered by me, so thanks for that…

But anyway I decided to resolder them as good as I can. In addition to that I rewired everything and checked the connections from header to header. Instead of using an UNO I now use a Nano, but thats not changing much. A photo of the result is attached.

FantomT:
you are testing DRDO for new data conversion completed, and according to data sheet on adc to make it work 25-clock need to be send to adc. Regular SPI works on 8-bit format, and get out 25-clock is practically impossible w/o pin manipulation. In that case I’d expect even more trouble.
So, here is working code for arduino UNO, that using direct port manipulation. Pin 8 & 9, clock and data.

I’m really thankful for your help and your code. There are just two problems:

  1. The code is somewhere way over my “normal” level, which makes it really difficult to understand and (because of that) really hard to manipulate, which leads to second problem:
  2. I tried to reproduce your result, but it looks like it isn’t coming any further than kalibrovka() in void setup() …

Yes, it would not. You need a serial monitor at 115200 bps, than send "i" to take 1 measurements, or "d" - to take measurements every second.
Is your arduino 5V device?

FantomT:
Yes, it would not. You need a serial monitor at 115200 bps, than send "i" to take 1 measurements, or "d" - to take measurements every second.

I know... That was the part I understood. The problem is, if I type in "i" or "d" (of course without quotation marks) nothing happens.
Because of that I set Serial.print("Test") on different positions to check what the code is doing and what not:

[...]
void setup()
{
  Serial.begin(115200);
  in_String.reserve(200);

  init_ADS1232();
  Serial.print("Test1");
  kalibrovka();
  Serial.print("Test2");
}
[...]

The serial monitor only shows "Test1", which is the reason I think the problem is there.

I just have seen (in your picture) that we don't have exactly the same chip, as yours has an external oscillator. I'm not sure if this is the reason.

FantomT:
Is your arduino 5V device?

Like the UNO the Nano runs 5V. In fact both are using the same chip: ATmega328P

markandre21062001:

  1. I know... That was the part I understood.

  2. The serial monitor only shows "Test1", which is the reason I think the problem is there.

  3. I just have seen (in your picture) that we don't have exactly the same chip, as yours has an external oscillator. I'm not sure if this is the reason.

  4. Like the UNO the Nano runs 5V. In fact both are using the same chip: ATmega328P

  1. Good.
  2. Right, it's hang up, there is "loop_until_bit_is_clear( PINB, 1);"
  3. I soldered crystal by myself, and your board is up side down, it's a good habit to show an IC to the user.
  4. If nano is 5V, than you should power up adc module from +5V, dispute it says +3V. See on my photo, both sides analog & interface powered from +5V lines. There is a reason, why TI divides analog power and logic power to separate pins, is to have ability to interface a module with 3.3 or 5V mCPU. Marking mistake is to module makers,

I just connected the 3.3V pin to 5V and it worked… partially. I now get something (using “d”), but only “read-back: 32767” and it isn’t changing. Typing in “k” to recalibrate it gives
“read-back do: 65535 read-back po: -1” or
“read-back do: 32767 read-back po: -1” back.

And here my brain starts to smoke:

int32_t read_24b(void)
{
  uint32_t recv = 0;

  loop_until_bit_is_clear( PINB, 1);   // DI

  uint8_t count = 25;
  do {
    PORTB  |=   pin_SK1;                       
    recv <<= 1;          
    PORTB  &= ~(pin_SK1);
    if(PINB & pin_DI1) { recv++; }                       
  } while(--count); 

// Cast to 19-bits  
//  recv /=32;    
//  if ( recv & 0x00080000) recv += 0xFFF00000; // Convert to negative 19-bit word (2's comp)

  if ( recv & 0x01000000) recv += 0xFE000000; // Convert to negative 24-bit word (2's comp)

  return recv;
}

What is connected to inputs?
My module has negative offset, if AINN1 & AINP1 to ground, something like -60000, than rotating pot clockwise I can get all numbers up to 16 777 216 at the middle of the pot scale. Setting AINN1 to 2.5V, and varying AINP1 from 0 to 5V provides from -16777xxx to +16777xxx

FantomT:
What is connected to inputs?
My module has negative offset, if AINN1 & AINP1 to ground, something like -60000, than rotating pot clockwise I can get all numbers up to 16 777 216 at the middle of the pot scale. Setting AINN1 to 2.5V, and varying AINP1 from 0 to 5V provides from -16777xxx to +16777xxx

markandre21062001:
I just connected the 3.3V pin to 5V and it worked... partially. I now get something (using "d"), but only "read-back: 32767" and it isn't changing.

The number isn't changing, uninteresting what I am doing: I already have connected AINN1 to Gnd. I tried connecting AINP1 to Gnd, 3,3V, 5V, all leading to the same result... 32767

Your photo shows GAIN0 &1 connected to +5, could you try to Gnd?

That doesn't change anything, as I just tested out

I’m afraid, the module is damaged by applying +5V to SCL pin same time as interface logic power was +3V.
Try to remove power for a few minutes, see if it’s make any difference.

The problem I currently have is time: As I mentioned before I wanted to use this project as part of my graduation exam. Here in Berlin are currently holidays, which allowed me to test this whole thing out. If the chip is broke, I can live with that... But getting a new will again take one month or so as the delivery times are very long.

But it looks like I need to wait this time, if what you are saying is right, as nothing has changed.

I buy one module ads1232 from aliexpress, about $3 CAD, before I get this "red" board. It was broken, as they say DOA, dead on arrival.
I also have a few NAU7802 in my stock, have got them from digikey.
https://www.digikey.ca/product-detail/en/nuvoton-technology-corporation-of-america/NAU7802KGI/NAU7802KGI-ND/2769783

It's in DIP package, so you don't need a board or solder some shitty TSSOP, 24-bits and very close to ads1232 in parameters, sampling rate etc. Don't know shipping and handling policy of the digikey in EU, but try. The point is, you can find 24-bits adc for less than 3 euro, it's shipping and handling what makes it expensive.
I think, arrow.com is offering free S/H for new customer, though they have cheap nau7802 in ssop, but you also can try to use their search engine, see if there is 24-bits in DIP for low price.
BTW, what is your project, is it 24-bits really necessary?

So firstly: I found that chip on arrow.com which sounds like the same (except it is SOP) like the one you’ve shown me(, which I think looks really promising btw.) But now I have two problems:

  1. (I really like enumerations) the additions to the name like SGI and KGI-ND at the end of the chips are really confusing, so I’m not really sure if they really are the same.
  2. It is SOC. I never had to handle SOC so I want to know if I am able to handle it without special instruments. The reason I want to buy form arrow.com and not from Digikey is the shipping price. Digikey wants 18 € for it (without any other options) and arrow gives it for free.

And secondly:

I’m not sure how much you know about the german school system, but I will try to summarize it:
After your mandatory 10 years of school you can do the so called “Abitur”. Based on where you live it is 2 or 3 years long. Here in Berlin it takes two years. The “Abitur” allows you to study by the way. So at the end of these 2/3 years you have to do an exam which will then be 1/3 of your diploma. This exam contains 5 exams in itself. 3 written, 1 verbal and 1 presentation exam. In my case these are: Biology, Chemics, English, Maths, and Psychology in this order. In the presentation exam (for me Psychology; also lovely called “5.PK”) you have to present a chosen topic for 20 minutes. This presentation must include a part which shows that you not just copied wikipedia. I want to do an experiment (My teachers are saying me thats way to much effort, but pffff…) based on this property. And to do that I need some kind of measuring device, so I thought I could use my knowledge to build such device an my own.

As already mentioned, some people are saying thats to much effort and they are probably right, but thats in my opinion the best way to demonstrate my topic. If you scroll a bit down in this PDF (Page 5) you can see in which scale this effect is measurable, which is also the reason I need such a high precision.

I am pretty sure that it wont work anyway for example because of interferences. But I really don’t want to fail on my own incompetence.

(After I wrote that I came to conclusion that I should refresh my English grammar skills before writing this English exam.)