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.

ADS1256: 一个esp32采集三个ads1256数据的问题

Part Number: ADS1256
Other Parts Discussed in Thread: ADS1255

我是用一个esp32采集三个ads1256数据,然后

硬件的连接方式是esp32的(六个引脚)sck、miso、mosi、drdy、reset、3.3同时连接到三个adc的对应引脚,然后用esp32的三个引脚作为片选,分别连接到ads1256的片选引脚,然后信号线上串联了一个100欧姆的牌组

程序上是分别三个adc初始化,然后依次读取三个adc的数据

现在遇到的问题是,读取到的数据噪音很大,然后每个adc的噪音水平还不一样,是什么原因呢?

有测过信号线的波形

这个miso是不是不太正常

还有如果想更换通讯方式的话,这个ads1256能直接接RS485总线吗,有没有相关的参考资料,求求啦,真的很需要帮助

  • 放一下现在用的程序,不会是程序出问题了吧

    首先是ads1256.h文件

    #ifndef _ADS1256_H_
    #define _ADS1256_H_

    #if defined(ARDUINO) && ARDUINO >= 100
        #include "arduino.h"
    #else
        #include "WProgram.h"
    #endif

    #include "SPI.h"
    #include "esp32-hal-gpio.h"

    class ADS1256
    {
    public:
        uint8_t pinCS;
        uint8_t pinRDY;
        uint8_t pinRESET;
        uint32_t speedSPI;

        double adcValues[8];
        double adcValues_init[8] = {0, 0, 0, 0, 0, 0, 0, 0};
        unsigned long adc_Raws[8] = {0, 0, 0, 0, 0, 0, 0, 0};
        byte mux[8] = {0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78};

        ADS1256();

        void init(uint8_t _pinCS, uint8_t _pinRDY, uint8_t _pinRESET, uint32_t _speedSPI);
        void init_value(int mean_num);
        void readInputToAdcValuesArray(int num);
        void readInputToAdcMeanValuesArray(int meanNum);
        // void readInputPEAKSToAdcValuesArray(int repeats);

    private:
    };

    #endif
    然后ads1256.cpp文件
    include "ADS1256.h"
    #include "esp32-hal-gpio.h"
    #include "SPI.h"

    ADS1256::ADS1256()
    {
    }

    void ADS1256::init(uint8_t _pinCS, uint8_t _pinRDY, uint8_t _pinRESET, uint32_t _speedSPI)
    {
        pinCS = _pinCS;
        pinRDY = _pinRDY;
        pinRESET = _pinRESET;
        speedSPI = _speedSPI;

        pinMode(pinCS, OUTPUT);
        digitalWrite(pinCS, LOW); // tied low is also OK.
        pinMode(pinRDY, INPUT);
        // pinMode(pinRDY, OUTPUT);
        pinMode(pinRESET, OUTPUT);

        digitalWrite(pinRESET, LOW);
        delay(1);                     // LOW at least 4 clock cycles of onboard clock. 100 microseconds is enough
        digitalWrite(pinRESET, HIGH); // now reset to default values

        delay(500);
        digitalWrite(pinCS, LOW);  
        delayMicroseconds(50);
        SPI.begin(); //start the spi-bus
        //
        delay(500);

        //init
        // SYNC 需要HIGH 否则初始化不成功
        while (digitalRead(pinRDY) != LOW)
        {
            Serial.println("ADC init not ready");

            vTaskDelay(500);
        }                                                                 // wait for ready_line to go low
        SPI.beginTransaction(SPISettings(speedSPI, MSBFIRST, SPI_MODE1)); // start SPI
        digitalWrite(pinCS, LOW);
        delayMicroseconds(100);

        //Reset to Power-Up Values (FEh)
        SPI.transfer(0xFE);
        delay(5);

        /******************************************************************************************************************
        STATUS : STATUS REGISTER (ADDRESS 00h)
        Reset Value = x1h
        BIT 7    BIT 6    BIT 5    BIT 4    BIT 3    BIT 2    BIT 1    BIT 0
        ID       ID       ID       ID       ORDER    ACAL     BUFEN    DRDY
        Bits 7-4 ID3, ID2, ID1, ID0 Factory Programmed Identification Bits (Read Only)
        Bit 3 ORDER: Data Output Bit Order
        0 = Most Significant Bit First (default)
        1 = Least Significant Bit First
        Input data is always shifted in most significant byte and bit first. Output data is always shifted out most significant
        byte first. The ORDER bit only controls the bit order of the output data within the byte.
        Bit 2 ACAL: Auto-Calibration
        0 = Auto-Calibration Disabled (default)
        1 = Auto-Calibration Enabled
        When Auto-Calibration is enabled, self-calibration begins at the completion of the WREG command that changes
        the PGA (bits 0-2 of ADCON register), DR (bits 7-0 in the DRATE register) or BUFEN (bit 1 in the STATUS register)
        values.
        Bit 1 BUFEN: Analog Input Buffer Enable
        0 = Buffer Disabled (default)
        1 = Buffer Enabled
        Bit 0 DRDY: Data Ready (Read Only)
        This bit duplicates the state of the DRDY pin.
        **************************************************************************************************************/
        byte status_reg = 0x00;  // address (datasheet p. 30)
        byte status_data = 0x05; // 01h = 0000 0 0 0 1 => status: Most Significant Bit First, Auto-Calibration Disabled, Analog Input Buffer Disabled
                                 //byte status_data = 0x07; // 01h = 0000 0 1 1 1 => status: Most Significant Bit First, Auto-Calibration Enabled, Analog Input Buffer Enabled
        SPI.transfer(0x50 | status_reg);
        SPI.transfer(0x00);        // 2nd command byte, write one register only
        SPI.transfer(status_data); // write the databyte to the register
        delayMicroseconds(100);

        /***************************************************************************************************************
        ADCON: A/D Control Register (Address 02h)
        Reset Value = 20h
        BIT 7   BIT 6   BIT 5   BIT 4   BIT 3   BIT 2   BIT 1   BIT 0
        0       CLK1    CLK0    SDCS1   SDCS0   PGA2    PGA1    PGA0
        Bit 7 Reserved, always 0 (Read Only)
        Bits 6-5 CLK1, CLK0: D0/CLKOUT Clock Out Rate Setting
        00 = Clock Out OFF
        01 = Clock Out Frequency = fCLKIN (default)
        10 = Clock Out Frequency = fCLKIN/2
        11 = Clock Out Frequency = fCLKIN/4
        When not using CLKOUT, it is recommended that it be turned off. These bits can only be reset using the RESET pin.
        Bits 4-2 SDCS1, SCDS0: Sensor Detect Current Sources
        00 = Sensor Detect OFF (default)
        01 = Sensor Detect Current = 0.5μA
        10 = Sensor Detect Current = 2μA
        11 = Sensor Detect Current = 10μA
        The Sensor Detect Current Sources can be activated to verify the integrity of an external sensor supplying a signal to the
        ADS1255/6. A shorted sensor produces a very small signal while an open-circuit sensor produces a very large signal.
        Bits 2-0 PGA2, PGA1, PGA0: Programmable Gain Amplifier Setting
        PGA SETTING
        00h = 000 = 1   ±5V(default)
        01h = 001 = 2   ±2.5V
        02h = 010 = 4   ±1.25V
        03h = 011 = 8   ±0.625V
        04h = 100 = 16  ±312.5mV
        05h = 101 = 32  ±156.25mV
        06h = 110 = 64  ±78.125mV
        07h = 111 = 64  ±78.125mV
        **********************************************************************************************************************/
        byte adcon_reg = 0x02;          //A/D Control Register (Address 02h)
                                        //byte adcon_data = 0x20; // 0 01 00 000 => Clock Out Frequency = fCLKIN, Sensor Detect OFF, gain 1
        byte adcon_data = 0x00;         // 0 00 00 000 => Clock Out = Off, Sensor Detect OFF, gain 1
                                        //byte adcon_data = 0x01;   // 0 00 00 001 => Clock Out = Off, Sensor Detect OFF, gain 2
        SPI.transfer(0x50 | adcon_reg); // 52h = 0101 0010
        SPI.transfer(0x00);             // 2nd command byte, write one register only
        SPI.transfer(adcon_data);       // write the databyte to the register
        delayMicroseconds(100);
        /*********************************************************************************************************
        DRATE: A/D Data Rate (Address 03h)
        Reset Value = F0h
        BIT 7    BIT 6    BIT 5    BIT 4    BIT 3    BIT 2    BIT 1    BIT 0
        DR7     DR6       DR5      DR4      DR3      DR2      DR1      DR0
        The 16 valid Data Rate settings are shown below. Make sure to select a valid setting as the invalid settings may produce
        unpredictable results.
        Bits 7-0 DR[7: 0]: Data Rate Setting(1)
        F0h = 11110000 = 30,000SPS (default)
        E0h = 11100000 = 15,000SPS
        D0h = 11010000 = 7,500SPS
        C0h = 11000000 = 3,750SPS
        B0h = 10110000 = 2,000SPS
        A1h = 10100001 = 1,000SPS
        92h = 10010010 = 500SPS
        82h = 10000010 = 100SPS
        72h = 01110010 = 60SPS
        63h = 01100011 = 50SPS
        53h = 01010011 = 30SPS
        43h = 01000011 = 25SPS
        33h = 00110011 = 15SPS
        23h = 00100011 = 10SPS
        13h = 00010011 = 5SPS
        03h = 00000011 = 2.5SPS
        (1) for fCLKIN = 7.68MHz. Data rates scale linearly with fCLKIN.
        ***********************************************************************************************/
        byte drate_reg = 0x03;  //DRATE: A/D Data Rate (Address 03h)
        // byte drate_data = 0xF0; // F0h = 11110000 = 30,000
        byte drate_data = 0xA1;  // 1000SPS
        SPI.transfer(0x50 | drate_reg);
        SPI.transfer(0x00);       // 2nd command byte, write one register only
        SPI.transfer(drate_data); // write the databyte to the register
        delayMicroseconds(100);

        // Perform Offset and Gain Self-Calibration (F0h)
        SPI.transfer(0xF0);
        delay(400);
        digitalWrite(pinCS, HIGH);
        SPI.endTransaction();
    }

    void ADS1256::readInputToAdcValuesArray(int cs)
    {
        //Single ended Measurements
        //unsigned long adc_Raws[ 8 ] = { 0,0,0,0,0,0,0,0 }; // store readings in array
        //byte mux[ 8 ] ={ 0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78 };

        int i = 0;
        int pincs=cs;
        SPI.beginTransaction(SPISettings(speedSPI, MSBFIRST, SPI_MODE1)); // start SPI
        digitalWrite(pincs, LOW);
        delayMicroseconds(2);

        /***************************************************************************
        Settling Time Using the Input Multiplexer
        The most efficient way to cycle through the inputs is to
        change the multiplexer setting (using a WREG command
        to the multiplexer register MUX) immediately after DRDY
        goes low. Then, after changing the multiplexer, restart the
        conversion process by issuing the SYNC and WAKEUP
        commands, and retrieve the data with the RDATA
        command. Changing the multiplexer before reading the
        data allows the ADS1256 to start measuring the new input
        channel sooner. Figure 19 demonstrates efficient input
        cycling. There is no need to ignore or discard data while
        cycling through the channels of the input multiplexer
        because the ADS1256 fully settles before DRDY goes low,
        indicating data is ready.
        Step 1: When DRDY goes low, indicating that data is ready for retrieval,
        update the multiplexer register MUX using the WREG command. For example,
        setting MUX to 23h gives AINP = AIN2, AINN = AIN3.
        Step 2: Restart the conversion process by issuing a SYNC command
        immediately followed by a WAKEUP command.
        Make sure to follow timing specification t11 between commands.
        Step 3: Read the data from the previous conversion using the RDATA command.
        Step 4: When DRDY goes low again, repeat the cycle by first
        updating the multiplexer register, then reading the previous data.
        ***************************************************************************************/
        for (i = 0; i < 8; i++)
        {                          // read all 8 Single Ended Channels AINx-AINCOM
            byte channel = mux[i]; // analog in channels #

            while (digitalRead(pinRDY) != LOW)
            {
                // Serial.println("ready not ready");
            }

            /*
            WREG: Write to Register
            Description: Write to the registers starting with the register specified as part of the command. The number of registers that
            will be written is one plus the value of the second byte in the command.
            1st Command Byte: 0101 rrrr where rrrr is the address to the first register to be written.
            2nd Command Byte: 0000 nnnn where nnnn is the number of bytes to be written – 1.
            Data Byte(s): data to be written to the registers.
            */
            //byte data = (channel << 4) | (1 << 3); //AIN-channel and AINCOM   // ********** Step 1 **********
            //byte data = (channel << 4) | (1 << 1)| (1); //AIN-channel and AINCOM   // ********** Step 1 **********
            //Serial.println(channel,HEX);
            SPI.transfer(0x50 | 0x01); // 1st Command Byte: 0101 0001  0001 = MUX register address 01h
            SPI.transfer(0x00);        // 2nd Command Byte: 0000 0000  1-1=0 write one byte only
            SPI.transfer(channel);     // Data Byte(s): xxxx 1000  write the databyte to the register(s)
            delayMicroseconds(2);

            //SYNC command 1111 1100                               // ********** Step 2 **********
            SPI.transfer(0xFC);
            delayMicroseconds(2);

            //while (!digitalRead(rdy)) {} ;
            //WAKEUP 0000 0000
            SPI.transfer(0x00);
            delayMicroseconds(250); // Allow settling time

            /*
            MUX : Input Multiplexer Control Register (Address 01h)
            Reset Value = 01h
            BIT 7    BIT 6    BIT 5    BIT 4    BIT 3    BIT 2    BIT 1    BIT 0
            PSEL3    PSEL2    PSEL1    PSEL0    NSEL3    NSEL2    NSEL1    NSEL0
            Bits 7-4 PSEL3, PSEL2, PSEL1, PSEL0: Positive Input Channel (AINP) Select
            0000 = AIN0 (default)
            0001 = AIN1
            0010 = AIN2 (ADS1256 only)
            0011 = AIN3 (ADS1256 only)
            0100 = AIN4 (ADS1256 only)
            0101 = AIN5 (ADS1256 only)
            0110 = AIN6 (ADS1256 only)
            0111 = AIN7 (ADS1256 only)
            1xxx = AINCOM (when PSEL3 = 1, PSEL2, PSEL1, PSEL0 are "don’t care")
            NOTE: When using an ADS1255 make sure to only select the available inputs.
            Bits 3-0 NSEL3, NSEL2, NSEL1, NSEL0: Negative Input Channel (AINN) Select
            0000 = AIN0
            0001 = AIN1 (default)
            0010 = AIN2 (ADS1256 only)
            0011 = AIN3 (ADS1256 only)
            0100 = AIN4 (ADS1256 only)
            0101 = AIN5 (ADS1256 only)
            0110 = AIN6 (ADS1256 only)
            0111 = AIN7 (ADS1256 only)
            1xxx = AINCOM (when NSEL3 = 1, NSEL2, NSEL1, NSEL0 are “don’t care”)
            NOTE: When using an ADS1255 make sure to only select the available inputs.
            */

            SPI.transfer(0x01); // Read Data 0000  0001 (01h)       // ********** Step 3 **********
            delayMicroseconds(5);
            // get a 3byte conversion result from the adc
            adc_Raws[i] = SPI.transfer(0);
            adc_Raws[i] <<= 8; //shift to left
            adc_Raws[i] |= SPI.transfer(0);
            adc_Raws[i] <<= 8;
            adc_Raws[i] |= SPI.transfer(0);
            delayMicroseconds(2);
        } // end of for Repeat for each channel ********** Step 4 **********

        digitalWrite(pincs, HIGH);
        SPI.endTransaction();

        //The ADS1255/6 output 24 bits of data in Binary Two's
        //Complement format. The LSB has a weight of
        //2VREF/(PGA(223 − 1)).
        // A positive full-scale input produces an output code of 7FFFFFh
        // and the negative full-scale input produces an output code of 800000h.
        //
        for (i = 0; i <= 7; i++)
        { // Single ended Measurements
            if (adc_Raws[i] > 0x7fffff)
            {                                         //if MSB == 1
                adc_Raws[i] = adc_Raws[i] - 0x1000000; //do 2's complement  做2的补码
               
            }
            adcValues[i] = (double) adc_Raws[i] / 4194304.0 * 2.5;
        }
    } // end of readInputToAdcValuesArray()

    void ADS1256::readInputToAdcMeanValuesArray(int meanNum=20) {
        double meanValues[8] = {0};
        for (int i = 0; i < meanNum; i++) {
            readInputToAdcValuesArray(10);
            for (int j = 0; j < 8; j++) {
                meanValues[j] += adcValues[j];
            }
        }
        for (int j = 0; j < 8; j++) {
            adcValues[j] = meanValues[j] / meanNum;
        }
    }

    /*
    * 得到静止电压
    */
    void ADS1256::init_value(int mean_num=50) {
        for (int i = 0; i < 8; i++) {
            adcValues_init[i] = 0;
        }
        readInputToAdcMeanValuesArray(mean_num);

        for (int j = 0; j < 8; j++) {
            adcValues_init[j] = adcValues[j];
        }
       
    }
    然后各引脚的使用
    #define ADS_CS 10  //10
    #define ADS_CS1 18 //第二个adc的片选用18
    #define ADS_CS2 16//第三个adc的片选用16
    #define ADS_RDY 8  //8
    #define ADS_RESET 3//3

    #define ADS_SPEED_SPI 1700000
    ADS1256 ads;
    初始化中有关adc的部分
        ads.init(ADS_CS, ADS_RDY, ADS_RESET, ADS_SPEED_SPI);
        delay(1000);
        ads.init(ADS_CS1, ADS_RDY, ADS_RESET, ADS_SPEED_SPI);
        delay(1000);
        ads.init(ADS_CS2, ADS_RDY, ADS_RESET, ADS_SPEED_SPI);
    读取adc的程序,这段程序20ms执行一次
     ads.readInputToAdcValuesArray(ADS_CS);

        //ads.readInputToAdcValuesArray(ADS_CS);
        String log = createLog(ads.adcValues);
        ads.readInputToAdcValuesArray(ADS_CS1);


        //ads.readInputToAdcValuesArray(ADS_CS1);
        String log1=createLog(ads.adcValues);
        ads.readInputToAdcValuesArray(ADS_CS2);

        //ads.readInputToAdcValuesArray(ADS_CS2);
        String log2=createLog(ads.adcValues);
        //log= "A," + log+"E\r\n";
       
        log = "A" + get_local_time() + "," + log+","+ log1+","+log2+"E\r\n";
        long_log += log;
  • 您好,

    esp32的地是否与ads1256的地共地?

    看信号波形应该是通信波形质量的问题。sck、miso、mosi是不是走线较近?看波形时钟好像受mosi信号的影响,miso、mosi看不出来是谁影响了谁,您可以附上这几个数字信号线的PCB layout吗?

  • 先放我的原理图吧

    然后板子的实际焊完的结果

    adc与旁边的板子分开的,通过排阻焊到一起

    是有共地的

    信号线的细节是这样的

    13 12 11 10,分别是我接的第一个adc的miso sck mosi 和片选

    有点疑惑,我的应该算板间连接吧,信号线的长度应该不超过20cm

  • 对了,信号线的走线再放大一些吧

  • 我没有看出信号线的完整走线,但是看下面截图处,这三个过孔处(应该分别对应miso sck mosi )就没有被地隔离,即最上面的过孔与中间的过孔间没有隔离,中间过孔与右边的过孔间也没有被地隔离,它们间的距离设置的是多少,有0.2mm吗?因为ADC PCB封装管脚定义距离是0.2mm。

    看信号波形应该是信号质量的问题,信号质量不好,设备就不能正确识别高低电平,造成通信错误。H1和H2上是接主控端的是吗?不知道主控板上SPI走线是怎样的?您可以从主控端飞线SPI接口至ADC SPI接口吗?以排除板子上走线太近串扰问题。飞线时尽量短。

  • 谢谢您的回复

    我在画板子时,确实不太规范,不过,我打算更改方案了

    谢谢

  • 不客气~

    嗯嗯好的,感谢您的反馈