Dvojosová kolíska na kameru ovládaná joystickom: Rozdiel medzi revíziami
Z SensorWiki
(→Dvojosová kolíska na kameru ovládaná joystickom) |
(→Analýza a opis riešenia) |
||
(96 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 9: | Riadok 9: | ||
− | [[Obrázok: | + | [[Obrázok:Matsibora_a_Fietisov_koliska.jpg|440px|thumb|center|Model projekta.]] |
+ | |||
+ | == Zadanie == | ||
+ | Rozhodli sme sa naprogramovať držiak na kameru, ktorý by sa otáčal doľava a doprava a samotná kamera sa pohybovala vertikálne. V našom prípade pôjde o dva typy pohybu a dva programy: | ||
+ | |||
+ | 1.) keď servopohony nasledujú polohu joysticku a pohybujú sa, kým posúvame joystick. | ||
+ | |||
+ | 2.)servopohony pohybovať smerom, kam ukazuje joystick, a zostanú tam, kým opäť neposunieme páčku alebo nezmeníme smer. | ||
'''Literatúra:''' | '''Literatúra:''' | ||
Riadok 20: | Riadok 27: | ||
== Analýza a opis riešenia == | == Analýza a opis riešenia == | ||
− | Celý projekt obsahuje dosku Arduino, dvojosový joystick, | + | Celý projekt obsahuje dosku Arduino, dvojosový joystick, dva servá sg90, prepojovacie vodiče a samotný držiak kamery. |
Použitý joystik má 5 pinov (Vcc, GND, Xaxis, Yaxis a kolík tlačidla). Joystick má 2 centrované potenciometre, pri napájaní produkujú analógový signál a pri použití s Arduino má nasledujúce hodnoty: „0-1023“ a keďže sú v pohotovostnom režime vycentrované, vytvárajú hodnoty okolo „512“ a tlačidlo má digitálny výstup 0/1. | Použitý joystik má 5 pinov (Vcc, GND, Xaxis, Yaxis a kolík tlačidla). Joystick má 2 centrované potenciometre, pri napájaní produkujú analógový signál a pri použití s Arduino má nasledujúce hodnoty: „0-1023“ a keďže sú v pohotovostnom režime vycentrované, vytvárajú hodnoty okolo „512“ a tlačidlo má digitálny výstup 0/1. | ||
Riadok 26: | Riadok 33: | ||
Musíme byť opatrní s joystickom, pretože sú dosť lacné a môže fungovať iba jedna os, čo sa stalo v našom prípade. Na kontrolu osej sme použili terminal PuTTY. | Musíme byť opatrní s joystickom, pretože sú dosť lacné a môže fungovať iba jedna os, čo sa stalo v našom prípade. Na kontrolu osej sme použili terminal PuTTY. | ||
− | [[Súbor: | + | [[Súbor:Matsibora_a_Fietisov_joystik.jpg|450px|thumb|left|Joystik.]] |
+ | |||
+ | [[Súbor:Matsibora_a_Fietisov_hodnoty joystika.png|590px|thumb|center|schema Joystika.]] | ||
+ | |||
− | [[Súbor: | + | [[Súbor:Matsibora_a_Fietisov_servo a joystik.jpg|500px|thumb|center|Schéma zapojenia joystika k Arduino.]] |
Ďalej budeme hovoriť o servomotoroch. | Ďalej budeme hovoriť o servomotoroch. | ||
Servomotory majú tri vodiče: GND/VCC/signál, v tomto prípade je napájaný 5V z Arduina, môžme použiť 9V alebo 12V, ale najprv si prečítajme datasheet list servomotora, aby sme poznali podporované napätie. Externý zdroj napájania musí mať spoločnú zem. Mame take charakteristiky motorčekov: | Servomotory majú tri vodiče: GND/VCC/signál, v tomto prípade je napájaný 5V z Arduina, môžme použiť 9V alebo 12V, ale najprv si prečítajme datasheet list servomotora, aby sme poznali podporované napätie. Externý zdroj napájania musí mať spoločnú zem. Mame take charakteristiky motorčekov: | ||
− | Napätie: | + | Napätie: 3V ~ 7.2V |
− | Rýchlosť | + | Rýchlosť 0,12 s/60° |
− | + | Točivý moment (@ U=4,8V)1,2 kg.cm | |
+ | Točivý moment (@ U=6V) 1,6 kg.cm | ||
Uhol natočenia: 180° | Uhol natočenia: 180° | ||
− | Hmotnosť: | + | Hmotnosť: 14g |
− | Rozmery: | + | Rozmery(mm): 22 x 11,5 x 27 |
− | [[Súbor: | + | [[Súbor:sg90.png|420px|thumb|left|Servomotor.]] |
− | [[Súbor: | + | [[Súbor:рис51.png|450px|thumb|center|Schéma zapojenia joystika a servomotorov k Arduino.]] |
− | |||
+ | [[Súbor:ServoAnimation.gif|450px|thumb|center|Riadenie polohy servomotora pomocou dĺžky impulzu.]] | ||
+ | Servomotor je kombináciou DC motora, systému riadenia polohy, prevodov. Polohu hriadeľa DC motora nastavuje riadiaca elektronika v servo na základe duty ratio PWM signálu na pine SIGNAL. Jednoducho povedané, riadiaca elektronika nastavuje polohu hriadeľa ovládaním DC motora. Tieto údaje o polohe hriadeľa sa odosielajú cez pin SIGNAL. Údaje o polohe do riadenia by sa mali odosielať vo forme signálu PWM cez signálny pin servomotora.Generovanie PWM bolo riešené pomocou 16-bitového počítadla a časovača T1. | ||
+ | Potom pre Т1: režim Fast PWM. To, ktorý režim PWM chceme používať sa nastavuje bitmi WGM13...WGM10, ktoré sú rozdelené do registrov TCCR1A a TCCR1B. | ||
+ | [[Súbor:Matsibora_a_Fietisov_tabulka.png|450px|thumb|center|Tabulka.]] | ||
+ | Ďalej musíme vypočítať frekvenciu signálu, na to použijeme vzorec z datasheetu. | ||
+ | [[Súbor:Matsibora_a_Fietisov_vzorec.png|450px|thumb|center|Vzorec.]] | ||
+ | fcpu je 16MHz, fpwm by malo byť 50Hz, N – preddelička. Sme zvolili 64, teda preddeličku nastavíme takto TCCR1B = (1<<CS10)|(1<<CS11);. Potom sa z výpočtov TOP rovná 4999 a túto hodnotu zapíšeme do ICR1. | ||
+ | Ďalej, aby sme mohli ovládať polohu servomotora k OCR1A a OCR1B, musíme zapisovať hodnoty, ktoré sú v rozsahu 5-10% z ICR1 (aby sme dostali impulzy 1,0-2,0 ms, ktoré nám dajú 0° - 180°), kde 7,5 % bude počiatočná pozícia. | ||
Riadok 56: | Riadok 74: | ||
Algoritmus programu je.... | Algoritmus programu je.... | ||
+ | |||
+ | |||
<tabs> | <tabs> | ||
− | <tab name="AVR C-code"><source lang="c++" style="background: LightYellow;" | + | <tab name="AVR C-code(s vrátením polohy kamery)"><source lang="c++" style="background: LightYellow;"> |
− | |||
+ | #define F_CPU 16000000UL // Define CPU Frequency()16MHz | ||
+ | #include <avr/io.h> // Include AVR std. library file | ||
+ | #include <stdio.h> // Include std. library file | ||
+ | #include <util/delay.h> // Include Delay header file | ||
+ | |||
+ | void ADC_Init() // ADC Initialization function | ||
+ | { | ||
+ | DDRC=0x00; // Make ADC port as input | ||
+ | ADCSRA = 0x87; // Enable ADC, with freq/128 | ||
+ | ADMUX = 0x40; // Vref: Avcc, ADC channel: 0 | ||
+ | } | ||
+ | |||
+ | int ADC_Read(char channel) | ||
+ | { | ||
+ | ADMUX = 0x40 | (channel & 0x07); // set input channel to read | ||
+ | ADCSRA |= (1<<ADSC); // Start ADC conversion | ||
+ | while (!(ADCSRA & (1<<ADIF))); | ||
+ | /* Wait until end of conversion by polling ADC interrupt flag*/ | ||
+ | ADCSRA |= (1<<ADIF); // Clear interrupt flag | ||
+ | _delay_ms(1); // Wait a little bit | ||
+ | return ADCW; // Return ADC word | ||
+ | } | ||
+ | |||
int main(void) | int main(void) | ||
{ | { | ||
− | + | ADC_Init(); // ADC initialize function | |
+ | DDRB|=(1<<PB1)|(1<<PB2); // Make OC1A and OC1B pin as output | ||
+ | TCNT1 = 0; // Set timer1 count zero | ||
+ | ICR1 = 4999; // Set TOP count for timer1 in ICR1 register //50Hz for 20ms pulse width | ||
− | while (1) | + | /* Set Fast PWM, TOP in ICR1, Clear OC1A, OC1B on compare match, clk/64 */ |
+ | TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1); | ||
+ | TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11); | ||
+ | |||
+ | while(1) | ||
{ | { | ||
− | + | OCR1A = 90 + (ADC_Read(0)/2); // Read ADC channel 0 and make count in between 90-600 | |
− | } | + | OCR1B = 90 + (ADC_Read(1)/2); // Read ADC channel 1 and make count in between 90-600 |
− | + | _delay_ms(16); // wait a bit | |
+ | } | ||
return(0); | return(0); | ||
} | } | ||
</source></tab> | </source></tab> | ||
− | <tab name=" | + | <tab name="AVR C-code(bez návratu polohy kamery)"><source lang="c++" style="background: LightYellow;"> |
− | #include <avr/io.h> | + | #define F_CPU 16000000UL // Define CPU Frequency()16MHz |
+ | #include <avr/io.h> // Include AVR std. library file | ||
+ | #include <stdio.h> // Include std. library file | ||
+ | #include <util/delay.h> // Include Delay header file | ||
+ | |||
+ | void ADC_Init() // ADC Initialization function | ||
+ | { | ||
+ | DDRC=0x00; // Make ADC port as input | ||
+ | ADCSRA = 0x87; // Enable ADC, with freq/128 | ||
+ | ADMUX = 0x40; // Vref: Avcc, ADC channel: 0 | ||
+ | } | ||
+ | |||
+ | int ADC_Read(char channel) | ||
+ | { | ||
+ | ADMUX = 0x40 | (channel & 0x07); // set input channel to read | ||
+ | ADCSRA |= (1<<ADSC); // Start ADC conversion | ||
+ | while (!(ADCSRA & (1<<ADIF))); | ||
+ | /* Wait until end of conversion by polling ADC interrupt flag*/ | ||
+ | ADCSRA |= (1<<ADIF); // Clear interrupt flag | ||
+ | _delay_ms(1); // Wait a little bit | ||
+ | return ADCW; // Return ADC word | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | ADC_Init(); // ADC initialize function | ||
+ | DDRB|=(1<<PB1)|(1<<PB2); // Make OC1A and OC1B pin as output | ||
+ | TCNT1 = 0; // Set timer1 count zero | ||
+ | ICR1 = 4999; // Set TOP count for timer1 in ICR1 register //50Hz for 20ms pulse width | ||
− | + | /* Set Fast PWM, TOP in ICR1, Clear OC1A, OC1B on compare match, clk/64 */ | |
+ | TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1); | ||
+ | TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11); | ||
+ | |||
+ | int c_X = 90 + 512/2; // The value of the initial position | ||
+ | int c_Y = 90 + 512/2; // The value of the initial position | ||
− | + | int ADC_ValueX; | |
+ | int ADC_ValueY; | ||
+ | |||
+ | OCR1A = c_X; // motor to the initial position | ||
+ | OCR1B = c_Y; // motor to the initial position | ||
+ | |||
+ | while(1) | ||
+ | { | ||
+ | ADC_ValueX = ADC_Read(0); // reading the value from the joystick | ||
+ | ADC_ValueY = ADC_Read(1); // reading the value from the joystick | ||
+ | |||
+ | if(ADC_ValueX >= 715) // when the joystick is tilted from its initial position | ||
+ | { | ||
+ | c_X = c_X +5; // changing the position value | ||
+ | if(c_X >=600) {c_X = 600;} // to stay in the range of 90 - 600 | ||
+ | if(c_X <=90) {c_X = 90;} // to stay in the range of 90 - 600 | ||
+ | } | ||
+ | if(ADC_ValueX <= 310) | ||
+ | { | ||
+ | c_X = c_X -5; | ||
+ | if(c_X >=600) {c_X = 600;} | ||
+ | if(c_X <=90) {c_X = 90;} | ||
+ | } | ||
+ | if(ADC_ValueY >= 715) | ||
+ | { | ||
+ | c_Y = c_Y +5; | ||
+ | if(c_Y >=600) {c_Y = 600;} | ||
+ | if(c_Y <=90) {c_Y = 90;} | ||
+ | } | ||
+ | if(ADC_ValueY <= 310) | ||
+ | { | ||
+ | c_Y = c_Y -5; | ||
+ | if(c_Y >=600) {c_Y = 600;} | ||
+ | if(c_Y <=90) {c_Y = 90;} | ||
+ | } | ||
+ | OCR1A = c_X; // setting the motor to a new value | ||
+ | OCR1B = c_Y; // setting the motor to a new value | ||
+ | _delay_ms(16); // wait a bit | ||
+ | } | ||
+ | return(0); | ||
+ | } | ||
</source></tab> | </source></tab> | ||
</tabs> | </tabs> | ||
− | + | Zdrojový kód: [[Médiá:Matsibora_a_Fietisov_projekt.zip|zdrojaky.zip]] | |
− | |||
− | |||
− | Zdrojový kód: [[Médiá: | ||
− | |||
=== Overenie === | === Overenie === | ||
Všetko sme spojili, ako je popísané vyššie. Pomocou Datasheetu sme skontrolovali napäťové charakteristiky našich dielov a vyšlo toto: | Všetko sme spojili, ako je popísané vyššie. Pomocou Datasheetu sme skontrolovali napäťové charakteristiky našich dielov a vyšlo toto: | ||
− | |||
− | |||
− | [[Súbor: | + | [[Súbor:Matsibora_a_Fietisov_fotka1.jpg|400px|thumb|center|Projekt.]] |
+ | [[Súbor:Matsibora_a_Fietisov_fotka2.jpg|400px|thumb|center|Projekt.]] | ||
+ | [[Súbor:Matsibora_a_Fietisov_fotka3.jpg|400px|thumb|center|Projekt.]] | ||
+ | |||
+ | V jednom prípade polohy servopohonov nasledujú polohu joysticku a pohybujú sa, kým posúvame joystick, v druhom - servopohony posúvame smerom, kam ukazuje joystick, a zostanú tam, kým opäť neposunieme páčku alebo nezmeníme smer. | ||
'''Video:''' | '''Video:''' |
Verzia zo dňa a času 18:56, 10. máj 2024
Záverečný projekt predmetu MIPS / LS2024 - Viacheslav Matsibora a Dmytro Fietisov
Dvojosová kolíska na kameru ovládaná joystickom
Držiak kamery pre servomotory SG90, MG90 a pod. Pohyb namontovanej kamery je možný v dvoch osiach (tzv. pan and tilt držiak kamery). Súčasťou balenia sú 4 kusy plastových komponentov a skrutky s maticami. Pre plnú funkčnosť budeme potrebovať 2 servomotory.
Takže budeme používať dva spôsoby riadenia servopohonmi: prvý, keď servopohony nasledujú polohu joysticku a pohybujú sa, kým posúvame joystick, druhý - servopohony začnú pohybovať smerom, kam ukazuje joystick, a zostanú tam, kým opäť neposunieme páčku alebo nezmeníme smer.
Zadanie
Rozhodli sme sa naprogramovať držiak na kameru, ktorý by sa otáčal doľava a doprava a samotná kamera sa pohybovala vertikálne. V našom prípade pôjde o dva typy pohybu a dva programy:
1.) keď servopohony nasledujú polohu joysticku a pohybujú sa, kým posúvame joystick.
2.)servopohony pohybovať smerom, kam ukazuje joystick, a zostanú tam, kým opäť neposunieme páčku alebo nezmeníme smer.
Literatúra:
Obsah
Analýza a opis riešenia
Celý projekt obsahuje dosku Arduino, dvojosový joystick, dva servá sg90, prepojovacie vodiče a samotný držiak kamery.
Použitý joystik má 5 pinov (Vcc, GND, Xaxis, Yaxis a kolík tlačidla). Joystick má 2 centrované potenciometre, pri napájaní produkujú analógový signál a pri použití s Arduino má nasledujúce hodnoty: „0-1023“ a keďže sú v pohotovostnom režime vycentrované, vytvárajú hodnoty okolo „512“ a tlačidlo má digitálny výstup 0/1.
Musíme byť opatrní s joystickom, pretože sú dosť lacné a môže fungovať iba jedna os, čo sa stalo v našom prípade. Na kontrolu osej sme použili terminal PuTTY.
Ďalej budeme hovoriť o servomotoroch.
Servomotory majú tri vodiče: GND/VCC/signál, v tomto prípade je napájaný 5V z Arduina, môžme použiť 9V alebo 12V, ale najprv si prečítajme datasheet list servomotora, aby sme poznali podporované napätie. Externý zdroj napájania musí mať spoločnú zem. Mame take charakteristiky motorčekov:
Napätie: 3V ~ 7.2V Rýchlosť 0,12 s/60° Točivý moment (@ U=4,8V)1,2 kg.cm Točivý moment (@ U=6V) 1,6 kg.cm Uhol natočenia: 180° Hmotnosť: 14g Rozmery(mm): 22 x 11,5 x 27
Servomotor je kombináciou DC motora, systému riadenia polohy, prevodov. Polohu hriadeľa DC motora nastavuje riadiaca elektronika v servo na základe duty ratio PWM signálu na pine SIGNAL. Jednoducho povedané, riadiaca elektronika nastavuje polohu hriadeľa ovládaním DC motora. Tieto údaje o polohe hriadeľa sa odosielajú cez pin SIGNAL. Údaje o polohe do riadenia by sa mali odosielať vo forme signálu PWM cez signálny pin servomotora.Generovanie PWM bolo riešené pomocou 16-bitového počítadla a časovača T1. Potom pre Т1: režim Fast PWM. To, ktorý režim PWM chceme používať sa nastavuje bitmi WGM13...WGM10, ktoré sú rozdelené do registrov TCCR1A a TCCR1B.
Ďalej musíme vypočítať frekvenciu signálu, na to použijeme vzorec z datasheetu.
fcpu je 16MHz, fpwm by malo byť 50Hz, N – preddelička. Sme zvolili 64, teda preddeličku nastavíme takto TCCR1B = (1<<CS10)|(1<<CS11);. Potom sa z výpočtov TOP rovná 4999 a túto hodnotu zapíšeme do ICR1. Ďalej, aby sme mohli ovládať polohu servomotora k OCR1A a OCR1B, musíme zapisovať hodnoty, ktoré sú v rozsahu 5-10% z ICR1 (aby sme dostali impulzy 1,0-2,0 ms, ktoré nám dajú 0° - 180°), kde 7,5 % bude počiatočná pozícia.
Algoritmus a program
Algoritmus programu je....
#define F_CPU 16000000UL // Define CPU Frequency()16MHz
#include <avr/io.h> // Include AVR std. library file
#include <stdio.h> // Include std. library file
#include <util/delay.h> // Include Delay header file
void ADC_Init() // ADC Initialization function
{
DDRC=0x00; // Make ADC port as input
ADCSRA = 0x87; // Enable ADC, with freq/128
ADMUX = 0x40; // Vref: Avcc, ADC channel: 0
}
int ADC_Read(char channel)
{
ADMUX = 0x40 | (channel & 0x07); // set input channel to read
ADCSRA |= (1<<ADSC); // Start ADC conversion
while (!(ADCSRA & (1<<ADIF)));
/* Wait until end of conversion by polling ADC interrupt flag*/
ADCSRA |= (1<<ADIF); // Clear interrupt flag
_delay_ms(1); // Wait a little bit
return ADCW; // Return ADC word
}
int main(void)
{
ADC_Init(); // ADC initialize function
DDRB|=(1<<PB1)|(1<<PB2); // Make OC1A and OC1B pin as output
TCNT1 = 0; // Set timer1 count zero
ICR1 = 4999; // Set TOP count for timer1 in ICR1 register //50Hz for 20ms pulse width
/* Set Fast PWM, TOP in ICR1, Clear OC1A, OC1B on compare match, clk/64 */
TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
while(1)
{
OCR1A = 90 + (ADC_Read(0)/2); // Read ADC channel 0 and make count in between 90-600
OCR1B = 90 + (ADC_Read(1)/2); // Read ADC channel 1 and make count in between 90-600
_delay_ms(16); // wait a bit
}
return(0);
}
#define F_CPU 16000000UL // Define CPU Frequency()16MHz
#include <avr/io.h> // Include AVR std. library file
#include <stdio.h> // Include std. library file
#include <util/delay.h> // Include Delay header file
void ADC_Init() // ADC Initialization function
{
DDRC=0x00; // Make ADC port as input
ADCSRA = 0x87; // Enable ADC, with freq/128
ADMUX = 0x40; // Vref: Avcc, ADC channel: 0
}
int ADC_Read(char channel)
{
ADMUX = 0x40 | (channel & 0x07); // set input channel to read
ADCSRA |= (1<<ADSC); // Start ADC conversion
while (!(ADCSRA & (1<<ADIF)));
/* Wait until end of conversion by polling ADC interrupt flag*/
ADCSRA |= (1<<ADIF); // Clear interrupt flag
_delay_ms(1); // Wait a little bit
return ADCW; // Return ADC word
}
int main(void)
{
ADC_Init(); // ADC initialize function
DDRB|=(1<<PB1)|(1<<PB2); // Make OC1A and OC1B pin as output
TCNT1 = 0; // Set timer1 count zero
ICR1 = 4999; // Set TOP count for timer1 in ICR1 register //50Hz for 20ms pulse width
/* Set Fast PWM, TOP in ICR1, Clear OC1A, OC1B on compare match, clk/64 */
TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
int c_X = 90 + 512/2; // The value of the initial position
int c_Y = 90 + 512/2; // The value of the initial position
int ADC_ValueX;
int ADC_ValueY;
OCR1A = c_X; // motor to the initial position
OCR1B = c_Y; // motor to the initial position
while(1)
{
ADC_ValueX = ADC_Read(0); // reading the value from the joystick
ADC_ValueY = ADC_Read(1); // reading the value from the joystick
if(ADC_ValueX >= 715) // when the joystick is tilted from its initial position
{
c_X = c_X +5; // changing the position value
if(c_X >=600) {c_X = 600;} // to stay in the range of 90 - 600
if(c_X <=90) {c_X = 90;} // to stay in the range of 90 - 600
}
if(ADC_ValueX <= 310)
{
c_X = c_X -5;
if(c_X >=600) {c_X = 600;}
if(c_X <=90) {c_X = 90;}
}
if(ADC_ValueY >= 715)
{
c_Y = c_Y +5;
if(c_Y >=600) {c_Y = 600;}
if(c_Y <=90) {c_Y = 90;}
}
if(ADC_ValueY <= 310)
{
c_Y = c_Y -5;
if(c_Y >=600) {c_Y = 600;}
if(c_Y <=90) {c_Y = 90;}
}
OCR1A = c_X; // setting the motor to a new value
OCR1B = c_Y; // setting the motor to a new value
_delay_ms(16); // wait a bit
}
return(0);
}
Zdrojový kód: zdrojaky.zip
Overenie
Všetko sme spojili, ako je popísané vyššie. Pomocou Datasheetu sme skontrolovali napäťové charakteristiky našich dielov a vyšlo toto:
V jednom prípade polohy servopohonov nasledujú polohu joysticku a pohybujú sa, kým posúvame joystick, v druhom - servopohony posúvame smerom, kam ukazuje joystick, a zostanú tam, kým opäť neposunieme páčku alebo nezmeníme smer.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.