CH32V003 - використання вбудованого операційного підсилювача

Мікроконтролери CH32V003 (як і CH32V006) мають одну дуже цікаву апаратну фішку - вбудований операційний підсилювач (OPA). У цій статті я спробую розібратися та на практиці показати, як ним користуватися для вимірювання малих напруг: наприклад, знімати показники з різноманітних сенсорів чи струмових шунтів.

Перш ніж переходити до пайки, варто трохи поглянути на архітектуру. Вбудований OPA має мультиплексовані входи — це означає, що він може програмно перемикатися і брати сигнал з різних пар пінів. Наприклад, у корпусі TSSOP20 доступні дві групи: нульова (PA1 — OPN0, PA2 — OPP0) та перша (PD0 — OPN1, PD7 — OPP1). Проте вихід завжди залишається один — це жорстко прив’язаний пін PD4 (OPO).

З “молодшими” чіпами в корпусах SOP8 та SOP16 ситуація трохи інша. Механізм мультиплексування в самому кремнії залишився, але потрібні ніжки просто фізично не виведені назовні, тому варіантів для перемикання там фактично немає. (До речі, є цікавий нюанс: на SOP16 розробники фізично вивели пін OPP1, але OPN1 залишили всередині).

Щоб продемонструвати користь цього підсилювача на реальному прикладі, я взяв звичайну термопару типу K (TP-01). Під час тестів у киплячій воді (при 100 °C) вона генерує ЕРС усього близько 0.0029 Вольта (2.9 мВ):

Чому ми не можемо обійтися без підсилювача? Річ у тім, що АЦП (ADC) у CH32V003 є 10-бітним. Якщо живити мікроконтролер від 3.3 В, то мінімальний крок квантування (навіть в ідеальних умовах без урахування шумів) становитиме: 3.3 V / 1024 = 0.0032 В (або 3.2 мВ).

Тобто напруга, яку термопара видає при ста градусах, навіть не дотягує до одного кроку АЦП! Якщо ми спробуємо читати сенсор напряму, наша “точність” у найкращому випадку складатиме десь ±100-130 градусів.

Для того, щоб перетворити ці мікровольти на адекватний сигнал, який зможе “побачити” мікроконтролер, ми і задіємо вбудований OPA. Під’єднаємо його за класичною схемою неінвертуючого підсилювача з коефіцієнтом 1:101:


Коефіцієнт підсилення задається резисторами 100 кОм та 1 кОм, а паралельно доданий конденсатор забезпечить додаткову фільтрацію сигналу від шумів.

Напруга зміщення нуля (Input Offset Voltage) - в операційних підсилювачах є один важливий нюанс, який може збентежити. На практиці в мене це проявилося так: зібрана на макетній платі схема працювала ідеально - при замиканні входу OPA+ на землю я отримував майже нуль на АЦП (значення 4–5). Але після перенесення схеми на PCB з іншим контролером, при замкненому вході я отримав на АЦП значення 165, що для 10-бітного АЦП при живленні 3.3 В відповідає напрузі близько 0.53 В на виході OPA.

Спочатку я почав шукати проблему чи непропай, але виявилося, що це абсолютно нормальна і припустима поведінка підсилювача. За документацією на CH32V003, його власна вхідна напруга зміщення (Vioffset​) типово становить ±2.2 мВ, а максимум може сягати ±7 мВ.

Оскільки наш коефіцієнт підсилення дорівнює 101, цей крихітний апаратний зсув множиться разом із корисним сигналом. Наприклад, типове зміщення у 2.2 мВ перетворюється на 222 мВ (∼0.22 В) на виході. А моє значення АЦП 165 (0.53 В) означає, що зміщення конкретно цього кристала становить близько 5.2 мВ — що цілком ідеально вписується в заводські допуски ±7 мВ.

Далі для практичного тесту я використаю мікроконтролер CH32V003 у корпусі TSSOP20. Для виводу інформації слугуватиме OLED-дисплей із роздільною здатністю 128х32 пікселі. У результаті вийшла ось така схема:


Важливий нюанс: термопара насправді не вимірює абсолютну температуру, а лише відносну. Тобто напруга на її виходах залежить від того, наскільки гарячою (чи холодною) є точка вимірювання відносно контактів підключення на платі.

Тому, щоб отримати абсолютну температуру, я додав до схеми NTC-термістор. Він вимірюватиме температуру навколишнього середовища та самої плати, і вже до цього базового значення ми програмно додаватимемо різницю, яку наміряли термопарою. В електроніці цей процес відомий як компенсація холодного спаю.

Процес виготовлення плати:


Плата готова - перейдемо до програмування.

Для початку потрібно налаштувати піни, ініціалізувати та увімкнути OPA. Це робиться наступним чином:

    // Увімкнути тактування для портів A, D, АЦП та альтернативних функцій (AFIO)
    RCC_APB2PeriphClockCmd(
        RCC_APB2Periph_GPIOA |
        RCC_APB2Periph_GPIOD |
        RCC_APB2Periph_ADC1 | 
        RCC_APB2Periph_AFIO, ENABLE
    );

    GPIO_InitTypeDef GPIO_InitStructure = {0};    
    // Налаштовуємо PA1 (Вхід OPA - / OPN0) та PA2 (Вхід OPA + / OPP0) як аналогові входи
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Налаштовуємо PD3 (NTC) та PD4 (OPA OUT) як аналогові входи
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    // Регістр EXTEN_CTR керує вбудованим OPA
    EXTEN->EXTEN_CTR |= EXTEN_OPA_EN;
    OPA_InitTypeDef OPA_InitStructure = {0};
    OPA_InitStructure.PSEL = CHP0; // OPA+ підключається до фізичного піна PA2
    OPA_InitStructure.NSEL = CHN0; // OPA- підключається до фізичного піна PA1
    OPA_Init(&OPA_InitStructure);
    OPA_Cmd(ENABLE);

Повний вихідний код прошивки доступний за посиланням: https://neonhero.dev/ua/files/ch32opa/main.c .

Після цих налаштувань можна зчитувати посилений сигнал термопари безпосередньо з піна PD4 (канал АЦП AIN7). А з піна PD3 (канал AIN4) ми читатимемо значення NTC-термістора для компенсації кімнатної температури.

На надвисоку точність я не розраховую, похибки у ±3–5 градусів для моїх завдань цілком вистачить. Тому складною калібровкою я не займався. Лише перевірив і відкалібрував розрахункові значення за двома контрольними точками: кімнатною температурою та температурою киплячої води (100 °C):


Використання вбудованого операційного підсилювача в мікроконтролерах CH32V - це цікаве інженерне рішення, яке дозволяє зекономити місце на платі та зчитувати мілівольтні значення з мінумом додаткової обв’язки.

 

Коментарі

Популярні дописи з цього блогу

Підключення поворотного енкодера до CH32V: теорія, осцилограми та код на С

Програмний I2C проти апаратного: запускаємо U8x8 на CH32V003

Огляд DC-DC Step-down Buck перетворювачів