Перейти к содержанию
    

AD7799 - проблема со считыванием входного сигнала

Здравствуйте.

Использую AD7799 для считывания напряжения с тензометрического датчика (взвешивает до 5 кг). Чипом АЦП управляет STM32. AD7799 установлен на печатной плате собственной разработки (ссылка на тех. спецификацию: https://www.analog.com/media/en/technical-documentation/data-sheets/ad7798_7799.pdf) . В процессе работы упёрся в проблему -  никак не могу считать корректное значение с аналогового входа АЦП - приложение усилия на тензодатчик никак не влияет на считываемое значение. Вместо этого, якобы считывается какое-то +- постоянное значение, на которое я при этом не могу повлиять. SPI интерфейс работает исправно - данные успешно отправляются и считываются с/на АЦП, что подтверждается как логическим анализатором, так и выводом данных в компьютер посредством последовательного порта. Если мультиметром замерить напряжение между выходами тензодатчика, и надавить на него пальцем, видно как напряжение меняется на несколько милливольт - из чего я делаю вывод, что тензодатчик исправен. Система ведёт себя не так как я ожидаю, особенно это проявляется при изменении параметра GAIN.

Как я подхожу к выбору коэффициента усиления входного сигнала (GAIN): заявленная чувствительность тензодатчика 2 мВ/В, что при питании 5 В даёт +-10 мВ диапазона в каждую сторону (сжатие и растяжение), а в сумме целых 20 мВ диапазона для входного сигнала в АЦП. В соответствии с таблицей №1 (стр. 3) даташита я высчитал "Differential Input Voltage Range": Имея 20 мВ диапазон входного сигнала и Vref = 5В, я могу позволить себе усиление в 128 раз (максимальное), потому как в этом случае допустимый диапазон входящего дифф. сигнала будет равен 5000/128 = 39.06 мВ, что почти вдвое превышает диапазон фактического входного сигнала.

Что я получил на практике: если значение GAIN в CONFIGURATION регистре установить в 128, то при считывании STATUS регистра бит ERR встаёт в единицу, а считываемое значение АЦП будет равнятся 0xFFFFFF (16777215 DEC), что сигрализирует об ошибке - "Error sources include overrange and underrange". 

  • Такая же ошибка проявляется, если GAIN выставить в 1 или 2 (это когда усилитель не используется).
  • При установке всех остальных значений GAIN (от 4 до 64 включая) ошибки не появляется, но и "считываемое" значение тоже странное - обычно где-то 98-99% от максимального значения 0xFFFFFF, например 16750362 (DEC).
  • Данная ошибка проявляется как при Single Conversion Mode, так и при Continuous Conversion Mode.
  • Данная ошибка проявляется как при Buffered Mode, так и при Unbuffered Mode.

Есть подозрение, что проблема кроется не в неправильном конфигурировании регистров АЦП, а в разводке электросхемы. К сожалению у меня недостаточно знаний, чтобы диагностировать это самостоятельно в приемлемые сроки.

  • Опорное напряжение V-ref замкнуто с AVDD, и равняется 5 В. Тензодатчик также запитан пятью вольтами. 
  • Напряжение между землёй и любым из двух выходов тензодатчика (подключены к пинам AIN2- и AIN2+ на АЦП) равняется половине от V-опорного, т.е. около 2.5 Вольт, что также находится в допуске, согласно параметру "Absolute AIN Voltage Limits" из таблицы №1.
  • Напряжение между выходами датчика (пины AIN2- и AIN2+ у АЦП) в состоянии покоя равняется 0 В, а если приложить какой-то вес, поднимается до ~8 мВ, что определённо попадает в обозначенный выше диапазон "Differential Input Voltage Ranges" из той же таблицы №1.

Не понимаю, что не даёт мне считать истинное значение сигнала. Буду рад, если кто-то сможет подсказать, в каком направлении искать решение. 

Ниже приложен код, управляющий коммуникацией, схема платы а также фото "живого" решения. При необходимости могу приложить скриншоты SPI коммуникации из логического анализатора.

//Reset AD7799
    txBuff[0]=0xFF;
    txBuff[1]=0xFF;
    txBuff[2]=0xFF;
    txBuff[3]=0xFF;
    CS_Clear
    HAL_SPI_TransmitReceive(&hspi2, txBuff, rxBuff, 4, 300);
    CS_Set
    HAL_Delay(50);

//Write to CONFIGURATION REGISTER. Set polarity to Bipolar. Set gain to 64, Reference_detect to 1. Buff to 0. Channel to 1 (AIN2).
    txBuff[0]=0b00010000;  // Write operation to CONF_REG
    txBuff[1]=0b00000110;  //0,0,BO,U/B' 0,G2,G2,G0
    txBuff[2]=0b00100001;  //0,0,REF_DET,BUF 0,CH2,CH1,CH0
    txBuff[3]=0;
    CS_Clear
    HAL_SPI_TransmitReceive(&hspi2, txBuff, rxBuff, 4, 300);
    CS_Set
    HAL_Delay(50);

// Write to MODE REGISTER. Set Continuous Conversion Mode. Set Update rate to 4.17 Hz
    txBuff[0]=0b00001000;
    txBuff[1]=0b00000000; // MD2, MD1, MD0 , PSW, 0000 
    txBuff[2]=0b00001111; // 0000, FS3, FS2, FS1, FS0
    txBuff[3]=0;
    CS_Clear
    HAL_SPI_TransmitReceive(&hspi2, txBuff, rxBuff, 3, 300);
    CS_Set
    HAL_Delay(480); // Settle time is 480 ms, according to Table No. 14

while (1)
  {
  	HAL_Delay(235);
  	RDY = false; 
//Read from STATUS REGISTER until RDY goes low. Check errors.
	txBuff[0]=0b01000000;
    txBuff[1]=0;
    txBuff[2]=0;
    txBuff[3]=0;

	timeout = AD7799_TIMEOUT;
	CS_Clear
	while((timeout > 0) && !RDY) 
	{
		HAL_SPI_TransmitReceive(&hspi2, txBuff, rxBuff, 2, 300);
	  	if ((rxBuff[1] >> 7) == 0) // Если бит RDY становится в ноль
	  	{
	  		RDY = true;
	  		if ((rxBuff[1] & 0b01000000) == 0b01000000) // Если бит ERR становится в еденицу
	  		{
	  			char* error = "ERR\n";
	  			CDC_Transmit_FS((uint8_t *)error, 4);
	  		}
	  		if ((rxBuff[1] & 0b00100000) == 0b00100000) // Если бит NOREF становится в еденицу
	  		{
	  			char* error = "NOREF\n";
	  			CDC_Transmit_FS((uint8_t *)error, 6);
	  		}
	  	}
	  	else timeout--;
	 }
	 CS_Set
	 HAL_Delay(3);

//Read from DATA REGISTER.
  	txBuff[0]=0b01011000;
    txBuff[1]=0;
    txBuff[2]=0;
    txBuff[3]=0;

    CS_Clear
	HAL_SPI_TransmitReceive(&hspi2, txBuff, rxBuff, 4, 300);
	CS_Set

	reg_data = rxBuff[0];
    reg_data = (reg_data << 8) | rxBuff[1];
    reg_data = (reg_data << 8) | rxBuff[2];
    reg_data = (reg_data << 8) | rxBuff[3];

	#define SIZE sizeof(uint8_t)*8+1
	char buffer [SIZE];
	itoa (reg_data,buffer,10);
	buffer[SIZE-1] = '\n';

	CDC_Transmit_FS((uint8_t *)&buffer, SIZE); // Вывод считываемого значения через USB на компьютер

  }
}

