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

Привет.

 

Читаю AD7799 в униполярном режиме и получаю какую-то ересь, ну либо не понимаю как правильно преобразовать цифры. Для начала, пытаюсь читать AVDD.

Вот код, которым настраиваю и читаю АЦП:

    ad7799_set_channel(AD7799_CH_AVDD_MONITOR);

    ad7799_set_burnout(0);
    ad7799_set_unipolar(1);
    ad7799_set_gain(AD7799_GAIN_1);
    ad7799_set_ref_det(0);
    ad7799_set_buffered(1);
    
    ad7799_set_psw(0);
    ad7799_set_rate(AD7799_RATE_4_17_HZ);

    ad7799_set_offset(0x000000);
    ad7799_set_fullscale(0xFFFFFF);

    ad7799_set_mode(AD7799_MODE_CONT);
    while(1)
    {
        if(ad7799_ready())
        {
            ad7799_dump_regs();
            printf("     offset = %f\n", ad7799_to_volts(ad7799_get_offset()));
            printf("  fullscale = %f\n", ad7799_to_volts(ad7799_get_fullscale()));
            printf("\n");
            adc_raw = ad7799_read_data_raw();
            printf("%06x   %2.6fv\n", adc_raw, ad7799_to_volts(adc_raw));
            for(i=0; i<20000000; i++);
        }
    }

 

Вот так преобразую в вольты:

uint32_t ad7799_read_data_raw(void)
{
    return ad7799_get_register(AD7799_REG_DATA, 3);
}

#define VREF 2.5
#define SPAN 0xFFFFFF
#define GAIN 1

float ad7799_to_volts(uint32_t value)
{
    return (float)(value * (VREF / SPAN * GAIN));
}

float ad7799_read_data_volts(void)
{
    return ad7799_to_volts(ad7799_read_data_raw());
}

 

Вот что выводит принтф:

     STAT = 0f
     MODE = 000f
     CONF = 1017
     DATA = aeff0c
       ID = 49
       IO = 00
   OFFSET = 800000
FULLSCALE = 555500

     offset = 1.250000
  fullscale = 0.833321

aeff0c   1.708948v

 

На ноге AVDD при этом сидит реальных 4.85В.

Всю голову уже сломал, помогите разобраться.

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


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

Привет.

Очевидно проблема в функции чтения дынных из АЦП, а не в функции преобразония этих данных в напряжение.

 

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


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

АЦП читается нормально - я это вижу по значениям регистров, вычитываемых после сброса: они соответствуют даташиту.

 

Я вот что подумал: в даташите написано, что при измерении в канале AVDD само значение AVDD сначала ослабляется в 6 раз, потом выносится на подствку 1.17В (типа, чтобы лучше видеть пульсации напряжения). Означает ли это, что вместо сидящих на входе 5В я должен прочитать: (5/6)+1.17=2.003333 Вольта?

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


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

Я вот что подумал: в даташите написано, что при измерении в канале AVDD само значение AVDD сначала ослабляется в 6 раз, потом выносится на подствку 1.17В (типа, чтобы лучше видеть пульсации напряжения). Означает ли это, что вместо сидящих на входе 5В я должен прочитать: (5/6)+1.17=2.003333 Вольта?

 

Это всего лишь для контроля напряжения AVDD. На оцифровку каналов это не влияет.

Вы окончание преобразования как контролируете ? По ножке или чтением регистра статуса ?

 

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


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

Чтением регистра статуса:

uint8_t ad7799_ready(void)
{
    unsigned char rdy = 0;
    rdy = ad7799_get_register(AD7799_REG_STAT, 1) & 0x80;
    return(!rdy);
}

uint32_t ad7799_read_data_raw(void)
{
    return ad7799_get_register(AD7799_REG_DATA, 3);
}

void main(void)
{
    ...
    ad7799_set_mode(AD7799_MODE_CONT);
    while(1)
    {
            if(ad7799_ready())
            {
                adc_raw = ad7799_read_data_raw();
                printf("%06x   %2.6fv\n", adc_raw, ad7799_to_volts(adc_raw));
            }
    }
}

 

