Operácie

Diaľkové ovládanie zosilňovača: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
(24 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 6: Riadok 6:
Zapojiť a naprogramovať IR diaľkové ovládanie s Atmega328P pre ovládanie tlačidiel vypínania a Loudness a potenciometra hlasitosti zosilňovača.
Zapojiť a naprogramovať IR diaľkové ovládanie s Atmega328P pre ovládanie tlačidiel vypínania a Loudness a potenciometra hlasitosti zosilňovača.


[[Obrázok:600px-UNO.jpg|400px|thumb|center|Vývojová doska Arduino UNO.]]
[[Obrázok:600px-UNO.jpg|400px|thumb|center|Vývojová doska Arduino UNO]]


'''Literatúra:'''  
'''Literatúra:'''  
* [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf Dokumentácia k Atmega328P]
* [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf Dokumentácia k Atmega328P]
* [https://sibotic.wordpress.com/wp-content/uploads/2013/12/adoh-necinfraredtransmissionprotocol-281113-1713-47344.pdf Dokumentácia k Protokolu NEC]




Riadok 17: Riadok 18:


Správu odvysielanú IR diaľkovým ovládačom bolo treba nejakým zariadením prijať, spracovať v mikropočítači a na základe prijatej správy aktivovať solenoid, ktorý zatlačí tlačidlo na zosilňovači alebo pootočiť servomotorček ovládajúci potenciometer hlasitosti.  
Správu odvysielanú IR diaľkovým ovládačom bolo treba nejakým zariadením prijať, spracovať v mikropočítači a na základe prijatej správy aktivovať solenoid, ktorý zatlačí tlačidlo na zosilňovači alebo pootočiť servomotorček ovládajúci potenciometer hlasitosti.  
=== Postup riešenia ===
====• Vysielanie správ====
====• Vysielanie správ====
Správy odosielame pomocou IR ďiaľkového ovládania ktoré sa bežne používa s Arduinom.
Správy odosielame pomocou IR diaľkového ovládania, ktoré sa bežne používa s Arduinom.
[[Obrázok:ovladac.jpg|200px|thumb|center|IR Diaľkový ovládač]]
[[Obrázok:ovladac.jpg|200px|thumb|center|IR Diaľkový ovládač]]
====• Prijímanie správ====
====• Prijímanie správ====
Riadok 24: Riadok 26:
[[Obrázok:prijimac.jpg|100px|thumb|center|IR Prijímač]]
[[Obrázok:prijimac.jpg|100px|thumb|center|IR Prijímač]]
====• Spracovanie prijatého signálu====
====• Spracovanie prijatého signálu====
Prijatý signál spracováva Arduino nižšie uvedeným programom. Po spracovaní signálu Arduino spína na pol sekundy digitálne piny 6 a 7 alebo pootočí servomotorček pomocou zmeny pwm signálu na pine 9.
Prijatý signál spracováva Arduino nižšie uvedeným programom. Po spracovaní signálu Arduino spína na pol sekundy digitálne piny 6 a 7 alebo pootočí servomotorček pomocou zmeny pwm signálu na pine 9. Signál vstupujúci do Arduina má zamenené logické jednotky a nuly kvôli použitému pull-up rezistoru, toto je kompenzované v programe pri vyhodnocovaní logických stavov prijímaného signálu.
 
 
=== Protokol nec ===
 
Pre rozšifrovanie správ bolo potrebné pochopiť ako funguje protokol nec ktorým ovládač posiela správy. Museli sme zistiť úvodnú správu a spôsob ktorým sú reprezentované logické jednotky a nuly. Najdôležitejšie bolo si uvedomiť, že rozdiel medzi logickou jednotkou a nulou je v dĺžke nulovej časti signálu, ktorá nasleduje kladnú časť. Rozdiel v logickej jednotke a nule je totiž v tom, že nulová časť je pri logickej jednotke tri krát dlhšia, ako pri logickej nule. Z nich sa následne skladá adresa zariadenia, špecifická pre výrobcu a niekedy aj model zariadenia a príkaz určujúci vybranú funkciu na ovládači. V rýchlosti doplním len že v nec protokole je konštantná dĺžka správy realizovaná vďaka dvojnému odosielaniu adresy a príkazu v správe. Jedna z týchto adries a príkazov vždy obsahuje pôvodnú správu s invertovanými bitmy. Vďaka tomu je počet logických jednotiek a núl v správe vždy rovnaký a mení sa iba ich poradie, preto je správa vždy rovnako dlhá. Polovica bitov teda pre určenie stlačeného tlačidla nie je potrebná, preto sme museli z celej správy vyselektovať 32-25 a 16-9 bity.
 
[[Súbor:NecProtokol.PNG|600px|thumb|center|Správa protokolu nec]]
 
 


=== Schéma zapojenia ===
=== Schéma zapojenia ===


[[Súbor:GeminiAI-image2.jpg|400px|thumb|center|Schéma zapojenia.]]
[[Súbor:SchemaIROvladanie.PNG|400px|thumb|center|Schéma zapojenia]]




=== Algoritmus a program ===
=== Algoritmus a program ===


Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto...  
Celý program je napísaný v jednom súbore bez použitia vlastných funkcií a knižníc. Ako prvé sme si pridali knižnice a funkcie a zadefinovali vstupné a výstupné piny. Pridali sme si funkciu delay. Následne sme si definovali premenné a inicializovali počítadlo. Prvá polovica programu v maine nám rozšifruje správu zaslanú ovládačom cez protokol nec. Táto časť programu rozlíši poslané logické jednotky a nuly a prevedie ich na hexadecimálny kód. V ďalšej časti programu sa tento kód porovnáva so známymi kódmi priradenými k funkciám. Ak sa prijatý kód zhoduje s kódom funkcie, funkcia sa vykoná. Keďže 8 bitové počítadlo nám nestačilo na čítanie kódu ani generovanie PWM, bolo potrebné počítadlo medzi týmito dvomi časťami programu prekonfigurovať. To sa deje na začiatku každej z daných častí programu. Rozhodli sme sa pre prácu s normalizovanými hexadecimálnymi kódmi diaľkových ovládačov a preto bolo potrebné prirátať k premennej count číslo 2.
Výpis kódu je nižšie...




<tabs>
<tabs>
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <math.h>


#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define IR1 PB0  // IR snimac
#define ZAP  PD7  // Vypinac
#define LOUD  PD6  // Loudness
#define VOL  PB1  // Volume
void delay(int delay)  // vlastna funkcia, lebo inak je max 16ms
{
  for (int i=1; i<=delay; i++)
  _delay_ms(1);
}
int main(void)
int main(void)
{
{  
  unsigned int measuredValue;
DDRB &= ~(1<<IR1);   // PB0 je vstup
 
DDRD |= (1<<ZAP); // PD7 je vystup
  while (1)
DDRD |= (1<<LOUD); // PD6 je vystup
   {
DDRB |=  (1<<VOL);  // PD5 je vystup
    /* relax */   
PORTB |= (1<<IR1);   // zapnuty pull-up
  }
 
  return(0);
}
 
</syntaxhighlight ></tab>
<tab name="filename.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#include <avr/io.h>


void adc_init(void);                                   // A/D converter initialization
int counter,bit,count,poc=2000;  // deklaracia premennych a nastavenie pociatocnej polohy servomotorceka
unsigned int tlac;
    while(1)
    {
TCNT1 = 0x0000;          // initialize (CLEAR) counter
ICR1  = 0;            // nulovanie pre pouzitie ako casovac
OCR1A = 0;            // nulovanie pre pouzitie ako casovac
TCCR1A = 0b10000000;  // nastavenie akcie pri zhode pocitadla
TCCR1B = 0b00000010;  // nastavenie preddelicky na 8
        if (bit_is_clear(PINB, IR1))
{
TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS
while( ((TIFR1 & (1<<TOV1)) != 0x01 ) && (bit_is_clear(PINB, IR1)))  // cakaj kym neubehlo aspon 8,6mS v log. 1
{
}
while(bit_is_set(PINB, IR1)) // nastavenie pocitadla v pripade ze log. 1 nebola dlha aspon 8.6mS
{
TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS
}
if(((TIFR1 & (1<<TOV1)) == 0x01 )) // ak sa pocitadlo preklopilo
{
delay(2);
while(bit_is_set(PINB, IR1)) // cakaj na log. 0
{
}
bit=15; // nastavenie pre vypocet hexadecimalneho cisla
count=0;
for(int i=32;i>=0;i--)  // cyklus pre precitanie 32 bitov spravy
{
while(bit_is_clear(PINB, IR1)) // cakaj na log. 1
{
}
TCNT1 = 0x0000;      // nulovanie pocitadla pre zaciatok pocitania noveho bitu
while(bit_is_set(PINB, IR1)) // cakaj na log. 0
{
}
counter = TCNT1;
if((i<=31)&&(i>=24) || (i<=15)&&(i>=8))  // vyselektovanie dolezitych bitov spravy
{
if ((counter>=700)&&(counter<=1500))  // ak je log. 1...
count = count + pow(2,bit);      // ...prirataj 2 umocnene na poziciu daneho bitu
bit--;
}
}
tlac = count+2;    // kompenzacia pre pracu s normalizovanymi hexadecimalnymi kodmi dialkovych ovladacov
if (tlac == 65437)    //Kod tlacidla pre vypinanie
{
set_bit(PORTD,ZAP);
delay(500);
clear_bit(PORTD,ZAP);
}
if (tlac == 65391)    //Kod tlacidla pre loudness
{
set_bit(PORTD,LOUD);
delay(500);
clear_bit(PORTD,LOUD);
}
TCNT1 = 0;            // Set Initial Timer value
ICR1  = 4000;            // set TOP for counting 
TCCR1A = 0b10000010;      // nastavenie fast PWM a akcie pri zhode pocitadla
TCCR1B = 0b00011010;      // nastavenie fast PWM a preddelicky 8
if (tlac == 65367 && poc <3900)      //Kod tlacidla pre pridanie hlasitosti
  poc = poc+100;
if (tlac == 65311  && poc >2000)      //Kod tlacidla pre ubratie hlasitosti
  poc = poc-100;
OCR1A = poc; // zapis do casovaca pre generovanie PWM
delay(100);
}
 
}
}
}


unsigned int adc_read(char a_pin);
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
</tabs>
</tabs>


Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'':


Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]]
Zdrojový kód: [[Médiá:IR_Ovladanie_Zosilnovaca_David_Bungyi.zip|IR_Ovladanie_Zosilnovaca_David_Bungyi.zip]]


=== Overenie ===
=== Overenie ===


Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia.
Celé zariadenie sa ovláda štyrmi tlačidlami ovládača tlačidlá + a - ovládajú pohyb servomotorčeka a tlačidlá CH a EQ ovládajú solenoidy stláčajúce tlačidlá zosilňovača. Solenoidy sú v ukážke reprezentované LED diódami.
Na konci uvádzame fotku hotového zariadenia.  


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Súbor:ZapojenieIROvladanie.jpg|600px|thumb|center|Zapojenie zariadenia]]


'''Video:'''
'''Video:'''
<center><youtube>D0UnqGm_miA</youtube></center>
<center><youtube>cXLb0B8ZQKA</youtube></center>





Verzia z 20:28, 18. máj 2025

Záverečný projekt predmetu MIPS / LS2025 - Dávid Bungyi


Zadanie

Zapojiť a naprogramovať IR diaľkové ovládanie s Atmega328P pre ovládanie tlačidiel vypínania a Loudness a potenciometra hlasitosti zosilňovača.

Vývojová doska Arduino UNO

Literatúra:


Analýza a opis riešenia

Správu odvysielanú IR diaľkovým ovládačom bolo treba nejakým zariadením prijať, spracovať v mikropočítači a na základe prijatej správy aktivovať solenoid, ktorý zatlačí tlačidlo na zosilňovači alebo pootočiť servomotorček ovládajúci potenciometer hlasitosti.

