Dvojosová kolíska na kameru ovládaná joystickom: Rozdiel medzi revíziami
Zo stránky SensorWiki
Riadok 66: | Riadok 66: | ||
#define F_CPU 16000000UL // Define CPU Frequency()16MHz | #define F_CPU 16000000UL // Define CPU Frequency()16MHz | ||
#include <avr/io.h> | #include <avr/io.h> // Include AVR std. library file | ||
#include <stdio.h> | #include <stdio.h> // Include std. library file | ||
#include <util/delay.h> | #include <util/delay.h> // Include Delay header file | ||
void ADC_Init() // ADC Initialization function | void ADC_Init() // ADC Initialization function |
Verzia z 16:20, 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:
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
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);
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);
}
#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);
}
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.