Operácie

Dvojosová kolíska na kameru ovládaná joystickom: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
StudentMIPS (diskusia | príspevky)
 
(67 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 9: Riadok 9:




[[Obrázok:Matsibora_a_Fietisov_koliska.jpg|280px|thumb|center|Model projekta.]]
[[Obrázok:Matsibora_a_Fietisov_koliska.jpg|440px|thumb|center|Model projekta.]]


== Zadanie ==
== Zadanie ==
Riadok 19: Riadok 19:


'''Literatúra:'''  
'''Literatúra:'''  
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf ATmega328P Datasheet]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
* [http://marcusjenkins.com/wp-content/uploads/2014/06/ARDUINO_V2.pdf Arduino Uno pinout diagram]




Riadok 33: 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:джойстик.jpg|280px|thumb|left|Joystik.]]
[[Súbor:Matsibora_a_Fietisov_joystik.jpg|450px|thumb|left|Joystik.]]


[[Súbor:рис8.png|450px|thumb|center|schema Joystika.]]
[[Súbor:Matsibora_a_Fietisov_hodnoty joystika.png|590px|thumb|center|schema Joystika.]]




[[Súbor:рис3.png|360px|thumb|center|Schéma zapojenia joystika k Arduino.]]
 
 
[[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.
Riadok 50: Riadok 52:
  Hmotnosť: 14g
  Hmotnosť: 14g
  Rozmery(mm): 22 x 11,5 x 27
  Rozmery(mm): 22 x 11,5 x 27
[[Súbor:sg90.png|300px|thumb|left|Servomotor.]]
[[Súbor:sg90.png|420px|thumb|left|Servomotor.]]
[[Súbor:рис51.png|350px|thumb|center|Schéma zapojenia joystika a servomotorov k Arduino.]]
[[Súbor:рис51.png|450px|thumb|center|Schéma zapojenia joystika a servomotorov k Arduino.]]
[[Súbor:ServoAnimation.gif|300px|thumb|center|Servomotor.]]
 
 
[[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|550px|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.




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


Algoritmus programu je....
Zdrojový kód do drziaka kamery
 
 




<tabs>
<tabs>
<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)
{
  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);
}
</source></tab>
<tab name="AVR C-code(bez návratu polohy kamery)"><source lang="c++" style="background: LightYellow;">
<tab name="AVR C-code(bez návratu polohy kamery)"><source lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL           // Define CPU Frequency()16MHz
#define F_CPU 16000000UL           // Define CPU Frequency()16MHz
#include <avr/io.h>               // Include AVR std. library file
#include <avr/io.h>               // Include AVR std. library file
Riadok 90: Riadok 151:
int main(void)
int main(void)
{
{
   ADC_Init();       // ADC initialize function
   ADC_Init();       // ADC initialize function
   DDRB|=(1<<PB1)|(1<<PB2);       // Make OC1A and OC1B pin as output
   DDRB|=(1<<PB1)|(1<<PB2);   // Make OC1A and OC1B pin as output
   TCNT1 = 0; // Set timer1 count zero
   TCNT1 = 0;       // Set timer1 count zero
   ICR1 = 4999; // Set TOP count for timer1 in ICR1 register //50Hz for 20ms pulse width
   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 */
/* Set Fast PWM, TOP in ICR1, Clear OC1A, OC1B on compare match, clk/64 */
Riadok 99: Riadok 160:
   TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
   TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
    
    
   int c_X = 90 + 512/2; // The value of the initial position
   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 c_Y = 90 + 512/2;           // The value of the initial position


   int ADC_ValueX;  
   int ADC_ValueX;  
   int ADC_ValueY;
   int ADC_ValueY;
    
    
   OCR1A = c_X; // motor to the initial position
   OCR1A = c_X;               // motor to the initial position
   OCR1B = c_Y; // motor to the initial position
   OCR1B = c_Y;               // motor to the initial position
    
    
   while(1)
   while(1)
   {
   {
ADC_ValueX = ADC_Read(0); // reading the value from the joystick
ADC_ValueX = ADC_Read(0);       // reading the value from the joystick
ADC_ValueY = ADC_Read(1); // 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
if(ADC_ValueX >= 715)   // when the joystick is tilted from its initial position
{
{
c_X = c_X +5; // changing the position value
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 >=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(c_X <=90) {c_X = 90;}   // to stay in the range of 90 - 600
}
}
if(ADC_ValueX <= 310)
if(ADC_ValueX <= 310)
Riadok 137: Riadok 198:
if(c_Y <=90) {c_Y = 90;}
if(c_Y <=90) {c_Y = 90;}
}  
}  
OCR1A = c_X; // setting the motor to a new value
OCR1A = c_X;               // setting the motor to a new value
OCR1B = c_Y; // setting the motor to a new value
OCR1B = c_Y;               // setting the motor to a new value
_delay_ms(16); // wait a bit
_delay_ms(16);               // wait a bit
   }
   }  
  return(0);
}
 
</source></tab>
<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)
{
  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);
   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á:Matsibora_a_Fietisov_projekt.zip|zdrojaky.zip]]


Riadok 206: Riadok 219:


'''Video:'''
'''Video:'''
<center><youtube>_l02MBu41n0</youtube></center>
<center><youtube>https://youtube.com/shorts/E7s8BPjaMC8?feature=share</youtube></center> - s vratenym polohy kamery
 
<center><youtube>https://youtube.com/shorts/G25c8ePBXMc</youtube></center> - bez vratenia polohy kamery
 


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


[[Category:AVR]] [[Category:MIPS]]
[[Category:AVR]] [[Category:MIPS]]

Aktuálna revízia z 20:26, 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.


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:


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.

Joystik.
schema Joystika.



Schéma zapojenia joystika k Arduino.

Ď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.
Schéma zapojenia joystika a servomotorov k Arduino.


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.

Tabulka.

Ďalej musíme vypočítať frekvenciu signálu, na to použijeme vzorec z datasheetu.

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.


Algoritmus a program

Zdrojový kód do drziaka kamery



#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:

Projekt.
Projekt.
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:

- s vratenym polohy kamery

- bez vratenia polohy kamery


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