Postup riešenia

• Vysielanie správ

Správy odosielame pomocou IR diaľkového ovládania, ktoré sa bežne používa s Arduinom.

IR Diaľkový ovládač

• Prijímanie správ

Signál odvysielaný ovládačom prijímame IR prijímačom, ktorý modulovaný 38KHz signál demoduluje a spracuje na logické jednotky a nuly.

IR Prijímač

• Spracovanie prijatého signálu

Prijatý signál spracováva Arduino nižšie uvedeným programom. Po spracovaní signálu Arduino spína na pol sekundy digitálne piny 6 a 7 alebo pootočí servomotorček pomocou zmeny pwm signálu na pine 9. Signál vstupujúci do Arduina má zamenené logické jednotky a nuly kvôli použitému pull-up rezistoru, toto je kompenzované v programe pri vyhodnocovaní logických stavov prijímaného signálu.


Protokol nec

Pre rozšifrovanie správ bolo potrebné pochopiť ako funguje protokol nec ktorým ovládač posiela správy. Museli sme zistiť úvodnú správu a spôsob ktorým sú reprezentované logické jednotky a nuly. Najdôležitejšie bolo si uvedomiť, že rozdiel medzi logickou jednotkou a nulou je v dĺžke nulovej časti signálu, ktorá nasleduje kladnú časť. Rozdiel v logickej jednotke a nule je totiž v tom, že nulová časť je pri logickej jednotke tri krát dlhšia, ako pri logickej nule. Z nich sa následne skladá adresa zariadenia, špecifická pre výrobcu a niekedy aj model zariadenia a príkaz určujúci vybranú funkciu na ovládači. V rýchlosti doplním len že v nec protokole je konštantná dĺžka správy realizovaná vďaka dvojnému odosielaniu adresy a príkazu v správe. Jedna z týchto adries a príkazov vždy obsahuje pôvodnú správu s invertovanými bitmy. Vďaka tomu je počet logických jednotiek a núl v správe vždy rovnaký a mení sa iba ich poradie, preto je správa vždy rovnako dlhá. Polovica bitov teda pre určenie stlačeného tlačidla nie je potrebná, preto sme museli z celej správy vyselektovať 32-25 a 16-9 bity.

