AD7792 / AD7793 для измерения температуры с помощью термопары (ТХА). Управление с помощью PIC16F628A

Крушневич С.П..

ВВЕДЕНИЕ.

Возникла необходимость в измерении температуры в трех точках термопарами. Учитывая положительный опыт в работе с AD7792 (измерение сопротивления) и наличие 3х дифференциальных входов, я выбрал ее для измерения температуры. В качестве датчиков температуры использовались термопары ТХА (Хромель-Алюмель, за бугром е еще называют "K-тип"), но могут быть использованы и другие типы термопар.

AD7792, AD7793 - это не только АЦП

Если присмотреться внимательнее, то микросхема AD7792 представляет целый набор компонентов: Остальные характеристике смотрите в официальной документации.

Блок-схема икросхемы аналогово-цифрового преобразователя AD7792

AD7792 + PIC16F628A

Схему измерения было решенно установить поближе к датчикам, поэтому на одной плате с AD7792 расположился и недорогой микроконтроллер PIC16F628A, который выполняет весть необходимый обмен данными с АЦП по интерфейсу SPI и передает результаты измерения (по запросу) по каналу RS485 (используется встроенный UART).

Схема электрическая прнинципиальная измерителя температуры с помощью термопар ТХА, ТКХ на базе: AD7792, PIC16F628, MAX483 (MAX485)
Нажмите для увеличения

Как видно, схема получилась весьма простая. Температура холодных спаев измеряется встроенным в микросхему датчиком температуры.

Ниже приведены участки программного кода для управления АЦП. Подробности настроек смотрите в документации на АЦП.



Исходники для микроконтроллера PIC16F628A

Начальная инициализация АЦП:
//Сброс АЦП. 32 клока с Dout=1
SendSPI(0xFF,8);
SendSPI(0xFF,8);
SendSPI(0xFF,8);
SendSPI(0xFF,8);
delay_ms(1); //Пауза

while(Din==1);//Ожидание завершения процедуры сброса


//Настройка внутреностей
//IO REG

SendSPI(0b00101000,8); //28h
delay_us(5);
SendSPI(0b00000000,8); //Опора отключенна

Выбор канала АЦП:
void ADC_configure_chanel(unsigned char Ch)
//Ch - номер канала, от 1 до 3 - входы, 4 - внутрений датчик температуры
{
//Config REG
SendSPI(0b00010000,8); // 10h
delay_us(5);
// ch Ch
// __ * ___
if (Ch==1) SendSPI(0b0100111010010000,16); //GAIN=64=18.28mV; Vbias=-AN1; ref=internal; buf=on
if (Ch==2) SendSPI(0b0100111010010001,16); //GAIN=64=18.28mV; Vbias=-AN2; ref=internal; buf=on
if (Ch==3) SendSPI(0b0100111010010010,16); //GAIN=64=18.28mV ref=internal; buf=on
if (Ch==4) SendSPI(0b0100111110010110,16); //GAIN=1/6 ref=1.17V
delay_us(5);
}

Самокалибровка:
void ADC_Calibrate(void)
{
//Mode REG
SendSPI(0b00001000,8); //08h
delay_us(5);
SendSPI(0b1000000000001111,16); //Калибровка нуля
while(Din==1); //Ждем завершения самокалибровки
//Mode REG
SendSPI(0b00001000,8); //08h
delay_us(5);
SendSPI(0b1010000000001111,16); //Калибровка шкалы
while(Din==1); //Ждем завершения самокалибровки
delay_us(5);
}

Запуск непрерывного преобразования:
void ADC_Start_Continuous_Conversion_Mode(void)
{
//Mode REG
SendSPI(0b00001000,8); //08h
delay_us(5);
SendSPI(0b0000000000001111,16); //0009h //Cont. conv.
delay_us(5);
}

