Uživatel:Vicarpet

Z MAM wiki

(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
Řádka 85: Řádka 85:
#include <avr/eeprom.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <util/delay.h>
 +
 +
#define xtal 1000000 //kmitocet krystalu 1MHz
 +
 +
#define TMR_CNT 65536 - 97 // cas / 1024 / 1000000, cas v sec, pro 0.1 sec
 +
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
int kteryudaj=0;//stara se o vyber udaje co bude zobrazen
+
unsigned char kteryudaj = 0;//stara se o vyber udaje co bude zobrazen (0..teplota)
-
volatile int iTemperature = 20; // Zmerena teplota  
+
volatile int teplota = 20; // Zmerena teplota  
volatile int Tnastavena = 20; //Nastavena teplota
volatile int Tnastavena = 20; //Nastavena teplota
-
const int Kzahrivani = 0;////Kzahrivani - (0-chladi,1-zahryva)- nastavuje zda ovladany prvek snizuje nebo zvysuje teplotu
 
-
const int N=1;//n - pocet urovni intenzity aktivity prvku (napriklad vetrak sepnut pomoci pcm 0-9 pulzu z doby 9->n=10)
 
-
const int K=1;//K - odchylka o jeden stupen zpusoby zapnuti na uroven 1*K (v pripade o n stupnu udela n*K az do hodnoty n)
 
-
void nastav (int kolik){
 
-
 
-
DDRB=0xFF;
 
-
 
-
while(1){
 
-
PORTB=8;
 
-
_delay_ms(kolik);
 
-
PORTB=0;
 
-
_delay_ms(N-kolik);
 
-
}
 
-
}
 
void UpdateOutput();
void UpdateOutput();
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
//vypne preruseni do te doby nez bude zavolana funkce void event_EnableIRQ (void)
+
void usni(void)
-
//zatim nevyzkouseno
+
-
void event_DisableIRQ (void)
+
{
{
-
// __asm {
+
SMCR = 1;
-
//  MRS r1, CPSR
+
-
//  ORR r1, r1, #0x80
+
-
//  MSR CPSR_c, r1
+
-
// }
+
}
}
-
//------------------------------------------------------------------------------
 
-
//znovuzapne preruseni
 
-
//zatim nevyzkouseno
 
-
void event_EnableIRQ (void)
 
-
{
 
-
sei();
 
-
}
 
 +
void preruseni (void)
 +
{ //jen osetruji aby jsme nepodtekli/nepretekli
 +
unsigned char portVal = PINC;
-
//------------------------------------------------------------------------------
+
do {
-
//zobrazi na display cislo
+
portVal = PINC & 0x30;
-
void zobraz(int cislo)
+
_delay_ms(20);
-
{
+
} while(portVal != (PINC & 0x30));
-
event_DisableIRQ();  
+
     
 +
if((portVal & 0x30) == 0x20)
 +
{
 +
//prvni
 +
Tnastavena++;
 +
kteryudaj = 10;
 +
}
 +
if((portVal & 0x30) == 0x10)
 +
{
 +
//druhy
 +
Tnastavena--;
 +
kteryudaj = 10;
 +
}
 +
}
-
DDRD=0xFF;
 
-
DDRC=0xFB;
 
-
//port D jako out - dopsat
 
-
//cast portu c 2,3 taky
 
-
//prvni cislo
 
-
PORTD=55;//(cislo%10);
 
-
_delay_ms(1);
 
-
PORTC=PORTC|0x03;
 
-
_delay_ms(1);
 
-
PORTC=PORTC&0xFB;
 
-
_delay_ms(1);
 
-
//druhy cislo
 
-
PORTD=(cislo-cislo%10)/10;
 
-
_delay_ms(1);
 
-
PORTC=PORTC|0x02;
 
-
_delay_ms(1);
 
-
PORTC=PORTC&0xFD;
 
-
_delay_ms(1);
 
-
event_EnableIRQ();
 
-
}
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
void usni(void)
+
//hlavni cast, nastavy procesor a uspi ho
-
{
+
void ShowDisplay(unsigned char num)
-
//doplnit
+
{
-
}
+
PORTD = (PORTD & 0xF0) | (num / 10);
-
 
+
PORTC = PORTC | 0x02;
-
 
+
_delay_ms(1);
-
void preruseni (void)
+
PORTC = PORTC & 0xFD;
-
{ //jen osetruji aby jsme nepodtekli/nepretekli
+
-
      event_DisableIRQ();
+
-
     
+
-
      _delay_ms(20);  
+
-
        if(PIND2==0&&iTemperature!=100)iTemperature++;
+
-
        if(PIND3==0&&iTemperature!=0)iTemperature--;
+
-
 
+
-
      event_EnableIRQ();
+
-
      zobraz(Tnastavena);
+
-
  }
+
 +
PORTD = (PORTD & 0xF0) | (num % 10);
 +
PORTC = PORTC | 0x08;
 +
_delay_ms(1);
 +
PORTC = PORTC & 0xF7;
 +
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
SIGNAL (ADC_vect)
+
int PrectiAdc()
{
{
 +
while((ADCSRA & (1 << ADIF)) == 0);
         int iAdcValue = ADCW;
         int iAdcValue = ADCW;
-
        iTemperature = (iAdcValue * 28) >> 8;
+
return((iAdcValue * 28) >> 8);
-
        UpdateOutput();
+
-
      if(kteryudaj++==0)
+
-
        zobraz(Tnastavena);
+
-
      else
+
-
      { 
+
-
        kteryudaj=0;
+
-
        zobraz(iTemperature);
+
-
      }
+
-
        usni();
+
}
}
-
 
+
//------------------------------------------------------------------------------
-
SIGNAL(INT12_vect)
+
SIGNAL(PCINT1_vect)
{
{
-
preruseni();  
+
preruseni();  
}
}
-
SIGNAL(INT13_vect)
+
//------------------------------------------------------------------------------
 +
SIGNAL(TIMER1_OVF_vect)
{
{
-
preruseni();  
+
teplota = PrectiAdc();
 +
if(kteryudaj > 0)
 +
{
 +
ShowDisplay(Tnastavena);
 +
kteryudaj--;
 +
}
 +
else
 +
ShowDisplay(teplota);
 +
 +
UpdateOutput();
 +
 
 +
TCNT1 = TMR_CNT;
 +
 +
// uspani
 +
usni();
}
}
-
//SIGNAL(TIMER1_OVF_vect)
 
-
//{
 
-
//      zmer();
 
-
//    UpdateOutput();
 
-
//    if(kteryudaj++==0)
 
-
  //      zobraz(Tnastavena);
 
-
  //  else
 
-
    //  { 
 
-
    //    kteryudaj=0;
 
-
    //    zobraz(iTemperature);
 
-
    //  }
 
-
//        usni();
 
-
//}
 
-
 
-
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void InitAdc()
void InitAdc()
{
{
-
 
+
    ADMUX = (1 << REFS1) | (1 << REFS0) | 2; // Reference 1.1V, kanal ADC2
-
        ADMUX = (1 << REFS1) | (1 << REFS0) | 2; // Reference 1.1V, kanal ADC2
+
    ADCSRA = (1 << ADEN) | (1 << ADATE) | 7; // Povoleni ADC, preddelicka 128
-
        ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | 7; // Povoleni ADC, preddelicka 128
+
    ADCSRB = 6; // start pri preteceni T1
-
        ADCSRB = 0;
+
-
 
+
-
   
+
-
PCMSK2 |= (1<<PINC4);
+
-
//GIMSK |= (1<<INT12); 
+
-
//MCUCR |= (1<<ISC01) | (1<<ISC00); 
+
-
//EIMSK |= (1<<INT0);
+
-
//      PCMSK |= (1<<PINC5)
+
-
    // interrupt on INTxx pin falling edge (sensor triggered)
+
-
  // GIMSK |= (1<<INT12);// MCUCR = (1<<ISC12) | (1<<ISC00);
+
-
//    MCUCR = (1<<ISC13) | (1<<ISC00);
+
-
    // turn on interrupts!
+
-
  //  GIMSK  |= (1<<INT12);
+
-
//              GIMSK  |= (1<<INT13);
+
-
 
+
-
 
+
-
 
+
-
        //dopsat nastaveni casovace
+
-
        //a portu
+
-
                //dopsat nastavenivystupu
+
-
        DDRB = (1 << 2); // PB2 jako vystup
+
-
        PORTB = 0;
+
-
 
+
-
        sei(); //povoli vsechnz preruseni
+
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
void nastavuroven(int jaka)
+
void UpdateOutput()
{
{
-
//dopsat nastaveni pcm vystupu
+
if(teplota > Tnastavena)
-
 
+
PORTD = (PORTD & 0x7F) | 0x80;
 +
if(teplota < Tnastavena - 10)
 +
PORTD = PORTD & 0x7f;
}
}
 +
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
void UpdateOutput()
+
void InitPorts()
{
{
-
//Kzahrivani - (0-chladi,1-zahryva)- nastavuje zda ovladany prvek snizuje nebo zvysuje teplotu
+
DDRD = 0x8F;
-
//n - pocet urovni intenzity aktivity prvku (napriklad vetrak sepnut pomoci pcm 0-9 pulzu z doby 9->n=10)
+
DDRC = 0x0A;
-
//K - odchylka o jeden stupen zpusoby zapnuti na uroven 1*K (v pripade o n stupnu udela n*K az do hodnoty n)
+
-
//Tnastavena - udrzovana teplota
+
-
//Treal - zmerena teplota
+
-
//funkce nastavuroven - nastavi uroven predanou v parametru 0-vypnuto, N-1 maximalni vykon
+
-
int deltaT=(iTemperature-Tnastavena)*(-1)^Kzahrivani;
+
PCICR = 0x02;
-
if(deltaT>0)
+
PCMSK1 = 0x30;
-
{
+
}
-
  int uroven_chlazeni_tmp=deltaT*K;
+
//------------------------------------------------------------------------------
-
  if(uroven_chlazeni_tmp>N-1)
+
void InitTimer1()
-
  {
+
{
-
    uroven_chlazeni_tmp=N-1;
+
TCCR1A = 0;
-
  }
+
TCCR1B = 5; // delicka 1024
-
  nastavuroven(uroven_chlazeni_tmp);
+
TCCR1C = 0;
-
}
+
TCNT1 = TMR_CNT;
-
else
+
TIMSK1 = 1; // povoleni preruseni od preteceni
-
{
+
-
  nastavuroven(0);//(vypnuto)
+
-
}
+
-
 
+
-
 
+
-
//     if(iTemperature >= iHighTemp)
+
-
        //      PORTB = PORTB | (1 << 2);
+
-
//      if(iTemperature < iLowTemp)
+
-
        //      PORTB = PORTB & ~(1 << 2);
+
}
}
-
 
-
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-
//hlavni cast, nastavy procesor a uspi ho
 
int main()
int main()
{
{
-
        InitAdc();
+
InitPorts();
-
        UpdateOutput();
+
    InitAdc();
-
         usni();
+
         InitTimer1();
-
//      for(;;);//yatyim neni usinani
+
sei();
-
zobraz(10);
+
 
-
_delay_ms(2000);
+
 
-
zobraz(88);
+
while(1);   //nekonecna smycka, aby neskoncil main
-
_delay_ms(2000);
+
    return (0);
-
        nastav(N);
+
-
        return (0);
+
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
 +
</pre>
 +
=== Datasheets ===
-
 
+
Teploměr LM-35
-
</pre>
+
BCD převodník HCF4056BE
 +
Sedmisegmentovky HDSP-F203
== Tým ==
== Tým ==

Verze z 12. 5. 2010, 13:54

petr vičar


Obsah

vybrana semestralni prace:

- možnost kalibrace na lokálni teplotu


Ovládání ventilátoru teplovzdušného rozvodu

Myslenka: k mikroprocesoru pripojen dvojmistny sedmisegmentovy displey - zobrazuje stridave nastavenou teplotu vs. teplotu skutecnou pomoci dvou tlacitek regulace nastavene teploty vetrak spinan tranzistorem mereni teploty: nejspise zdroj referencniho napeti + delic termistor, resistor(mozna vymyslim i neco presnejsiho) pri prekladu definovana konstanta tolerance k odchylkam(pri odchylce 1 stupen chladit na 0%...100% vykonnu vetraku)

nejaky zakladni nastrel, viz schema (schema je priblizne, popisuje myslenku, ne presne zapojeni, to budu muset upravit podle dostupnych soucastek) schema 3,3V bude realizovano nejspise stabilizatorem zakmity od tlacitek reseny softwarove zdrojak do Eagle



Ukoly

funkce void nastav(int uroven)
nastavi uroven 0 az N-1 na pcm vystupu (zaklady na jednom cviceni)

zjisteni teploty - precteni hodnoty z A/D prevodniku+nejaka korekce
int zjistiteplotu()
<b>korekci zdiskutovat</b>

probouzeni
jednoduse jednou za x ms + pri stisku tlacitka

ovladani tlacitkama
inkrementace/dekrementace nejake hodnoty, bacha na zakmity, (asi udelam ja)
void xyz () // edituje promenou nastavena teplota

funkce zobrazeni teploty
prevod binarni cislo na dve binarni hodnoty (mod,div) a zobrazeni
void zobrazteplotu(int)

Zakmity

Proste tlačítko neudelá normální prechod 0-1, ale párkrát zakmitá, takze se objevi cca neco takovýdleho ..01000110010001111111... Vyresíme jednoduse, pokud prijde interup pockame cca 20ms a pak teprve prectem hodnotu, jde to resit i hw, ale tohle je jednodussí.

--Jiří Zikmund 9. 5. 2010, 14:48 (UTC)

Obávám se, že nikdo nezaručí, že za 20ms tam bude určitě tutová 0. Co takhle to řešit prvním přečtením, pak 20ms počkat a znova přečíst, porovnat a když to bude stejný, tak je to OK a pokračujem dál? Ale to je jen takovej nápad. Jestliže bude vstupem třeba PD.2 viz schéma, zkusil bych jít třeba tudy:

no zaruci, tak spatny tlacitka aby to kmitalo dele nez 20ms sem snad mit nebudeme :)

První nástřely tlačítek v C

- jsou to dvě tlačítka, jedno má teplotu o stupeň snížit a druhé zvýšit, porty jsou podle schématu

Měření teploty

Tady bych se přikláněl k měření přes A/D převodník s teploměrem LM35

Řeší problém kalibrace (vnitřní kompenzací teploty) sám o sobě (dokonce je kalibrován na °C, má velmi malou spotřebu, rozlišení 10mV/°C), tak uvidíme, jak se k tomu vyjádří případně vedoucí cvičení. Pouzdro asi ještě doladíme, zatím LM35DZ v TO-92 (pakliže nebude třeba měřit záporné teploty), vychází nejlevněji.

Jiří Zikmund 19. 4. 2010, 17:16 (UTC)

--Jiří Zikmund 9. 5. 2010, 14:48 (UTC)

Takže měření teploty... použijeme vnitřní 10-bitový A/D převodník s vnitřním referenčním napětím 1,1V, vstup ADC2, výstup PB2



Kód

//------------------------------------------------------------------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>

#define xtal 1000000 //kmitocet krystalu 1MHz

#define TMR_CNT 65536 - 97 // cas / 1024 / 1000000, cas v sec, pro 0.1 sec


//------------------------------------------------------------------------------
unsigned char kteryudaj = 0;//stara se o vyber udaje co bude zobrazen (0..teplota)
volatile int teplota = 20; // Zmerena teplota 
volatile int Tnastavena = 20; //Nastavena teplota


void UpdateOutput();
//------------------------------------------------------------------------------
void usni(void)
{
	SMCR = 1;
}


void preruseni (void)
{ //jen osetruji aby jsme nepodtekli/nepretekli
	unsigned char portVal = PINC;

	do {
		portVal = PINC & 0x30;
		_delay_ms(20);
	} while(portVal != (PINC & 0x30));
       
	if((portVal & 0x30) == 0x20)
	{
		//prvni
		Tnastavena++;
		kteryudaj = 10;
	}
	if((portVal & 0x30) == 0x10)
	{
		//druhy
		Tnastavena--;
		kteryudaj = 10;
	}
} 


//------------------------------------------------------------------------------
//hlavni cast, nastavy procesor a uspi ho
void ShowDisplay(unsigned char num)
{
	PORTD = (PORTD & 0xF0) | (num / 10);
	PORTC = PORTC | 0x02;
	_delay_ms(1);
	PORTC = PORTC & 0xFD;

	PORTD = (PORTD & 0xF0) | (num % 10);
	PORTC = PORTC | 0x08;
	_delay_ms(1);
	PORTC = PORTC & 0xF7;

}
//------------------------------------------------------------------------------
int PrectiAdc()
{
		while((ADCSRA & (1 << ADIF)) == 0);
        int iAdcValue = ADCW;
		return((iAdcValue * 28) >> 8);
}
//------------------------------------------------------------------------------
SIGNAL(PCINT1_vect)
{
	preruseni(); 
}
//------------------------------------------------------------------------------
SIGNAL(TIMER1_OVF_vect)
{
	teplota = PrectiAdc();
	if(kteryudaj > 0)
	{
		ShowDisplay(Tnastavena);
		kteryudaj--;
	}
	else
		ShowDisplay(teplota);
	
	UpdateOutput();

	TCNT1 = TMR_CNT;
	
	// uspani
	usni();
}
//------------------------------------------------------------------------------
void InitAdc()
{
    ADMUX = (1 << REFS1) | (1 << REFS0) | 2; // Reference 1.1V, kanal ADC2
    ADCSRA = (1 << ADEN) | (1 << ADATE) | 7; // Povoleni ADC, preddelicka 128
    ADCSRB = 6; // start pri preteceni T1
}


//------------------------------------------------------------------------------
void UpdateOutput()
{
	if(teplota > Tnastavena)
		PORTD = (PORTD & 0x7F) | 0x80;
	if(teplota < Tnastavena - 10)
		PORTD = PORTD & 0x7f; 
}



//------------------------------------------------------------------------------
void InitPorts()
{
	DDRD = 0x8F;
	DDRC = 0x0A;

	PCICR = 0x02;
	PCMSK1 = 0x30;
}
//------------------------------------------------------------------------------
void InitTimer1()
{
	TCCR1A = 0;
	TCCR1B = 5; // delicka 1024
	TCCR1C = 0;
	TCNT1 = TMR_CNT;
	TIMSK1 = 1; // povoleni preruseni od preteceni
}
//------------------------------------------------------------------------------
int main()
{
	InitPorts();
    InitAdc();
        InitTimer1();
	sei();


 	while(1);   //nekonecna smycka, aby neskoncil main
    return (0);
}
//------------------------------------------------------------------------------

Datasheets

Teploměr LM-35 BCD převodník HCF4056BE Sedmisegmentovky HDSP-F203

Tým

Petr Vičar
Jachym Simak - simakjac@fel.cvut.cz
Jiří Zikmund
Osobní nástroje