tel. +48 (12) 659-14-42

Programowe zwiększenie rozdzielczości pomiaru temperatury w sterowniku SU (nadpróbkowanie czyli oversampling).

Sterowniku SU 1.2 oraz sterownik SU 1.5 umożliwiają pomiar temperatury za pomocą czujników PT100 w zakresie -50...+160 stopni Celsjusza z rozdzielczością 0,2 stopnia na bit. Wynika to z tego że przetwornik mikrokontrolera jest 10 bitowy (1023 bitów), natomiast offset wynosi 89 bitów:

Rozdzielczość standardowa

Wzór 1. Obliczenie rozdzielczości standardowej.


Aby uzyskać rozdzielczość 0,01 stopnia na bit należy zwiększyć programowo rozdzielczość przetwornika do 15 bitów. Jest to tak zwana metoda nadpróbkowania, tzw. oversampling. Aby wykorzystać metodę oversamplingu, w mierzonym sygnale powinien znajdować się szum. Szum ten pochodzi od: CPU, wahania napięcia źródła zasilania, pracy portów wejścia/wyjścia, szum termiczny. Zwiększając rozdzielczość przetwornika przez oversampling, zmniejszamy częstotliwość próbkowania sygnału. Aby zwiększyć rozdzielczość przetwornika z 10 do 15 bitów (n=5) należy 4^5=1024 razy dokonać próbkowania sygnału. Otrzymane wyniki należy zsumować a następnie uśrednić przez przesunięcie bitów w prawo o 5 bitów co odpowiada jej podzieleniu przez 2^5 (tzw. decymacja).

Rozdzielczość rozszerzona

Wzór 2. Obliczenie rozdzielczości rozszerzonej.


W prezentowanym przykładzie, pomiar wejścia temperaturowego numer 1 odbywa się z rozdzielczością 0,007 stopnia na bit (tzw. oversampling), natomiast pomiar wejścia temperaturowego numer 2 odbywa się ze standardową rozdzielczością 0,2 stopnia na bit.

Prezentowany przykład napisany został w języku C w Atmel Studio 6.2:

#include <avr/io.h>
#include "avr/interrupt.h"
#include "avr/pgmspace.h" 
#include "global.h"
#include "lcd.h"
#include "i2c.h"
#include "procedury.h"
#include <util/delay.h>


volatile unsigned char BCD[5];
	