Еще вопрос: если АЦП подключен по униполярной схеме, то как правильно задавать значения FULLSCALE и OFFSET? Судя по даташиту (When the ADC is configured for unipolar operation, the output code is natural (straight) binary with a zero differential input voltage resulting in a code of 00...00, a midscale voltage resulting in a code of 100...000, and a full-scale input voltage resulting in a code of 111...111.), их надо задать как OFFSET=0, FULLSCALE=FFFFFF (нулевое смещение и размах во всю шкалу). Но если я так сделаю, то из АЦП всегда читается FFFFFF при напряжении на входе, например, 0.7В.

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

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


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

ilkz сказал:
Еще вопрос: если АЦП подключен по униполярной схеме, то как правильно задавать значения FULLSCALE и OFFSET? Судя по даташиту (When the ADC is configured for unipolar operation, the output code is natural (straight) binary with a zero differential input voltage resulting in a code of 00...00, a midscale voltage resulting in a code of 100...000, and a full-scale input voltage resulting in a code of 111...111.), их надо задать как OFFSET=0, FULLSCALE=FFFFFF (нулевое смещение и размах во всю шкалу). Но если я так сделаю, то из АЦП всегда читается FFFFFF при напряжении на входе, например, 0.7В.

Их вообще не надо трогать. Вы сначала так запустите.

Вот вам рабочий пример.

void Init_ADC(void)
{
uint16_t snd;

adc_proc = ST_IDLE;
InitSPI();
// reset SPI interface

SPI_CS_ASSERT();
SPI_rcvr_byte(0xFF);
SPI_rcvr_byte(0xFF);
SPI_rcvr_byte(0xFF);
SPI_rcvr_byte(0xFF);
SPI_CS_DEASSERT();

_delay_ms(750);

// set Idle mode and 50 Hz update rate
SPI_CS_ASSERT();
snd = WEN | RW_W | CREAD_OFF | MODE_REG;
SPI_rcvr_byte(snd);
snd = IDLE_MOD | FS_RATE_16_1;
SPI_rcvr_byte(snd >> 8);
SPI_rcvr_byte(snd);
SPI_CS_DEASSERT();

adc_tim = 500UL;	

adc_ch_num = 0;
}
uint8_t ADC_Process(void)
{
uint8_t ret_val = 0;
uint16_t snd;

switch(adc_proc)
{
	case ST_IDLE:
			if(adc_tim) break;				

			// set gain = 4, unipolar, buffered
			SPI_CS_ASSERT();
			snd = WEN | RW_W | CREAD_OFF | CONF_REG;
			SPI_rcvr_byte(snd);

			switch(adc_ch_num)
			{
				case PP_CHAN:
					snd = BO_DIS | UB_B | GAIN_4 | REF_DET_DIS | BUF_ENA | CHAN_AIN2;
					//snd = BO_DIS | UB_U | GAIN_1 | REF_DET_DIS | BUF_ENA | CHAN_AIN2;
					break;
				case PT_CHAN:
					snd = BO_DIS | UB_U | GAIN_2 | REF_DET_DIS | BUF_ENA | CHAN_AIN1;
					break;
				case TT_CHAN:
					snd = BO_DIS | UB_U | GAIN_1 | REF_DET_DIS | BUF_DIS | CHAN_AIN3;
					adc_tim = 1000UL;
					break;
			};				

			SPI_rcvr_byte(snd >> 8);
			SPI_rcvr_byte(snd);
			SPI_CS_DEASSERT();

			// start single conversion
			SPI_CS_ASSERT();
			snd = WEN | RW_W | CREAD_OFF | MODE_REG;
			SPI_rcvr_byte(snd);
			snd = SINGLE_MOD | FS_RATE_16_1 | PSW_ON;
			SPI_rcvr_byte(snd >> 8);
			SPI_rcvr_byte(snd);
			SPI_CS_DEASSERT();

			adc_proc = ST_WAIT_DATA;			
			break;	
	case ST_WAIT_DATA:
			SPI_CS_ASSERT();
			snd = WEN | RW_R | CREAD_OFF | STATUS_REG;
			SPI_rcvr_byte(snd);
			snd = SPI_rcvr_byte(0);
			SPI_CS_DEASSERT();

			if((snd & RDY) == 0) adc_proc = ST_DATA_RDY;

			break;
	case ST_DATA_RDY:
			// read data reg
			SPI_CS_ASSERT();
			snd = WEN | RW_R | CREAD_ON | DATA_REG;
			SPI_rcvr_byte(snd);
			adc_val[adc_ch_num] = 0;
			adc_val[adc_ch_num] = SPI_rcvr_byte(0);
			adc_val[adc_ch_num] <<= 8;
			adc_val[adc_ch_num] |= SPI_rcvr_byte(0);
			adc_val[adc_ch_num] <<= 8;
			snd = WEN | RW_R | CREAD_OFF | DATA_REG;
			adc_val[adc_ch_num] |= SPI_rcvr_byte(snd);
			SPI_CS_DEASSERT();				

			adc_proc = ST_IDLE;					

			++adc_ch_num;
			if(adc_ch_num > TT_CHAN) 
			{
				adc_ch_num = 0; 
				ret_val = 1;
			} 

			break;
}
return ret_val;
}
 

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


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

Ребята, все нормально: обнаружилась ошибка в разводке - вход не был подключен. :)

Спасибо всем за помощь!

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

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


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

Ребята, все нормально: обнаружилась ошибка в разводке - вход не был подключен. :)

Спасибо всем за помощь!

Электроника - наука о контактах ;-)

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


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

пытаюсь читать AVDD

DATA = aeff0c
aeff0c   1.708948v

На ноге AVDD при этом сидит реальных 4.85В.

Всю голову уже сломал, помогите разобраться.

По вышеприведённой формуле:

 

$AEFF0C · 1,17 В · 6 / 2^24 = 4,79872603 В

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


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

Доброго времени суток ув. форумчане

Столкнулся я тут с задачей на AD7799, имеется 3 таких ацп на общей шине с раздельными CS ессно. К двум каналам каждого АЦП подключены свои мостовые тензодатчики.

Устройство занимается дозированием, посему требуется достаточно быстрый опрос значений с ацп с приемлимой точностью.

Столкнулся вот с какими проблемами:

1. Не совсем понятно как себя ведет внутренний фильтр.

youtu.be/sv3gs0dkyPo

На видео показана проблема.

5 число сверху - вход к которому подключен датчик.

результаты измерения ацп иногда замирают, причем на разное время.

так-же время замирания зависит от частоты фильтра. чем выше частота фильтра тем короче эти задержки

режим работы ацп - непрерывный. данные считываю по флагу в регистре статуса.

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

код инициализации:
 

void AD7799_Config(unsigned char chip)
{
    AD7799_Init(chip);
    AD7799_SetUnipolar(chip,1);
    AD7799_SetGain(chip,AD7799_GAIN_1);               
    
   AD7799_SetFilterMode(chip,AD7799_Filter_16_7_50hz);
    
    AD7799_SetChannel(chip,AD7799_CH_AIN2P_AIN2M);  
    
    AD7799_SetMode(chip,AD7799_MODE_CAL_INT_ZERO);
    while(AD7799_Ready(chip));
    
    AD7799_SetMode(chip,AD7799_MODE_CAL_INT_FULL);
    while(AD7799_Ready(chip));
    
    AD7799_SetChannel(chip,AD7799_CH_AIN1P_AIN1M);

    AD7799_SetMode(chip,AD7799_MODE_CAL_INT_ZERO);
    while(AD7799_Ready(chip));
    
    AD7799_SetMode(chip,AD7799_MODE_CAL_INT_FULL);
    while(AD7799_Ready(chip));

    AD7799_SetFilterMode(chip,AD7799_Filter_10);
    
    AD7799_SetMode(chip,AD7799_MODE_CONT);
}

код опроса регистра статуса

