TI中文支持网
TI专业的中文技术问题搜集分享网站

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

Part Number:ADS1256Other 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;

,

Amy Luo:

您好,

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

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

,

? ?:

先放我的原理图吧

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

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

是有共地的

信号线的细节是这样的

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

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

,

? ?:

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

,

Amy Luo:

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

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

,

? ?:

谢谢您的回复

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

谢谢

,

Amy Luo:

不客气~

嗯嗯好的,感谢您的反馈

赞(0)
未经允许不得转载:TI中文支持网 » ADS1256: 一个esp32采集三个ads1256数据的问题
分享到: 更多 (0)

© 2024 TI中文支持网   网站地图 鲁ICP备2022002796号-1