Diaľkové ovládanie zosilňovača: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
Bez shrnutí editace |
||
(11 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 19: | Riadok 20: | ||
=== Postup riešenia === | === Postup riešenia === | ||
====• Vysielanie správ==== | ====• Vysielanie správ==== | ||
Správy odosielame pomocou IR | 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 25: | 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: | [[Súbor:SchemaIROvladanie.PNG|400px|thumb|center|Schéma zapojenia]] | ||
=== Algoritmus a program === | === 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. | |||
Riadok 70: | Riadok 78: | ||
PORTB |= (1<<IR1); // zapnuty pull-up | PORTB |= (1<<IR1); // zapnuty pull-up | ||
int counter,bit,count,poc=2000; | int counter,bit,count,poc=2000; // deklaracia premennych a nastavenie pociatocnej polohy servomotorceka | ||
unsigned int tlac; | unsigned int tlac; | ||
while(1) | while(1) | ||
{ | { | ||
TCNT1 = 0x0000; // initialize (CLEAR) counter | TCNT1 = 0x0000; // initialize (CLEAR) counter | ||
ICR1 = 0; // | ICR1 = 0; // nulovanie pre pouzitie ako casovac | ||
OCR1A = 0; // | OCR1A = 0; // nulovanie pre pouzitie ako casovac | ||
TCCR1A = 0b10000000; | TCCR1A = 0b10000000; // nastavenie akcie pri zhode pocitadla | ||
TCCR1B = 0b00000010; | TCCR1B = 0b00000010; // nastavenie preddelicky na 8 | ||
if (bit_is_clear(PINB, IR1)) | if (bit_is_clear(PINB, IR1)) | ||
{ | { | ||
TCNT1 = 0xDE67; | TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS | ||
while( ((TIFR1 & (1<<TOV1)) != 0x01 ) && (bit_is_clear(PINB, IR1))) | 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)) | while(bit_is_set(PINB, IR1)) // nastavenie pocitadla v pripade ze log. 1 nebola dlha aspon 8.6mS | ||
{ | { | ||
TCNT1 = 0xDE67; | TCNT1 = 0xDE67; // nastavenie pocitadla aby doslo k preklopeniu po 8,6mS | ||
} | } | ||
if(((TIFR1 & (1<<TOV1)) == 0x01 )) | if(((TIFR1 & (1<<TOV1)) == 0x01 )) // ak sa pocitadlo preklopilo | ||
{ | { | ||
delay(2); | delay(2); | ||
while(bit_is_set(PINB, IR1)) | while(bit_is_set(PINB, IR1)) // cakaj na log. 0 | ||
{ | { | ||
} | } | ||
bit=15; | bit=15; // nastavenie pre vypocet hexadecimalneho cisla | ||
count=0; | count=0; | ||
for(int i=32;i>=0;i--) | for(int i=32;i>=0;i--) // cyklus pre precitanie 32 bitov spravy | ||
{ | { | ||
while(bit_is_clear(PINB, IR1)) | while(bit_is_clear(PINB, IR1)) // cakaj na log. 1 | ||
{ | { | ||
} | } | ||
TCNT1 = 0x0000; | TCNT1 = 0x0000; // nulovanie pocitadla pre zaciatok pocitania noveho bitu | ||
while(bit_is_set(PINB, IR1)) | while(bit_is_set(PINB, IR1)) // cakaj na log. 0 | ||
{ | { | ||
} | } | ||
counter = TCNT1; | counter = TCNT1; | ||
if((i<=31)&&(i>=24) || (i<=15)&&(i>=8)) | if((i<=31)&&(i>=24) || (i<=15)&&(i>=8)) // vyselektovanie dolezitych bitov spravy | ||
{ | { | ||
if ((counter>=700)&&(counter<=1500)) | if ((counter>=700)&&(counter<=1500)) // ak je log. 1... | ||
count = count + pow(2,bit); | count = count + pow(2,bit); // ...prirataj 2 umocnene na poziciu daneho bitu | ||
bit--; | bit--; | ||
} | } | ||
} | } | ||
tlac = count+2; | tlac = count+2; // kompenzacia pre pracu s normalizovanymi hexadecimalnymi kodmi dialkovych ovladacov | ||
if (tlac == 65437) // | if (tlac == 65437) //Kod tlacidla pre vypinanie | ||
{ | { | ||
set_bit(PORTD,ZAP); | set_bit(PORTD,ZAP); | ||
Riadok 123: | Riadok 131: | ||
clear_bit(PORTD,ZAP); | clear_bit(PORTD,ZAP); | ||
} | } | ||
if (tlac == 65391) // | if (tlac == 65391) //Kod tlacidla pre loudness | ||
{ | { | ||
set_bit(PORTD,LOUD); | set_bit(PORTD,LOUD); | ||
Riadok 132: | Riadok 140: | ||
TCNT1 = 0; // Set Initial Timer value | TCNT1 = 0; // Set Initial Timer value | ||
ICR1 = 4000; // set TOP for counting | ICR1 = 4000; // set TOP for counting | ||
TCCR1A = 0b10000010; | TCCR1A = 0b10000010; // nastavenie fast PWM a akcie pri zhode pocitadla | ||
TCCR1B = 0b00011010; | TCCR1B = 0b00011010; // nastavenie fast PWM a preddelicky 8 | ||
if (tlac == 65367 && poc <3900) // | if (tlac == 65367 && poc <3900) //Kod tlacidla pre pridanie hlasitosti | ||
poc = poc+100; | poc = poc+100; | ||
if (tlac == 65311 && poc >2000) | if (tlac == 65311 && poc >2000) //Kod tlacidla pre ubratie hlasitosti | ||
poc = poc-100; | poc = poc-100; | ||
OCR1A = poc; | OCR1A = poc; // zapis do casovaca pre generovanie PWM | ||
delay(100); | delay(100); | ||
Riadok 145: | Riadok 153: | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
Riadok 160: | Riadok 168: | ||
'''Video:''' | '''Video:''' | ||
<center><youtube> | <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.

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.

• 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.

• 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.
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.

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