Opis bezprzewodowego układu do pomiaru oporu elektrycznego skóry Andrzej Jeziorski 307408 Układ powstały w ramach zaliczenia przedmiotu Programowanie Mikrokontrolerów miał być udoskonaleniem układu do pomiaru oporu skóry wykonanego w ramach pracy licencjackiej 1100-LIC-FBM-NI-191762. Tematem pracy licencjackiej było stworzenie prostego układu do pomiaru oporu skóry człowieka. Układ taki miał pozwolić na zaobserwowanie tzw. reakcji skórnogalwanicznej, czyli wzrostu przewodnictwa skóry w odpowiedzi na stresujący bodziec. Wzrost przewodnictwa spowodowany jest mimowolnym wypełnianiem się duktów potowych. Człowiek nie jest w stanie łatwo kontrolować swojej reakcji skórnogalwanicznej, dlatego urządzenia do jej rejestracji wykorzystuje się w poligrafach jako elementy wykrywacza kłamstw. Układ wykonany w ramach pracy licencjackiej składał się z: elektrod, dzielnika napięcia regulowanego multiplekserem i mikrokontrolera Atmega 16. Układ mierzył spadek napięcia na elektrodach i przesyłał informację o tym do komputera za pośrednictwem komunikacji szeregowej. Układ pozwalał na rejestrację reakcji skórnogalwanicznej, ale był bardzo wrażliwy na zakłócenia pochodzące od sieci elektrycznej. 1. Zdjęcie starego układu do pomiaru reakcji skórno-galwanicznej
Żeby zredukować w pomiarach zakłócenia spowodowane sygnałem 50 Hz pochodzącym z sieci elektrycznej powstał plan stworzenia wersji układu, która funkcjonowałaby bez bezpośredniego połączenia z siecią elektryczną. Układ taki może być następnie obudowany w warstwę chroniącą przed zakłóceniami pochodzącymi od pola elektrycznego. Układ powstały w ramach pracy licencjackiej był połączony z siecią elektryczna na dwa sposoby. Był zasilany prądem z sieci elektrycznej przez transformator oraz komunikował się z komputerem za pomocą kabla RS232. Gdy komputer był podłączony do sieci stanowiło to drugie źródło zanieczyszczenia pomiaru sygnałem z sieci. W układzie powstałym w ramach przedmiotu zastąpiono zasilanie sieciowe baterią. Komunikację z komputerem uczyniono bezprzewodową stosując moduł bluetooth. Sygnał szeregowy z odczytami urządzenia był przysyłany do komputera za pomocą fal radiowych. Do sterowania urządzeniem wykorzystano mikrokontroler typu ATTiny8. Procesor odpowiadał za przesyłanie informacji od 12-to bitowego przetwornika analogowo-cyfrowego (ADC) do nadajnika bluetooth. Procesor wykorzystywał zewnętrzny zegar kwarcowy o częstości taktowania 8 MHz. Za ADC służył układ scalony MCP3202. Mikrokontoler odbierał dane z ADC za pośrednictwem protokołu SPI, gdzie procesor pełnił funkcję master a przetwornik funkcję slave. Każdy 12-to bitowy odczyt z ADC był przesyłany za pomocą dwóch bajtów danych a następnie łączony w 16-to bitowy integer. Wynik pomiaru był następnie przesyłany poprzez port szeregowy do układu Bluetooth. Do komunikacji bluetooth służył układ HC-06. Po sparowaniu z urządzeniem odbiorczym, np. laptopem, układ ten przesyłał do niego wszystkie dane, które otrzymał poprzez port szeregowy. W ten sposób dane pomiarowe z ADC trafiały poprzez mikrokontoler do komputera, bez użycia przewodów. Cały układ zasilany jest przez 3 baterie AAA i układ stabilizujący napięcie na poziomie 3,3 V. 2. Schemat nowego układu. Dodatkową przewagą nowej wersji układu jest kompaktowy rozmiar i lepsza jakość połączeń zagwarantowana wytrawienie połączeń na miedzianej płytce. Układ pomiarowy w pracy licencjackiej miał charakter pajaka. Plątanina kabli na pewno przyczyniała się do wysokiego poziomu zakłóceń.
3. Schemat połączeń na płytce. 4. Zdjęcie gotowego układu. (wierzch)
5. Zdjęcie gotowego układu. (spód)
Kod programu readadc.c : /* * ReadADC.c * * Created: 2015-01-31 19:14:51 * Author: Andrzej Jeziorski */ #include <avr/io.h> #include"rs232.h" #include <util/delay.h> /* Funkcja inicjalizujaca dzialanie protokolu SPI */ void SPI_MasterInit(void) /* PB1 to wyjscie Slave Selectora */ /* PB3 - MOSI (Master Out, Slave In) to wyjscie SPI */ /* PB4 - MISO (Master In, Slave Out) to wejscie SPI */ /* PB5 - SCK to wyjscie zegara */ DDRB = (1<<PB4) (1<<PB3) (1<<PB5); DDRC = (1<<PB1) (1<<PC1); PORTC = 1 << PB1; PORTC = 1 << PC1; /* Uruchominie protokolu SPI */ /* Ustawienie uc jako Master */ /* Ustawienie czestosci zegara SPI fosc/16. */ SPCR = (1 << SPE) (1 << MSTR) (1 << SPR0); /* Funkcja wysylajaca 1 bajt */ void SPI_send_byte(uint8_t byte) /* Wprowadzenie bajtu do rejestru */ SPDR = byte; /* Transmisja bajtu zawartego w rejestrze SPDR */ while(!(spsr & (1<<SPIF))); /* Funkcja wysylajaca i odbierajaca 1 bajt */ uint8_t SPI_send_and_recieve_byte(uint8_t byte) uint8_t recieved = 0; /* Wprowadzenie bajtu do rejestru */ SPDR = byte; /* Transmisja bajtu zawartego w rejestrze SPDR i otrzymanie nowego */ while(!(spsr & (1<<SPIF))); recieved = SPDR; /* Zwrot wartosci w rejestrze */ return recieved; /* Funkcja odbierajaca 12 bitowa liczbe z wybranego kanalu ADC 1 lub 2*/ uint16_t ReadADC(int num) /* Deklaracja bajtow 1 i 2 skladajacych sie na wynik: t */ uint8_t byte1, byte2; /* Deklaracja bajtu z ustawieniami transmisji z ADC */ /* Pierwszy bit wybiera tryb miedzy trybem roznicowym a jednokanalowym, 1 oznacza tryb jednokanalowy */ /* Drugi bit pozwala wybrac kanal, 0 oznacza CH0 */ /* Trzeci bit ustawia kierunek kodowania liczby, 0 oznacz MSBF */ uint8_t settings = 0b10000000; if (num == 2) // drugi kanal ADC settings = 0b11000000; /* CS ON - poczatek komunikacji*/ PORTC &= 0 << PB1; /* Nadanie bitu startowego */ SPI_send_byte(0b00000001); /* Nadanie 3 bitow z ustawieniami i odbior bajtu zawierajacego pierwsze 4 bity wyniku */ byte2 = SPI_send_and_recieve_byte(settings); /* Odebranie bajtu zawierajacego koncowke wyniku */ byte1 = SPI_send_and_recieve_byte(0b00000000); /* CS OFF - koniec komunikacji*/ PORTC = 1 << PB1; /* Sklejenie bajtow w wynik i zwrot */ return ((byte2 <<8) byte1); /*FUNKCJA GLOWNA*/ int main(void) SPI_MasterInit(); setrs232(); while(1) uint16_t V1 = ReadADC(1); // odczyt wartosci z pierwszego kanalu ADC //uint16_t V2 = ReadADC(2); // odczyt wartosci z drugiego kanalu ADC writeword(v1); //writeword(v2); _delay_ms(100); return 0;
Kod programu rs232.c : #include"rs232.h" uint8_t isdata() return (UCSRA & (1<<RXC))? 1 : 0; void setrs232(void) /* set RS232 as follows: * BOUD RATE = 9600 * NO PARITY BIT? * 8 DATA BITS */ UBRRH = (uint8_t)(speed >> 8); // 4 most significant bits UBRRL = (uint8_t)speed; // 8 least significant bits UCSRC = ( (1<<URSEL) (1<<UCSZ1) (1 << UCSZ0 ) ); // 8 bits of date per frame UCSRB = ( (1<< RXEN) (1<<TXEN) (1 << RXCIE ) ); // turn on RS232 to receiving and sending // set interrupt reacting to data incomming uint8_t readbyte(void) while (!isdata()); uint8_t c = UDR; return c; uint16_t readword(void) uint8_t most, least; uint16_t data; least = readbyte(); most = readbyte(); data = most; data = ( data << 8 ); data = (uint16_t)least; return data; uint32_t readdword(void) uint16_t firstword, secondword; uint32_t data; firstword = readword(); secondword = readword(); data = secondword; data = (data << 16); data = (uint32_t)firstword; return data; void writebyte(uint8_t data) while (!(UCSRA & (1 << UDRE))); UDR = data; void writeword(uint16_t data) uint8_t most = (data >> 8); uint8_t least = (data & 0x00FF); writebyte(least); writebyte(most); void writedword(uint32_t data) uint16_t most = (data >> 16); uint16_t least = (data & 0x0000FFFF); writeword(least); writeword(most);
Kod pilku bibliotecznego rs232.h : #ifndef _RS_232_H_ #define _RS_232_H #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #define FCPU (8000000) #define RS232_BAUD_RATE (9600) #define UBBR (51) // for RS232_BAUD_RATE = 9600 #define SPEED (FCPU/16/(RS232_BAUD_RATE)) void setrs232(void); void writebyte(uint8_t data); void writeword(uint16_t data); void writedword(uint32_t data); uint8_t readbyte(void); uint16_t readword(void); uint32_t readdword(void); #endif