Capture.thumb.JPG.c28cfd17c4ba62832af1070ff0de3640.JPGIMG_20230128_172256.thumb.jpg.132d9abbe8cbcf2a4fd3a688dc630fde.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, Plain said:

Пишете 4 байта?

Для каждого сообщения пишу столько байт, сколько минимально необходимо для каждой транзакции. В функции HAL_SPI_TransmitReceive за это отвечает четвёртый аргумент.

 

image.png.72e9ad0348902457aa4a645c187ca736.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, CocoJumbo сказал:

пишу столько байт, сколько минимально необходимо

Для "Configuration register" надо 16 бит — сколько пишете?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 minutes ago, Plain said:

Для "Configuration register" надо 16 бит — сколько пишете?

Да, и правда. Писал на 1 байт больше, чем надо. Исправил. Ничего не решило.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Наличие delay(time) в коде. Не то, чтобы их не должно быть совсем, но насколько помню, окончание оцифровки лучше смотреть через бит Ready в статусном регистре.

2. Проверьте настройки SPI (полярность CLK, фаза "защелки"). По даташиту на АЦП защелка данных идет по raise. На Вашем скриншоте с Л.А. отмечены fail фронт. 

3. Какая размерность массива txBuf[] и его размер ?

итд

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 minutes ago, k155la3 said:

1. Наличие delay(time) в коде. Не то, чтобы их не должно быть совсем, но насколько помню, окончание оцифровки лучше смотреть через бит Ready в статусном регистре.

2. Проверьте настройки SPI (полярность CLK, фаза "защелки"). По даташиту на АЦП защелка данных идет по raise. На Вашем скриншоте с Л.А. отмечены fail фронт. 

3. Какая размерность массива txBuf[] и его размер ?

итд

1.  Убрал HAL_Delay(50) после каждого сообщения. Да, окончание оцифровки проверяется по биту RDY. HAL_Delay(480) нужен для того, чтобы не отправлять бесполезные запросы статусного регистра, потому что я и так знаю ( согласно даташиту), что ближайшие 480 мс после записи в регистр MODE, оцифровка не закончится. В это время планирую занять процессор другими делами. 

2. Да, исправил параметр CPHA в логическом анализаторе на 1. 

На МК вот такие настройки SPI стояли и продолжают стоять. Это вроде как соответствует "защёлкиванию" данных на растущем фронте.

 image.thumb.png.77eef7cad3c9d2b7aa28fe9d65b149e6.png 

 

3.     uint8_t txBuff[4];
        uint8_t rxBuff[4]; 

 

Не повлияло.

Стыдно за напрасно потраченное вами время. Ларчик просто открывался, как это иногда бывает. Неделю мучался с этой проблемой. В итоге всего лишь через час после публикации топика я обнаружил, что перепутал местами расположение пинов AIN2+, AIN2- и AIN3+ и AIN3- . При чём ещё на этапе проектирования платы. Заметил только сейчас. Подключил датчик к другим пинам, и сигнал начал считываться как положено. 

image.png.d38f3eb25fb3d1ba423a242b1d2d29f7.png

 

Спасибо за помощь.

Изменено пользователем CocoJumbo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...