Prosty przetwornik A/D na AVR AT90S2313

Potrzeba matką wynalazku! Co zrobić gdy potrzebujemy zaopatrzyć nasz układ oparty o mikrokontroler (np. At90s2313, attiny2313 i pochodne) w prosty przetwornik A/D, przy czym akceptujemy błędy pomiarowe na poziomie +/- 5% ?

Naturalnie można podłączyć zewnętrznego ADC na I2C, ale w przypadku gdy chcemy tylko zorientować się jak wygląda napięcie lub dokonać jego nie dokładnego pomiaru, można wykorzystać wbudowany w mikrokontroler komparator oraz obwód RC.

Teoria

Zasada działania opisywanej metody pomiaru napięcia przy pomocy wbudowanego w mikrokontroler komparatora, jest następująca. Mamy dany układ RC podłączony do jednego wejścia komparatora, do drugiego podłączamy napięcie które chcemy zmierzyć. Włączamy timer i zaczynamy ładować kondensator. Gdy komparator wskaże że napięcia są równe, zatrzymujemy timer i odczytujemy jego wartość, w ten sposób otrzymujemy wartość proporcjonalną do przyłożonego napięcia.

Praktyka

W praktyce, wykorzystamy jako obwód RC wewnętrzny rezystor podciągający port do dodatniej szyny zasilania przez który będzie się ładował zewnętrzny kondensator. Rozwiązanie to ogranicza konieczność stosowania dodatkowych elementów w układzie, oraz zapewnia nam pewną liniowość pomiarów w zakresie Vin < 2V. Jak można odczytać z poniższego wykresu, prąd dla rezystorów podciągających jest w tym zakresie praktycznie stały.

Zależność prądu od napięcia rezystorów podciągających układ AT90S2313

Zależność prądu od napięcia rezystorów podciągających układ AT90S2313

Rozwiązanie takie ma jednak również swoje wady, mianowicie prąd tych rezystorów może się wahać wraz z zmianą temperatury otoczenia, co wpływa na błąd pomiarowy, który wynosi dla zakresu temperatur od 10 do 40 stopni celesjusza ok. +/- 5%. Można ten błąd wyeliminować stosując zewnętrzne źródło prądu odniesienia.

Schemat układu

Schemat układu

Powyżej schemat układu testowego, który jak widać składa się dodatkowo z wyświetlacza LCD na którym prezentowane są odczytane wartości, oraz potencjometr który działa jako dzielnik napięcia wejściowego. Dodatkowo jest jeszcze przycisk S1, który służy do pomiaru wartości.

Układ testowy

Układ testowy

Na poniższym wykresie, wyniki pomiarów. Pomiary były dokonywane przy pomocy zwykłego (słabej jakości) multimetru, a co za tym idzie błąd pomiaru multimetru + błąd pomiaru samego układu mogły się z sumować i pewnie dlatego wykres nie jest idealnie prosty.

Wyniki pomiarów

Wyniki pomiarów

Z przeprowadzonych doświadczeń wynika, że liniowość takiego układu jest znośna w przypadku napięć wejściowych do max. 1.90V. Jest to dość niewielki zakres, jednak można go rozszerzyć stosując rezystorowy dzielnik napięcia 1:10 lub 1:100, co pozwoliło by na pomiary w zakresie 0..19V lub 0..190V.

Program

Poniżej zamieszczam kod programu, ważnym jest aby podczas dokonywania pomiaru, wszelkie przerwania nie były aktywne.

#define F_CPU 10000000L				/* Częstotliwość kwarcu */

#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>

#include "lcd.h"
#include "lcd.c"


void wait_until_key_pressed(void)
{
    unsigned char temp1, temp2;
    unsigned int i;

    do {
        temp1 = PIND;                  /* read input */
        for(i=0;i<65535;i++);
        temp2 = PIND;                  /* read input */
        temp1 = (temp1 & temp2);       /* debounce input */
    } while ( temp1 & _BV(PIND2) );

    loop_until_bit_is_set(PIND,PIND2);            /* wait until key is released */
}

int ADRead()
{
	unsigned int i=0;

	DDRB &=~ (1 << PB0);  /* charge capacitor */
	PORTB |= (1 << PB0);  

	while(1)
	{
		i++;
		if(bit_is_set(ACSR, ACO))
			break;
	}

	PORTB &=~ (1 << PB0);	/* discharge capacitor */	
	DDRB |= (1 << PB0);

	return i;
}


int main(void)
{
	char buff[7];

	DDRD &=~ (1 << PD2);        /* Pin PD2 input              */
	PORTD |= (1 << PD2);        /* Pin PD2 pull-up enabled    */


        lcd_init(LCD_DISP_ON);

        lcd_clrscr();
	lcd_puts("Press bu\ntton");
	wait_until_key_pressed();

	for(;;)
	{
		lcd_clrscr();
		itoa(ADRead(), buff, 10);
		lcd_puts(buff);
		wait_until_key_pressed();
	}
}

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *