CocoJumbo 1 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба Здравствуйте. Использую 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 на компьютер } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 206 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба Пишете 4 байта? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CocoJumbo 1 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба 1 minute ago, Plain said: Пишете 4 байта? Для каждого сообщения пишу столько байт, сколько минимально необходимо для каждой транзакции. В функции HAL_SPI_TransmitReceive за это отвечает четвёртый аргумент. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 206 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба 4 минуты назад, CocoJumbo сказал: пишу столько байт, сколько минимально необходимо Для "Configuration register" надо 16 бит — сколько пишете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CocoJumbo 1 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба 10 minutes ago, Plain said: Для "Configuration register" надо 16 бит — сколько пишете? Да, и правда. Писал на 1 байт больше, чем надо. Исправил. Ничего не решило. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 28 января, 2023 Опубликовано 28 января, 2023 · Жалоба 1. Наличие delay(time) в коде. Не то, чтобы их не должно быть совсем, но насколько помню, окончание оцифровки лучше смотреть через бит Ready в статусном регистре. 2. Проверьте настройки SPI (полярность CLK, фаза "защелки"). По даташиту на АЦП защелка данных идет по raise. На Вашем скриншоте с Л.А. отмечены fail фронт. 3. Какая размерность массива txBuf[] и его размер ? итд Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CocoJumbo 1 28 января, 2023 Опубликовано 28 января, 2023 (изменено) · Жалоба 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 стояли и продолжают стоять. Это вроде как соответствует "защёлкиванию" данных на растущем фронте. 3. uint8_t txBuff[4]; uint8_t rxBuff[4]; Не повлияло. Стыдно за напрасно потраченное вами время. Ларчик просто открывался, как это иногда бывает. Неделю мучался с этой проблемой. В итоге всего лишь через час после публикации топика я обнаружил, что перепутал местами расположение пинов AIN2+, AIN2- и AIN3+ и AIN3- . При чём ещё на этапе проектирования платы. Заметил только сейчас. Подключил датчик к другим пинам, и сигнал начал считываться как положено. Спасибо за помощь. Изменено 28 января, 2023 пользователем CocoJumbo 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться