Prezentace 2012/Senzorove pole

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Samostatná práce

[editovat] Vývoj modulu modulu dotykových spínačů na bázi měření odporu pokožky

[editovat] Zadání

Navrhněte řešení senzorového (nemechanického) spínání světelných návěští v modelu elektrárny Lipno. Návštěvník bude moci model ovládat pomocí 11-ti tlačítek (senzorů). Po zmáčknutí tlačítka se rozsvítí příslušná část modelu a zůstane svítit několik sekund. Pokud bude během této doby stisknuto jiné tlačítko, musí dříve stisknutý okruh zhasnout. Model bude umístěn společně s jiným, který je již v provozu a který pracuje na bázi měření odporu pokožky návštěvníka při stisknutí ovládacích elektrod. Je žádoucí, aby ovládací prvky obou modelů vypadaly stejně.


[editovat] Návrh řešení

Zvolená koncepce řešení zadané úlohy je následující: Jako ovládací prvek jednotlivých spínaných okruhů byla použita dvojice elektrod. Na tyto elektrody je přes odpor vysoké impedance přivedeno bezpečné napětí.

Pokud se uživatel dotkne obou elektrod, napětí mezi elektrodami poklesne vlivem odporu lidské pokožky. Tento pokles napětí je měřen ADpřevodníkem mikroprocesoru a je následně vyhodnocen jako stisk tlačítka.

Problematické bylo splnění požadavku na přerušení časovaného sepnutí obvodu při stisku jiného tlačítka. Dostupné mikroprocesory mají většinou omezený počet vstupů ADpřevodníku. Bylo by tedy problematické realizovat požadovaný počet senzorů na jedné desce plošných spojů. Nebylo by to ani koncepčně správné. Řešení je následující: Navžený modul obsahuje 6 senzorů. Obvod je ale vybaven sběrnicí, napájenou odpojitelným proudovým zdrojem. K této sběrnici lze připojit více modulů. Pokud je v některém modulu aktivovaný senzor, je tímto modulem zmíněná sběrnice zkratována. Ostatní moduly tak obdrží informaci, že někdě bylo zmáčknuto tlačítko a dokážou se podle ní zařídit tak, aby bylo splněno zadání. Sběrnice byla navržena tak, aby se dala případně použít i pro nízkorychlostní asynchronní komunikaci.


Každý modul obsahuje galvanicky oddělenou výkonovou část, kterou je možné (žádoucí) napájet z jiného zdroje, než ze kterého jsou napájeny senzorové obvody (napájení senzorových obvodů by mělo být realizováno pouze naprosto bezpečným zdrojem bezpečného napětí). Jako spínací prvky jsou použity tranzistory mosfet IRFR024N s vemi nízkým odporem v sepnutém stavu (Idmax=17A).

[editovat] Schéma zapojení

Podle zadání byl navržen následující obvod řízený mikroprocesorem Atmega48.

Schéma zapojení

[editovat] Zdrojové kódy

Ovládací program pro mikroprocesor byl napsán v jazyce C ve vývojovém prostředí AVRstudio4. Zde jsou uvedené všechny zdrojové kódy projektu, tak jak byly v projektu rozděleny do jednotlivých souborů.

[editovat] senzorovePole_01.c - Soubor obsahující funkci main

sfafad

#include <stdint.h>
#include <avr/io.h> 
#include <math.h> 
#include <avr/power.h>

#include <stdlib.h>

#include <stdlib.h>

#define F_CPU 1000000UL  // 1 MHz

// #include <util/delay.h>
#include <math.h> 
#include "globVariablesDeklarace.h" //deklarace globalnich promenych

int main(void)
{
	iniPoResetu();
	do 
	{
		for (uint8_t i = 0; i<6;i++)
		{
			//postupne u vsech sesti tlacitek vyhodnocuje jejich zmacknuti a prislusnou reakci
			obsluhaTlacitka(i); 
		}
	}while (1);
}




[editovat] iniPoResetu.c - Inicializační funkce

Inicializace proměných a registrů po restartu.

/*********
GLOBALNI INICIALIZACE PO RESETU PROCESORU
	-obsahuje definice funkci pro inicializaci po resetu
*********/
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <stdint.h>


//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych


static void iniGlobVariables()
{
	for (int i=0;i<=5;i++) zmacknuto[i]=0; //tlacitka na zacatku nezmacknuta
	//zadouci doplnit i ostatni promene
}

static void iniCPU()
{
	
	//CLKPR=0x80; // nastaveni deliciho pomeru preddelicky cpu
	//CLKPR=REGISTR_DELICKY;
	//clock_prescale_set(4) 
	//clock_prescale_set(1); //nastaveni delicky CPU, nefunguje pri optimalizaci
	
}

//inicializace portu
static void iniPort()
{
	// B1 - vystup pro ovladani LED v 1
	DDRB = ((1<<DDB1)); 
	PORTB = ((1<<PORTB1));

	//vstupy AD prevodniku jako vstupy bez pullup	
	DDRC = 0x00; 
	PORTC = 0x00;
	
	// D0- RX in s pullupem, D1 - TX v jedna, vystupy D2-D7 v 1, 
	DDRD = 0b11111110; 
	PORTD= 0b11111111;	 
}
//inicializce citace 0
static void iniCount0 ()
{
//	OCR0A = 0x255;
	
	TCCR0A = 0x00|((1<<WGM01)); // WGM01 nastavi rezim CTC (na porovnani s OCR0A)
	TCNT0= 0x00; // citaci registr
	OCR0A=  255; // komparacni reg. A
	TIMSK0= ((1<<OCIE0A)); //preruseni pro spousteni adc 
	TCCR0B= 0x02; // nastavuje zdroj hodin a preddelicku 8
	
}

static void iniCount1 ()
{
	TCCR1B = (1<<WGM12); //ctc rezim, zastaveni citace
	OCR1A = DELKA_SVITU_PREPOCTENO;	//bude citat nastaveny cas		
	TCNT1 = 0x0000; //vynuluje citaci registr
	TCCR1A = 0x00; //(1<<WGM12); //ctc rezim	
	TCCR1C &= ~((1<<FOC1A)|(1<<FOC1A)); //Force output compare for channel A,B >>0
	TIMSK1 = (1<<OCIE1A); //povoli preruseni na porovnani A1

	TCCR1B |= ((1<<CS12)|(0<<CS11)|(1<<CS10) ); //pusti citac 2 - delicka 1024
//	TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10) ); //zastavi citac 1


}

//inicializace externiho preruseni na zmenu na pinu
static void iniPcint()
{

	PCICR  = 0x00 | ((1<<PCIE2)); //vyber pinu preruseni na zmenu PCINT33-PCINT16
	PCMSK2 = 0x00 | ((1<<PCINT16)); //preruseni jen na zmenu PCINT16 = RX

}

static void iniAdc()
{
	ADMUX = (0<<REFS1)|(1<<REFS0); //ref AVcc   //ADC multiplexer selection register
	ADMUX |= 0x00; // vyber pinu (dolni 4 bity)
	ADMUX |= (0<<ADLAR);
	ADCSRA = (1<<ADEN); //zapne prevodnik
	ADCSRA |= (1<<ADIE); //povoli preruseni Adc
	ADCSRA |= (1<<ADATE); //povoli atomatice pousteni
	ADCSRA |= ((0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //delicka 16 = 250kHz
	ADCSRB |= ((0<<ADTS2)|(1<<ADTS1)|(1<<ADTS0)); //pusti prevod na porovnani A0
	DIDR0 = 0x3F; //vypne digitalni  buffery na AD vstupech >> uspora energie

//	ADCSRA |= (1<<ADSC); //pusti prevod

}

void iniPoResetu()
{
	cli();
	iniCPU();
	iniPort();
	iniGlobVariables();
	iniAdc();

	iniCount0();
	iniCount1 ();
	iniPcint();
	sei();

}


[editovat] ADmonitorovani.c - Měření odporu AD převodníkem

Mereni odporu

#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/io.h> 
#include <stdio.h>
#include <math.h> 

#include <stdlib.h>

//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych





ISR (ADC_vect)
{
	ADhonota  = (uint8_t)ADCH;
	
	if(ADhonota > MEZ_HORNI) 
	{
		zmacknuto[ADtl]=0; //napeti nebylo stazeno dotykem prstu
	}
	else if(ADhonota < MEZ_DOLNI) zmacknuto[ADtl]=1; //napeti bylo stazeno dotykem prstu

	ADtl++;
	if (ADtl > 5) ADtl = 0 ; //posune ukazatel pro dalsi mereni
	
	ADMUX &= 0xF0; //spodni bity nastavi na nulu
	ADMUX |= ADtl ;	// nastavi vstup ad prevodniku pro nove mereni
	
	
}


[editovat] obsluhaTlacitka.c - Vyhodnoceni stavu talcitek

V této části programu se analyzují data naměřená AD převodníkem.

#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/io.h> 
#include <stdio.h>


#include <stdlib.h>

//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych




void obsluhaTlacitka(uint8_t cTL )
{
	cli();
	if ((zmacknuto[cTL]==0) && (zmacknutoMinule[cTL]==0)) //tl nezmacktnuto a minule taky ne > 
	{
		sei();
		regBlokace &= ~(1<<cTL); //potvrdi odblokovani v registru
		if ((regBlokace == 0)) 	PORTD |= (1<<PIN_TX); //niko neblokuje > prestane stahovat sbernici

		if (adresaZpozdenehoVypnuti != cTL) //pokud tohle tlacitko neni sepnute se zpozdenim, vypni jeho okruh
		{
			PORTD |= (1<<(cTL+2)); //rozepne tento okruh
		}
	}
	
	
	
	else if ((zmacknuto[cTL]>=1) && (zmacknutoMinule[cTL]>=1)) //tl zmacktnuto a minule taky  > 
	{
		PORTD &= ~(1<<PIN_TX); //potvrdi signal blokace na sbernici - zatahen za sbernici
		PORTD &= ~(1<<(cTL+2)); //potvrdi sepnuti tohoto okruhu
		sei();
		regBlokace |= (1<<cTL); //potvrdi blokaci v registru
		
	}
	
	
	
	else if ((zmacknuto[cTL]>=1) && (zmacknutoMinule[cTL]==0)) //tl zmacktnuto ale minule nebylo > nabezna hrana
	{
		zmacknutoMinule[cTL] = zmacknuto[cTL]; // ulozi stav tlacitka
		PORTD &= ~(1<<PIN_TX); //vysle signal blokace na sbernici
		PORTD &= ~(1<<(cTL+2)); //sepne tento okruh (pri stisku je vzdy okruh sepnuty)
		sei();
		regBlokace |= (1<<cTL); //zablokuje v registru 
						
	}
	
	
	//tl nezmacktnuto ale minule bylo > spadova hrana
	else if ((zmacknuto[cTL]>=0) && (zmacknutoMinule[cTL]==1)) 
	{
		zmacknutoMinule[cTL] = zmacknuto[cTL]; // ulozi stav tlacitka
		sei();
		regBlokace &= ~(1<<cTL); //odblokuje svoji blokaci v registru 
		
		if ((regBlokace == 0)) //kdyz zadne jine tlacitko neblokuje
		{
			cli();
			PORTD |= (1<<PIN_TX); //prestane stahovat sbernici
			sei();
			for (int i=0;i<1000;i++ ); //pocka na regeneraci sbernice 
			
			if ((PIND & (1<<PIN_RX)) == 0 ) //kdyz nikdo sbernici nestahuje
			{
				//pusti casovac	zpozdeneho vypnuti
				cli();
				TCNT1 = 0x0000; //vynuluje citaci registr
				TCCR1B |= ((1<<CS12)|(0<<CS11)|(1<<CS10) ); //pusti citac 1 - delicka 1024
				sei();
				adresaZpozdenehoVypnuti = cTL; //musi vedet, ktere tlacitko ma po dobehnuti vypnout
			}
			else // sbernici nekdo stahuje -> musi se vypnout okruh tohoto TL
			{
				cli();
				PORTD |= (1<<(cTL+2)); //rozepne tento okruh
				sei();
			}
		}
		else // jine tlacitko blokuje -> musi se vypnout okruh tohoto TL
		{
			cli();
			PORTD |= (1<<(cTL+2)); //rozepne tento okruh
			sei();
		}	


	}
}


[editovat] intKomp1A.c - Přerušení čítače 1

Čítač 1 slouží k odpočtu doby, po kterou svítí aktivovaný osvětlovací okruh modelu.

#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/io.h> 
#include <stdio.h>
// #include <util/delay.h>

#include <stdlib.h>

//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych





ISR (TIMER1_COMPA_vect)
{
	
	TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10) ); //zastavi citac 1
	
	if (zmacknuto[adresaZpozdenehoVypnuti] == 0) //kdyz tlacitko co se melo vypnout nikdo znova nezmackl...
	{
		PORTD |= (1<<(adresaZpozdenehoVypnuti+2)); //rozepne prislusny okruh

	}
}


[editovat] intBlokace.c - Přerušení na změnu na blokovací sběrnici

Pokud je v jiném modulu aktivován okruh, prostřednictvím sběrnice je dáno ostatním modulům na vědomí, že mají vypnout rodloužené svícení okruhu.

#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/io.h> 
#include <stdio.h>
// #include <util/delay.h>

#include <stdlib.h>

//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych




ISR (PCINT2_vect)
{
	if ((PIND & (1<<PIN_RX)) == 1 ) //kdyz nekdo sbernici stahne
	{
		TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10) ); //zastavi citac 1 odpocitavajici zozdene vypnuti
	
		if (zmacknuto[adresaZpozdenehoVypnuti] == 0) //kdyz tlacitko co se melo vypnout ted nikdo nemacka
		{
			PORTD |= (1<<(adresaZpozdenehoVypnuti+2)); //rozepne prislusny okruh

		}

	}

}


[editovat] intComp0A.c - Přerušní čítače 0

Toto přerušení slouží pouze k aktivaci nového AD převodu.

#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/io.h> 
#include <stdio.h>
// #include <util/delay.h>

#include <stdlib.h>

//definice pro preprocesor
#include "definice.h" //definice kmitoctu procesoru atd.


//deklarace (pro praci s prom. ktere jsou definovany jinde)
#include "globVariablesDeklarace.h" //deklarace globalnich promenych






ISR (TIMER0_COMPA_vect)
{
	//timto prerusenim se pouze automaticky zpusti ADprevod
	//mozna lze program upravit tak, aby nemuselo nastat

}


[editovat] globVariables.c - Definice globálních proměných

Zde jsou definovány používané globální proměné.

/********************
GLOBALNI PROMENNE
	-obsahuje globalni promene
********************/

#include <inttypes.h>
#include <avr/eeprom.h>
#include <stdint.h>


	/*******************
	PROMENE MERENI
	*******************/
	uint8_t ADhonota; // ulozi hodnotu ad prevodu
	uint8_t zmacknuto[6];  //obsahuje hodnoty aktualni zmacknuto/nezmacknuto
	uint8_t zmacknutoMinule[6]; // obsahuje hodnoty zmacknuto pri posledni kontrole
	
	uint8_t ADi;
	uint8_t ADtl;
	
	/*******************
	PROMENE BLOKOVANI
	*******************/
	uint8_t regBlokace; // vyznam bitu: 	regBlokace.0 = 1/0 -> tlacitko0 blokovano/neblokovano ...
										//  	regBlokace.1 = 1/0 -> tlacitko1 blokovano/neblokovano ...

	uint8_t adresaZpozdenehoVypnuti;





[editovat] definice.h - Definice konstant

Hlavičkový soubor

/********

*********DEFINICE**********
	-obsahuje definice 
	
*********/

	/******
	definice mereni
	*******/

	#define POCET_TLACITEK 6

	#define MEZ_HORNI (250)
	#define MEZ_DOLNI (240)

	

	/******
	definice pinu
	*******/
	#define PIN_TX 1
	#define PIN_RX 0

	#define DELICKA_COUNT_0 (0x02) //jak se ma nastavit delicka pro citac0 (generuje mereni)

	/******
	definice casu
	*******/
	#define DELKA_SVITU 1 // v sekundach
	#define DELKA_SVITU_PREPOCTENO (DELKA_SVITU * 976)








[editovat] globVariablesDeklarace.c - Deklarace globálních proměných

Hlavičkový soubor

/*********
DEKLARACE GLOBALNICH PROMENNYCH
	-musi byt obsazeno ve vsech souborech kde se s promnenymi pracuje
	-deklarace jen rika ze nekde takova promenna existuje
*********/

	/*******************
	PROMENE MERENI
	*******************/
	extern uint8_t ADhonota; // ulozi hodnotu ad prevodu
	extern uint8_t zmacknuto[6];  //obsahuje hodnoty aktualni zmacknuto/nezmacknuto
	extern uint8_t zmacknutoMinule[6]; // obsahuje hodnoty zmacknuto pri posledni kontrole
	
	extern uint8_t ADi;
	extern uint8_t ADtl;

	/*******************
	PROMENE SPINANI
	*******************/
	extern uint8_t regBlokace; 
		//vyznam bitu v regBlokace:
			//regBlokace.0 = 1/0 -> tlacitko0 blokovano/neblokovano ...
			//regBlokace.1 = 1/0 -> tlacitko1 blokovano/neblokovano ...
	extern uint8_t adresaZpozdenehoVypnuti;




[editovat] Plošný spoj

Návrh plošného spoje. Plošný spoj byl navrhnut v návrhovém programu Eagle.


[editovat] Celkový pohled

Schéma zapojení


[editovat] Celkový pohled

Schéma zapojení


[editovat] Celkový pohled

Schéma zapojení
Osobní nástroje