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.

[参考译文] ADS1299:nRF52832电路板上的 SPI 通信和数据不稳定性问题(异常值)疑难解答

Guru**** 1821780 points
Other Parts Discussed in Thread: ADS1299
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1432983/ads1299-troubleshooting-spi-communication-and-data-instability-issues-outlier-on-nrf52832-board

器件型号:ADS1299

工具与软件:

大家好! 我有一个问题一直困扰着我一个星期,我不知道如何解决它。 我想征求每个人的建议。 谢谢!

我基于 OpenBCI PCB 设计使用 ADS1299芯片设计了一个 PCB、并尝试使用 Adafruit nRF52832开发板读取数据。 我主要修改了 master·chipaudette/OpenBCI (github.com)上基于 OpenBCI/Arduino/Librarys/ADS1299的代码 、以将适用于 AVR 控制器的 SPI 信号读取代码替换为适用于与 Adafruit nRF52832进行 SPI 通信的代码。 在实际测试中、我使用代码来打印 ADS1299数据、该数据已从3字节2补码转换为4字节2补码。

代码确实如此处所示。 这和主功能代码一样、我打印了转换后的数据8个通道用于验证

void loop(){
  if (is_running) {
    //is data ready?      
    while(!(ADSManager.isDataAvailable())){            // watch the DRDY pin
      delayMicroseconds(10);
    }
    unsigned long start_micros = micros();
  
    //get the data
    // analogVal = analogRead(PIN_ANALOGINPUT);   // get analog value
    ADSManager.updateChannelData();            // update the channelData array 
    sampleCounter++;                           // increment my sample counter
    
    //Apply  filers to the data
    if (useFilters) applyFilters();
    ADSManager.printChannelDataAsText(MAX_N_CHANNELS,sampleCounter);  //print all channels, whether active or not
  }

} // end of loop

void ADS1299::updateChannelData(){
	byte inByte;
	int nchan=8;  //assume 8 channel.  If needed, it automatically changes to 16 automatically in a later block.
	digitalWrite(CS, LOW);				//  open SPI
	
	// READ CHANNEL DATA FROM FIRST ADS IN DAISY LINE
	for(int i=0; i<3; i++){			//  read 3 byte status register from ADS 1 (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
		inByte = transfer(0x00);
		stat_1 = (stat_1<<8) | inByte;				
	}
	
	for(int i = 0; i<8; i++){
		for(int j=0; j<3; j++){		//  read 24 bits of channel data from 1st ADS in 8 3 byte chunks
			inByte = transfer(0x00);
			channelData[i] = (channelData[i]<<8) | inByte;
		}
	}
	
	digitalWrite(CS, HIGH);				//  close SPI
	
	//reformat the numbers
	for(int i=0; i<nchan; i++){			// convert 3 byte 2's compliment to 4 byte 2's compliment	
		if(bitRead(channelData[i],23) == 1){	
			channelData[i] |= 0xFF000000;
		}else{
			channelData[i] &= 0x00FFFFFF;
		}
	}
}

我发现大多数数据都是正常的、但突然发生了突变;信号应该是连续的、但显然存在错误的数据点。 我发现转换3字节二进制补码数据不是问题。 相反、问题似乎出在数据读取过程本身。

以下是 ADS1299 8通道数据在不同情况下的数据:1)悬空2)内部测试信号:短接3)内部测试信号:1mV 方波 4)内部测试信号:2mV 方波。 最左边只是一个计数器、后面是8个通道数据。 正如您所看到的、幅度似乎是正确的、但读数有突变、我将其称为异常值。 这种噪声让我感到疯狂。

为了帮助进行调试、我会尽可能详细地列出信息。

首先是我的寄存器设置:

第二、 我怀疑问题在于 SPI 通信、因此我使用了逻辑分析仪和示波器捕获信号以进行分析。 但是、由于这是我第一次使用这些仪器来捕获信号、我发现我捕获的信号有点矛盾、很难解释。

这是逻辑分析仪显示的内容:此 SPI 通信信号是否存在任何问题? 我注意到 SCLK 信号看起来不像预期的那样;它应该看起来不像这样。

为了进一步研究、我使用示波器来测量 SCLK 和 DRDY 信号的波形。 黄色迹线为 SCLK、蓝色迹线为 DRDY 信号。

1.

在示波器上、SCLK 信号看起来相对正常、但 DRDY 信号在变为高电平之前未按预期行为。 在下图中、我主要观察 DRDY 信号。 我将采样率设置为1000Hz、因此间隔为1ms、并使用自动设置成功采集此间隔。 但是、我注意到 DRDY 信号非常不稳定;当我将时间间隔调整为1ms 时、信号看起来不一致。 如您所见、除了每1ms DRDY 信号外、还有一些噪声。

这是我到目前为止已经尝试过的步骤、但我不确定是我的电路、代码问题还是我选择了错误的 MCU。 我还尝试使用 ESP32读取数据。 这种情况真的令人沮丧。 如果有人可以提出可能的问题、我会尝试收集更多信息并努力找到解决方案。 非常感谢!

附录:这里是我使用 nRF52832设置 SPI 所用的代码、这也是与原始代码的主要区别。"

#include "ADS1299.h"

void ADS1299::initialize(int _DRDY, int _RST, int _CS, int _FREQ, boolean _isDaisy){
	isDaisy = _isDaisy;
	DRDY = _DRDY;
	CS = _CS;
	int FREQ = _FREQ;
	int RST = _RST;
	
	delay(250);				// recommended power up sequence requiers Tpor (~32mS)	
	pinMode(RST,OUTPUT);
	digitalWrite(RST,LOW);
	delayMicroseconds(4);	// toggle reset pin
	digitalWrite(RST,HIGH);
	delayMicroseconds(20);	// recommended to wait 18 Tclk before using device (~8uS);
	

    // **** ----- SPI Setup ----- **** //
    
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE1); // clock polarity = 0; clock phase = 1 (pg. 8)
    
    switch (FREQ){
        case 8:
            SPI.setClockDivider(SPI_CLOCK_DIV8);
            break;
        case 4:
            SPI.setClockDivider(SPI_CLOCK_DIV16);
            break;
        case 2:
            SPI.setClockDivider(SPI_CLOCK_DIV32);
            break;
        case 1:
            SPI.setClockDivider(SPI_CLOCK_DIV64);
            break;
        default:
            break;
    }
    
    // **** ----- End of SPI Setup ----- **** //
    
    // initalize the data ready chip select and reset pins:
    pinMode(DRDY, INPUT);
    pinMode(CS, OUTPUT);
    
    digitalWrite(CS,HIGH); 	
	digitalWrite(RST,HIGH);
}


//SPI communication methods
byte ADS1299::transfer(byte _data) {
	return SPI.transfer(_data);
}