unsigned char AD7799_Ready(unsigned char CS)
{
  unsigned char rdy = 0;
  unsigned long reg_stat= AD7799_GetRegisterValue( CS,AD7799_REG_STAT,1);
  rdy = (reg_stat & 0x80);
  if((rdy==0x80)&&((reg_stat& 0x07)==0x00))
    rdy=1;
  if((rdy==0x80)&&((reg_stat& 0x07)==0x01))
    rdy=2;
  if((rdy==0x80)&&((reg_stat& 0x07)==0x02))
    rdy=3;
  return(rdy);
}

код опроса ацп

       switch(AD7799_Ready(AD7799_CHIP2))
        {
        case 1:
              weigt[2] = AD7799_GetRegisterValue(AD7799_CHIP2, AD7799_REG_DATA,3);
              AD7799_SetChannel(AD7799_CHIP2,AD7799_CH_AIN2P_AIN2M);
              break;
        case 2:
              weigt[3] = AD7799_GetRegisterValue(AD7799_CHIP2, AD7799_REG_DATA,3);
              AD7799_SetChannel(AD7799_CHIP2,AD7799_CH_AIN1P_AIN1M);
              break;
        }

 

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

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


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

вывел все регистры на экран. считываю их в цикле измерений.

1 - STATUS

2 -  MODE

3 - CONFIGURATION

4 - OFFSET

5 - FULLSALE

6- значение ацп.

 

по видео видны странности:

1. в моменты пауз в регистре статуса биты ready и error = 0

положительное усилие на датчик не влияет на эту ситуацию

но отрицательное усилие поднимает бит error сразу при его появлении(что в принципе нормально, на входе ацп отрицательное значение становится).

2. очень большая задержка между повышением показаний на выходе ацп и моментом приложения положительного усилия.

так-же после снятия положительного усилия с датчика с очень большой задержкой он возвращается в нулевое положение по показаниям.

куда копать? всю голову сломал, не могу понять природу происходящей магии

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


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

On 1/14/2019 at 3:54 PM, Reystlin said:

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

Встречал такое у АЦП с мултиплексором на входе, вроде у AD7949. Канал с низким напряжением на входе хорошо чувствовал своего соседа (опрошенного перед ним), у которого на входе был потенциал заметно выше (в режиме по умолчанию эта ИМС перебирала каналы последовательно от 0 до N). Проблема решилась отключением режима последовательного перебора канала и двух- трехкратным чтением каждого канала.

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


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

11 minutes ago, alexunder said:

Встречал такое у АЦП с мултиплексором на входе, вроде у AD7949. Канал с низким напряжением на входе хорошо чувствовал своего соседа (опрошенного перед ним), у которого на входе был потенциал заметно выше (в режиме по умолчанию эта ИМС перебирала каналы последовательно от 0 до N). Проблема решилась отключением режима последовательного перебора канала и двух- трехкратным чтением каждого канала.

Пробовал делать переключение каналов на каждое 10ое измерение, все-равно каналы друг в друга проникают. после переключения один канал плавно подбирается к уровню второго

было решено отказаться от использования вторых каналов.

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

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


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

12 hours ago, Reystlin said:

Пробовал делать переключение каналов на каждое 10ое измерение, все-равно каналы друг в друга проникают. после переключения один канал плавно подбирается к уровню второго 

Это несколько интересных эффектов:

1. перезаряд всех имеющихся в схеме емкостей на входе АЦП (и внешних реальных-паразитных и внутренней) от неизвестного уровня предыдущего входа к новому измеряемому уровню током нового подключенного измеряемого входа, с учетом входного сопротивления АЦП и других токов утечки.

2. перегрузка фильтр АЦП новыми данными. Процесс и технология обычно описаны в даташите АЦП. Но следует понимать, что сеачала должно произойти (1) и тольео потом начаться (2).

 

У меня был случай, когда, паразитные емкости электронных коммутаторов мешали. Вводил даже специальный вход, перезаряжающий все емкости измерителя до среднего уровня, от которого уже можно было посчитать максимальное время перезаряда до измеряемого уровня. То есть In1-Ref-In2-Пауза-Измерение_In2.

Это все считается (ну или хоть симулируется в симуляторе как набор цепочек R-C), подбирать тут опасно- будет на одном входе -Vmax, а  на другом входе +Vmax, и окажется что емкости недоперезарядились.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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