Operácie

Diaľkové ovládanie zosilňovača

Zo stránky SensorWiki

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.