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.

ADS1255: How to simply code ADS1255 with Arduino

Part Number: ADS1255

Hello Texas Staff

Sorry to bother you.

I am the entry level electrical engineer. I met the problem of coding the ADS1255 and cannot find the solution.

My test circuit is following your datasheet Figure.25 but with arduino control.

My connection is AIN0 to Signal Generator BNC Red (1kHZ,5V SinWave) AIN1 to Signal Generator BNC Black.

SCLK to CS is connected to Arduino SPI and Control. RESET is connected to Arduino to reset the ADC. VREFP  is used DC power supply 2.5V 

All any others are same as Figure display.

My problem is how to code this ADS1255. I have one code which is uploaded in the file (Arduino IDE). Please check it.

I check the Arduino IDE output. I got Sinwaves but if I changed the Sinwaves to Triangle or other waveform, it always came out SinWaves 

And the amplitude of waveform is also not correct. I want to input Sinwaves and get the same waveform Sinwaves.

For coding problem----------

1) How to write register? is the following code is correct?

276 -SPI.transfer(0x50 | status_reg);
277 -SPI.transfer(0x00); // 2nd command byte, write one register only 

2) In code, each delay is correctADS1255 Arduino Code.docx or need to make adjustment?

3) how to convert the Hex code to my real measuring voltage

if(adc_val > 0x7fffff){
adc_val = (16777215ul - adc_val) + 1; //do 2's complement
}
Serial.println(adc_val*PGAmulti_1,10);