Чтения результатов преобразования из АЦП:
signed int16 ADC_Read_Data(void)
{
//Ждем флага окончания преобразования
while(Din==1);
//Читаема
//DATA REG

SendSPI(0b01011000,8); //58h
delay_us(5);
return ReadSPI(16);
}

Перевод АЦП в ждущий режим:
void ADC_Shut_Down(void)
{
//Mode REG
SendSPI(0b00001000,8); //08h
delay_us(5);
SendSPI(0b0100000000001111,16); //0009h //Cont. conv.
delay_us(5);
}

Главная функция получения температуры:
void RefreshAllData(void)
{
float T4f;
// Настраиваем канал 1
ADC_configure_chanel(1);
// Делаем самокалибровку
ADC_Calibrate();
// Запускаем на преобразование
ADC_Start_Continuous_Conversion_Mode();
// Делаем паузу на 250 мсек. Мы не спешим, пускай все "устаканится"
delay_ms(250);
// Считываем показания канала 1 - Т1
T1_RAW=ADC_Read_Data()-0x8000;

// Настраиваем канал 2
ADC_configure_chanel(2);
// Делаем самокалибровку
ADC_Calibrate();
// Запускаем на преобразование
ADC_Start_Continuous_Conversion_Mode();
// Делаем паузу на
delay_ms(250);
// Считываем показания канала 2 - Т2
T2_RAW=ADC_Read_Data()-0x8000;

// Настраиваем канал 3
ADC_configure_chanel(3);
// Делаем самокалибровку
ADC_Calibrate();
// Запускаем на преобразование
ADC_Start_Continuous_Conversion_Mode();
// Делаем паузу
delay_ms(250);
// Считываем показания канала 3 - Т3
T3_RAW=ADC_Read_Data()-0x8000;

//Был замечен глюк. Если каждый раз переключатся на измерение температуры через встроенный датчик, то в это время отключается источник подтягивающего напряжения и конденсаторы в цепочке фильтра на входе успевают немного разрядится, что вызывает появление отрицательного напряжения на дифференциальном входе и как следствие - заметного снижения отображаемой температуры. Поэтом внутреннюю температуру измеряет редко.
if (NeedT4refresh++>10)
{
NeedT4refresh=0;
// Настраиваем канал ТЕМПЕРАТУРА
ADC_configure_chanel(4);
// Делаем самокалибровку
ADC_Calibrate(); // ??? нужна ли она?
// Запускаем на преобразование
ADC_Start_Continuous_Conversion_Mode();
// Делаем паузу
delay_ms(255);
// Считываем показания канала ТЕМПЕРАТУРА - Т4
T4_RAW=ADC_Read_Data();

ADC_configure_chanel(1); //После работы со встроенным термодатчиком
delay_s(3); //делаем паузу на восстановление заряда конденсаторов.
}

Благодаря тому, что все каналы АЦП выполены на одном кристалле, в одном технологическом процессе, они имеют очень близкие характеристики, что позволяет использовать одну функцию для преобразования "отсчеты АЦП" - "температура".

Учитывая, что в решаемой задаче высокая точность измерений не требуется, компенсация температуры холодного спая выполнялась просто приплюсовкой температуры холодного спая к температуре горячего спая. Это дало приемлемую точность в рабочем диаппазоне температур (от 20 до 350 градусов Цельсия).

Проверка встроенного датчика темперы показала его высокую линейность в диапазоне от -16 до +30 градусов (в этих пределах выполнялось тестовые измерения).

Точных данных я не привожу, так как для калибровки использовался самый обычый китайский цифровой мультиметр с функцией измерения температуры, у которого разрешающая способность 1 градус. По показаниям прибора отклонение температуры от измеренного мультиметром не превышала 1 градус (опять же: индикация с разрешением в 1 градус). Выполнив тщательную калибровку можно получить и более высокую точность, но ввиду малого времени на разработку и отсуствие более точных измерительных приборов более тонкая калибровка не выполнялась.

07.07.2009