Správa protokolu nec


Schéma zapojenia

Schéma zapojenia


Algoritmus a program

Celý program je napísaný v jednom súbore bez použitia vlastných funkcií a knižníc. Ako prvé sme si pridali knižnice a funkcie a zadefinovali vstupné a výstupné piny. Pridali sme si funkciu delay. Následne sme si definovali premenné a inicializovali počítadlo. Prvá polovica programu v maine nám rozšifruje správu zaslanú ovládačom cez protokol nec. Táto časť programu rozlíši poslané logické jednotky a nuly a prevedie ich na hexadecimálny kód. V ďalšej časti programu sa tento kód porovnáva so známymi kódmi priradenými k funkciám. Ak sa prijatý kód zhoduje s kódom funkcie, funkcia sa vykoná. Keďže 8 bitové počítadlo nám nestačilo na čítanie kódu ani generovanie PWM, bolo potrebné počítadlo medzi týmito dvomi časťami programu prekonfigurovať. To sa deje na začiatku každej z daných častí programu. Rozhodli sme sa pre prácu s normalizovanými hexadecimálnymi kódmi diaľkových ovládačov a preto bolo potrebné prirátať k premennej count číslo 2.


#define F_CPU 16000000UL

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <math.h>

#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

#define IR1 PB0  // IR snimac
#define ZAP  PD7  // Vypinac
#define LOUD  PD6  // Loudness
#define VOL  PB1  // Volume
 
void delay(int delay)   // vlastna funkcia, lebo inak je max 16ms
{
  for (int i=1; i<=delay; i++)
  _delay_ms(1);
}	
 