Thanks very much

  • Hi Yang,

    Welcome to the TI E2E Forums! To answer your questions...

    Yang Chang said:

    1) How to write register? is the following code is correct?

    276 -SPI.transfer(0x50 | status_reg);
    277 -SPI.transfer(0x00); // 2nd command byte, write one register only 

    That is correct. The next byte you send will be the register data to write (to the STATUS register in this example), just be sure to include the "t6" delay before sending the data byte. 

    Also, make sure that the device is in SDATAC mode (by sending the SDATAC command) before sending the WREG command. The ADS1255 should power-up into this mode; however, I would consider it a good practice to enforce this mode after power-up.

     

    Yang Chang said:
    2) In code, each delay is correct(Please visit the site to view this file) or need to make adjustment?

    I didn't see the "t6" delay after the WREG's second command byte. If your Arduino's SPI.transfer() function calls is slow enough you probably have sufficient delay time between these bytes. Again, it would still be good practice to include an intentional delay here.

    Also, after running a calibration, make sure you are delaying at least the time given by Table 13 in the ADS1255 datasheet.

     

    Yang Chang said:

    3) how to convert the Hex code to my real measuring voltage

    if(adc_val > 0x7fffff){
    adc_val = (16777215ul - adc_val) + 1; //do 2's complement
    }
    Serial.println(adc_val*PGAmulti_1,10);

    Take a look at this blog post:

    ...It looks like what you're doing could work though. Once you've gotten the 2's compliment conversion you just need to multiply the value by the ADC's LSB size, which is what you've done. A possible problem though is that "adc_val*PGAmulti_1" might be returning an integer value, and not the double precision number you're looking for. You might need to cast this operation into a double data type.

     

    Best Regards,
    Chris

  • Hi Yang,

    One more thought, regarding the "Serial.println(adc_val*PGAmulti_1,10);" statement...

    In many cases, you would need to convert the number to a string before you can print the value. A formatted print function might allow you to do this with a format specifier, for example: printf("Voltage = %d\r\n", (double) adc_val*PGAmulti_1);

    Best Regards,
    Chris
  • Hi Christopher

    I followed your advice. And I changed my code a little bit.

    For example: I added the delay 7 microseconds

    //----------- For part of setup 

    Serial.println("Status Data setup started");

     byte status_data = 0x01; //status: Most Significant Bit First, Auto-Calibration Disabled, Analog Input Buffer Disabled

     SPI.transfer(0x50 | status_reg);

     SPI.transfer(0x00);   // 2nd command byte, write one register only

     delayMicroseconds(7);                                             ---------------------- ------------------------------ADD t6 correct position?

     SPI.transfer(status_data);   // write the databyte to the register

     delayMicroseconds(10);                                            ------------------------------should I delay??

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

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

     // ADCON setup

     //byte adcon_data = 0x00; // 0 00 00 000

     Serial.println("ADCON Data setup started");

     SPI.transfer(0x50 | ADCON);

     SPI.transfer(0x00);   // 2nd command byte, write one register only

     delayMicroseconds(7);                                               ---------------------- ------------------------------ADD t6 correct position?

     SPI.transfer(PGA_1);   // write the databyte to the register

     Serial.println("ADCON Data setup ended");

     delayMicroseconds(10);                                             --------------------------------------------------------------should I delay??

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

    And for main loop:

    void AIN_0_COM()

    {

     long adc_val =0; // store reading

     digitalWrite(cs, LOW);

     SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI

     delayMicroseconds(10);

     while (digitalRead(rdy)) {} ;

     SPI.transfer(SDATAC);                                             ---------------------------------add SDATAC to make sure  in SDATAC model

                                                                                                     ------------------------------should I delay??

     //byte channel = 0;

     //byte data = (channel << 4) | (1 << 3); //AIN-channel and AINCOM

     //byte data = 1;

     SPI.transfer(0x50 | 1); // MUX register (0101 rrrr)

     SPI.transfer(0x00);   // 2nd command byte, write one register only

     //SPI.transfer(AIN0_COM);   // write the databyte to the register

     delayMicroseconds(7);//t6                                                ------------------------------ADD t6

     SPI.transfer(P_AIN0 + N_AINCOM);

     delayMicroseconds(10);                                                         ---------Should I delay here??

     //SYNC command 1111 1100

     SPI.transfer(SYNC);

     delayMicroseconds(10);                                                        ---------Should I delay here??/

     //WAKEUP 0000 0000

     SPI.transfer(WAKEUP);

     delayMicroseconds(34);                                                     --------------------add one shot delay here

     SPI.transfer(0x01); // Read Data 0000  0001 (01h)

     //delayMicroseconds(10);                                                       ---------Should I delay here??/

     adc_val = SPI.transfer(0);

     adc_val <<= 8; //shift to left

     adc_val |= SPI.transfer(0);

     adc_val <<= 8;

     adc_val |= SPI.transfer(0);

     while (digitalRead(rdy) == HIGH) {} ;                                 ADD to detect if Dready go high to finish one shot

     delayMicroseconds(3);//t 17                                                ADD T17 wait for one shot I used 7.86M

     digitalWrite(cs, HIGH);

     SPI.endTransaction();

     if(adc_val > 0x7fffff){ //if MSB == 1

       adc_val = (16777215ul - adc_val) + 1; //do 2's complement

     }

     //Serial.print("AIN0_COM: ");

     //String myString = String((double) adc_val*PGAmulti_1);

     //Serial.println (myString);

     Serial.println((double) adc_val*PGAmulti_1,5);                                          ADD DOUBLE

     //Serial.println(" Volt");

     //Serial.println(adc_val*PGAmulti_1*1000,2);

    }

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

    Could you check it if there need more adjustment?

    So I give you my output waveform. Sorry i don't have SPI simulation software. I give you the Serial Output. If it can help

    First Case:

    Same Circuit Schematic of Figure 25 in datasheet. AIN0 is 5V AIN1 is 0V DC...

    1st problem: I got  3.76953V for all time. How can I get 5V?

    2nd problem: I got 4.39453V for one time within 50 times of 3.76953. How to avoid this distort.

    Second Case:

    Same Circuit Schematic of Figure 25 in datasheet. AIN0 is BNC Red  AIN1 is BNC black  from Signal Generator of 1KHZ Sinwaves 5 amplitude. I got the waveform is

    I forgot my reference is 2.5V DC from power supply

    I very need your help.

    Thanks very much!

    Best Wish

  • Hi Christopher
    I mis-clicked /button 'Verify Answer'. I hope I don't make some mistakes.
  • Hi Yang,

    I would recommend reading back your register settings (with the RREG command) to make sure that the device settings are correct after programming the device....Doing that will help you verify the SPI communication.

    I think you have delays in the correct locations. In some cases, you many be delaying much longer than you need to be, but that shouldn't be a problem. 

    The biggest issue I see is that you appear to read data, then wait for /DRDY, here in the code:

    Yang Chang said:

     SPI.transfer(WAKEUP);

     delayMicroseconds(34);                                                     --------------------add one shot delay here

     SPI.transfer(0x01); // Read Data 0000  0001 (01h)

     //delayMicroseconds(10);                                                       ---------Should I delay here??/

     adc_val = SPI.transfer(0);

     adc_val <<= 8; //shift to left

     adc_val |= SPI.transfer(0);

     adc_val <<= 8;

     adc_val |= SPI.transfer(0);

     while (digitalRead(rdy) == HIGH) {} ;                                 ADD to detect if Dready go high to finish one shot

     delayMicroseconds(3);//t 17                                                ADD T17 wait for one shot I used 7.86M

     digitalWrite(cs, HIGH);

     SPI.endTransaction();

    You will want to make sure that you wait for /DRDY to go low and then read the data.

    I would suggest making sure that the SPI communication is working first, that way you know that you are getting the correct data conversion results from the ADC. From there, I would look at the ADC's raw data to see if it looks correct (don't try to covert to a voltage in software - at least not at first). The problem with trying to test everything all at once is that it becomes very difficult to know where the problem is occurring; however, by validating each step in order (the SPI communication, the raw data results, and then the voltage conversion math) it becomes much easier to debug and work out the problems one at a time.

    Best Regards,
    Chris

  • Yang Chang said:
    I mis-clicked /button 'Verify Answer'. I hope I don't make some mistakes.

    No problem, I was able to disregard the answer on that post.