int main(void)
{
 unsigned char godziny, minuty,sekundy;
 unsigned long przetwornik1, przetwornik2, temp1, temp2;
 unsigned int c,b;
 sei();

 i2c_init();	//Inicjalizacja magistrali I2C
 
 DDRB=0xff;		//magistrala danych jako wyjscie
 sbi(DDRD,4);	//aktywacja pinu wyswietlacza
 sbi(DDRC,6);	//aktywacja pinu ING1 odczytu wejsc cyfrowych
 sbi(DDRC,7);	//aktywacja pinu do sterowania wyjsc cyfrowych
 sbi(DDRA,4);	//aktywacja pinu /OE wyjsc cyfrowych
 sbi(PORTC,6);	//stan wysoki na ING1
 sbi(PORTC,7);	//stan wysoki na OUTG1
 cbi(PORTA,4);	//stan niski na /OE (sterowanie wyjsc cyfrowych mozliwe)
 sbi(PORTD,4);	//stan wysoki na DISPLAY

 cbi(DDRC,2);	//pin PC2 wejscie (klawisz UP)
 cbi(DDRC,3);	//pin PC2 wejscie (klawisz LEFT)
 cbi(DDRC,4);	//pin PC2 wejscie (klawisz DOWN)
 cbi(DDRC,5);	//pin PC2 wejscie (klawisz RIGHT)
 cbi(DDRA,6);	//pin PC2 wejscie (klawisz ESC)
 cbi(DDRA,7);	//pin PC2 wejscie (klawisz OK)

 cbi(PORTA,0);
 cbi(PORTA,1);
 cbi(PORTA,2);
 cbi(PORTA,3);
 
 //Odpowiednie skonfigurowanie przetwornika w mikrokontrolerze
 ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
 c=0;

 LCD_init();	//inicjalizacja wyświetlacza LCD
 LCD_clear();	//wyczyszczenie wyświetlacza

 //zapisanie w pamięci wyświetlacza znaczka stopnie Celsjusza
 LCD_send_0(0b01000000);
 LCD_putchar(0b0011100);
 LCD_putchar(0b0010100);
 LCD_putchar(0b0011100);
 LCD_putchar(0b0000000);
 LCD_putchar(0b0000111);
 LCD_putchar(0b0001000);
 LCD_putchar(0b0001000);
 LCD_putchar(0b0000111);
 LCD_send_0(0x080);
 wait(20000); 

 while(1)
 {
	c++;	

/*
Pętle w której dokonywany jest odczyt z przetwornika
*/		
	if (c==100)
	{
		przetwornik1=0;
		przetwornik2=0;
		c=0;
		
		//W tej pętli dokonywany jest oversampling wejścia temperaturowego numer 1
		for (b=0;b<1024; b++)
		{
			ADMUX=(1<<REFS1)|(1<<REFS0)|(1<<MUX1);
			ADCSRA=(1<<ADSC)|(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
			loop_until_bit_is_set(ADCSRA, ADIF);
			ADCSRA |= _BV(ADIF); /* wyzeruj bit */ 
			przetwornik1=przetwornik1+ADC;
		}
	
		//Poniżej standardowy odczyt temperatury z wejścia numer 2
		przetwornik2=0;
		ADMUX=(1<<REFS1)|(1<<REFS0)|(1<<MUX1)|(1<<MUX0);
		ADCSRA=(1<<ADSC)|(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
		loop_until_bit_is_set(ADCSRA, ADIF);
		ADCSRA |= _BV(ADIF); /* wyzeruj bit */
		przetwornik2=przetwornik2+ADC;
	
	}
		 
	//Odpowiednie przeliczenie odczytu według wzoru numer 2
	temp1=((przetwornik1-91136)>>5)*7/10;
	if (temp1<5000) temp1=5000-temp1;
	if (temp1>=5000) temp1=temp1-5000;

	//Odpowiednie przeliczenie odczytu według wzoru numer 1
	temp2=(przetwornik2-89)*225/100;
	if (temp2<500) temp2=500-temp2;
	if (temp2>=500) temp2=temp2-500;
	
	bcd8(temp1); //zamiana hex na BCD
	
	LCD_xy(1,2);
	
	//wyświetlenie temperatury numer 1 na wyświetlaczu
	LCD_putchar(0x030+(BCD[1]>>0x004));
	LCD_putchar(0x030+(BCD[1]&0x00f));
	LCD_putchar(',');
	LCD_putchar(0x030+(BCD[0]>>0x004));
	LCD_putchar(0x030+(BCD[0]&0x00f));
	LCD_putchar(0);
	
	bcd8(temp2);//zamiana hex na BCD
	
	//wyświetlenie temperatury numer 2 na wyświetlaczu
	LCD_putchar(' ');
	LCD_putchar(0x030+(BCD[1]&0x00f));
	LCD_putchar(0x030+(BCD[0]>>0x004));
	LCD_putchar(',');
	LCD_putchar(0x030+(BCD[0]&0x00f));
	LCD_putchar(0);
				
	//Odczyt zegara RTC
	sekundy=read_ram_rtc(0x002);
	minuty=read_ram_rtc(0x003);
	godziny=read_ram_rtc(0x004);
 	
	//Wyświetlenie aktualnego czasu na wyświetlaczu LCD
	LCD_xy(9,1);
	LCD_LCZB(godziny);
	LCD_putchar(':');
	LCD_LCZB(minuty);
	LCD_putchar(':');
	LCD_LCZB(sekundy);
 }
}


Film 1. Film prezentujący działanie oversampling-u w praktyce.

Początek ..
ikona-google
ikona-youtubee