int main(void)
{ 
	DDRB &= ~(1<<IR1);   // PB0 je vstup
	DDRD |=  (1<<ZAP);  // PD7 je vystup
	DDRD |=  (1<<LOUD);  // PD6 je vystup
	DDRB |=  (1<<VOL);  // PD5 je vystup
	PORTB |= (1<<IR1);   // zapnuty pull-up

	int counter,bit,count,poc=2000;  // deklaracia premennych a nastavenie pociatocnej polohy servomotorceka
	unsigned int tlac;
    while(1)
    {
		TCNT1 = 0x0000;           // initialize (CLEAR) counter 
		ICR1  = 0;             // nulovanie pre pouzitie ako casovac 
		OCR1A = 0;             // nulovanie pre pouzitie ako casovac 
		TCCR1A = 0b10000000;  // nastavenie akcie pri zhode pocitadla
		TCCR1B = 0b00000010;  // nastavenie preddelicky na 8
        if (bit_is_clear(PINB, IR1)) 
		{
			TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS
			while( ((TIFR1 & (1<<TOV1)) != 0x01 ) && (bit_is_clear(PINB, IR1)))   // cakaj kym neubehlo aspon 8,6mS v log. 1
			{	 
			}
			while(bit_is_set(PINB, IR1)) // nastavenie pocitadla v pripade ze log. 1 nebola dlha aspon 8.6mS
			{
				TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS
			}
			if(((TIFR1 & (1<<TOV1)) == 0x01 )) // ak sa pocitadlo preklopilo
			{
					delay(2);
					while(bit_is_set(PINB, IR1)) // cakaj na log. 0
					{
					}
					bit=15; // nastavenie pre vypocet hexadecimalneho cisla
					count=0;
					for(int i=32;i>=0;i--)   // cyklus pre precitanie 32 bitov spravy
					{
						while(bit_is_clear(PINB, IR1)) // cakaj na log. 1
						{
						}
						TCNT1 = 0x0000;      // nulovanie pocitadla pre zaciatok pocitania noveho bitu
						while(bit_is_set(PINB, IR1)) // cakaj na log. 0
						{
						}
						counter = TCNT1;
											
						if((i<=31)&&(i>=24) || (i<=15)&&(i>=8))   // vyselektovanie dolezitych bitov spravy
						{
							if ((counter>=700)&&(counter<=1500))  // ak je log. 1...
								count = count + pow(2,bit);       // ...prirataj 2 umocnene na poziciu daneho bitu
							bit--;
						}
										
					}
					tlac = count+2;    // kompenzacia pre pracu s normalizovanymi hexadecimalnymi kodmi dialkovych ovladacov
					if (tlac == 65437)     //Kod tlacidla pre vypinanie
					{
 						set_bit(PORTD,ZAP);
						delay(500);
						clear_bit(PORTD,ZAP);
					}
					if (tlac == 65391)     //Kod tlacidla pre loudness
					{
 						set_bit(PORTD,LOUD);
						delay(500);
						clear_bit(PORTD,LOUD);
					}	
						
					TCNT1 = 0;             // Set Initial Timer value
					ICR1  = 4000;             // set TOP for counting  
					TCCR1A = 0b10000010;      // nastavenie fast PWM a akcie pri zhode pocitadla
					TCCR1B = 0b00011010;      // nastavenie fast PWM a preddelicky 8
					if (tlac == 65367 && poc <3900)       //Kod tlacidla pre pridanie hlasitosti
					   poc = poc+100;
					if (tlac == 65311  && poc >2000)      //Kod tlacidla pre ubratie hlasitosti
					   poc = poc-100;
					OCR1A = poc;		 // zapis do casovaca pre generovanie PWM
					delay(100);
				
			}
				   
		}
	}
}


Zdrojový kód: IR_Ovladanie_Zosilnovaca_David_Bungyi.zip

Overenie

Celé zariadenie sa ovláda štyrmi tlačidlami ovládača tlačidlá + a - ovládajú pohyb servomotorčeka a tlačidlá CH a EQ ovládajú solenoidy stláčajúce tlačidlá zosilňovača. Solenoidy sú v ukážke reprezentované LED diódami.

Zapojenie zariadenia

Video:



Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.