AD7792 та AD7793 - представляють собою (ADC) з мультиплексором на 3 канали, внутнішнє та зовнішнє джерело опорної напруги, інструментальний підсилювач з коефіцієнтом підсилення від 1 до 128 раз, додатковим буферним повторювачем напруги, вбудований датчик температури і інше:
Інші характеристики дивіться в документації.
Схему вимірювання було вирішено встановити ближче до датчиків, тому на одній платі з AD7792 розташувався і недорогий мікроконтролер PIC16F628A, який виконує необхідний обмін даними з АЦП за інтерфейсом SPI і передає результати вимірювання (за запитом) каналом RS485.
Як видно, схема вийшла дуже проста. Температура холодних спаїв вимірюється вбудованим у мікросхеу AD7792 датчиком температури.
Нижче наведено приклад вихідного коду для керування АЦП.
Початкова ініціалізація АЦП
//Скидання АЦП. 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);
if (Ch==1) SendSPI(0b0100111010010000,16); //CH1: GAIN=64 = 18.28mV; Vbias = -AN1; ref=internal; buf=on
if (Ch==2) SendSPI(0b0100111010010001,16); //CH2: GAIN=64 = 18.28mV; Vbias = -AN2; ref=internal; buf=on
if (Ch==3) SendSPI(0b0100111010010010,16); //CH3: GAIN=64 = 18.28mV ref=internal; buf=on
if (Ch==4) SendSPI(0b0100111110010110,16); //Temperature: 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);
}
Зчитування результатів перетворення з ADC
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; //Зміщення шкали ADC до нуля"
// Налаштовуємо канал 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_Start_Continuous_Conversion_Mode();
// Робимо паузу
delay_ms(255);
// Зчитуємо показання каналу ТЕМПЕРАТУРА - Т4
T4_RAW=ADC_Read_Data();
ADC_configure_chanel(1); //Після роботи з вбудованим термодатчиком
delay_s(3); //робимо паузу на відновлення заряду конденсаторів.
}
Завдяки тому, що всі канали АЦП виконані на одному кристалі, в одному технологічному процесі, вони мають дуже близькі характеристики, що дозволяє використовувати одну функцію для перетворення "відліки АЦП" - "температура".
Враховуючи, що у поставленій задачі висока точність вимірювань не потрібна, компенсація температури холодного спаю виконувалася просто приплюсовування температури холодного спаю до температури гарячого спаю. Це дало прийнятну точність у робочому діапазоні температур (від 20 до 350 градусів Цельсія).
Перевірка вбудованого датчика темпери показала його високу лінійність в діапазоні від -16 до +30 градусів (у цих межах виконувалось тестове вимірювання).
Опубліковано
Оновлено 27.11.2023