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.

adc122s021 array with arduino uno

Other Parts Discussed in Thread: DAC7562, ADC122S021

My application

I designed a 32 regulated power supply, computer controlled. The PC interface is written in Java and provides all control needed. The system has 32 removable voltage regulators boards. Each voltage regulators have two voltage references (in the main board) to set the voltage output and the current limit. For each channel the output voltage and output current can be measured.

The system uses an Arduino Uno R3 to interface to the PC via USB and to the adc’s and dac’s in the system via SPI. The address decoding uses four devices HC154 (decoder 4 to 1-of 16) and an inverter. This part works.

The voltage references are issued by dac7562, one per each channel, operating in SPI mode 1. All dac channels operate and provide output voltage of 0-5V to the 1mV precision.

The output voltage and output current is measured using in each channel adc122s021cimm operating in SPI mode 3. There are 32 dac7562 and 32 adc122s021 on the same SPI bus.

Problem description

  1. The regulator output voltage is measured at the adc122s021 pin 5 which is named IN1 in the data sheet. To address this pin I had to use the configuration for IN2 (see tables 2, 3, 4 in page 17 in the data sheet). I solved this problem in the Arduino software but it seems there is a typo in the data sheet. Please check.

  2. The dacs work without problems. The problem is that some of the adcs work and some others not. I suspected there is an ESD issue and replaced some of the failing devices, only to get the same fail results. So I think something is working near some limit and for this I need your help. Following is some data:

Tfall(CS) to Tfall (CLK) = 1.55uS           start of conversion

Trise = Tfall = 25nS                   CLK

Trise(CLK) to Trise(CS) = 5.9uS            end of conversion

Fclock = 2MHz. Tests were performed also at 1MHz with the same results

Since SPI work in bytes I have to issue a reading twice to get all the 16bits. This produces a small interval between the requests = 5.9uS. During this time the clock remains at logic 1.

The following scope pics were issued with 1000mV dac output. The dac outputs were connected directly to the adc inputs to avoid problems related to the regulators. For this the code needed (5V reference) is 819dec = 333 hex. The adcs should output about the same value when reading the voltage. Following is a scope pic of a good channel.

Code = Vout/Vref * 4096 = 1V/5V * 4096 ≈ 819

 

The yellow trace is CS (chip select)

The green trace is the clock.

The blue trace is Data In (MOSI)

The red trace is Data Out (MISO)


Note the “1” in Data In as I presented in issue 1, above. The output code is 334hex = 820dec

Now is a bad channel

This channel shows an output code of 576dec = 240hex.

To read the data I look at the rising edges of the clock, also shown in the scope pics.

Some of the channels provide 0 value around 1.25V (Vref/4) and then from 1.3 - 1..5V the value is constant 1024dec = 400hex.

One of the devices has a similar behavior around 2.5V (Vref/2).


Following are the relevant schematics

The connection from the output of the dac to the input of the adc is in connector J1 (at the right) by shorting pins A4 (adc in) – A7 (dac out). The diodes and the resistors form a primitive ESD protection for the adc since the adc input (also the regulator output) is exposed to the external world.

To the right top is the address decoder, based on the HC154. One pair cover the dacs addressing and the other pair cover the adcs addressing. Two enable lines adcselb and dacselb enable the address decoder (and the corresponding device) after the address is set. The scheme was tested and works without any problem.

The inverters at the bottom was modified and is relevant to the dacs. They provided control to the CLR signal in the dac7562. The circuit was modified so there is no longer control and the dacs get a fixed “high” signal.

Following is the relevant code in the Arduino

This is the function that reads the adcs.

//--------------------------------------------------------------

int adcConvert(byte adChannel, byte address){   // 8 bit version

byte adDin;

               if(adChannel == 1)                                 //select adc channel

                    adDin = 0x08;                                      //convert command channel 1

  else

                if(adChannel == 2)

                adDin = 0x00;                                                //convert command channel 2  

  selectAddress(address);                                         //select adc address

               SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE3));

               digitalWrite(adcselb, LOW);                    //adc enable

               int adDataHigh = SPI.transfer(adDin);    // high byte data transfer

                int adDataLow = SPI.transfer(0);           // low byte data transfer

               digitalWrite(adcselb, HIGH);                    //adc disable

 SPI.endTransaction();

    int adData = (adDataHigh << 8) + adDataLow;    

  return adData;      

}

//-------------------------------------------------------------------------

At the starting of the function there is the addressing for IN1 or IN2 as reported above.

The function is called in a nested <for> loop which also prepares the data array to be send to the PC. The <for> loop is called once per second using the internal timer in the Arduino. This fills up the array adDataOut[192]. The data transmission also works.

// -----------------------------------------------

         byte index =0;

      for(address = 0; address < 32; address++){                // get data from all adc's        for(adChannel = 1; adChannel <= 2; adChannel++){        // data into three consecutive bytes

          adData = adcConvert(adChannel, address);           // adc call

                                                                                                               // adc chA = 1 - vout

                                                                                                               // adc chB = 2 - currentmon

            adDataOut[index] = (byte)(adData & 0x00FF);                 // adc low data 0x00 - 0xFF

              index += 1;

             

            adDataOut[index] = (byte)((adData & 0x0F00) >> 8);     // adc high data 0x00 - 0x0F

              index += 1;

            adDataOut[index] = (byte)(address + (adChannel << 6));

                  // composite address 0bcc0aaaaa

              index += 1;

          }

        }


// -----------------------------------------------------------------------------------------------------

 

Below is the window in the PC

  

Please look at channel 1. The voltage is set to 1 Volt (output settings). The reading in output readings is code, not voltage for debugging purposes. The value is 576 which is not good.

For channel 23 I get 820 which is a good value.

I hope you can help me. Thanks.

Mario Zajac

  • Hi Mario,

    It likes everything is being done correctly from your description. To try troubleshooting, if you read channel 1 multiple times in a row, do you get the same bad value? Also, please check the voltage directly at pin 5 of the ADC, just to make sure that the 1V is present there.

    Mike
  • Michael, thanks for your answer.
    I checked pin 5 to better than 1mV precision. The signal is also clean from glitches. My scope has 350MHz BW (Agilent MSO-X 3034A). When preparing my post I paid attention that the clock has a rise/fall time of 25nS, which seems too long. The rise/fall time of the ATMega328P- the processor in the Arduino uno- is specified at 3.6nS whith a small capacitive loading. The clock total capacitive loading in my project is about 150pF (all adcs + all dacs + board traces). I paid attention there is no spec in the ADC122S021 for rise/fall time of the clock. May be there are internal constrains (setup/hold/etc times) in the adc that limit the maximum rise/fall time of the clock?
    I am trying to insert a clock buffer consisting of four 74AHC244 buffers connected in parallel, just to charge that capacitance faster. A short simulation showed that the clock rise time is reduced to about 5nS.