Operácie

Ovládanie robotického ramienka joystickom: Rozdiel medzi revíziami

Zo stránky SensorWiki

Balogh (diskusia | príspevky)
dBez shrnutí editace
StudentMIPS (diskusia | príspevky)
 
(11 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 1: Riadok 1:
Záverečný projekt predmetu MIPS / LS2025 - '''Meno Priezvisko'''
Záverečný projekt predmetu MIPS / LS2025 - '''Juraj Krasnovský'''
 
(napr. https://www.engineersgarage.com/how-to-use-a-wireless-joystick-to-remotely-control-two-servo-motors/)


== Zadanie ==
== Zadanie ==


Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie
Cieľom projektu bolo ovládať robotické ramienko s tromi servo motormi pomocou pomocou jedného joysticku.
 
[[Obrázok:ard.jpg|400px|thumb|center|Vývojová doska ACROB.]]
[[Obrázok:Auno.jpg|400px|thumb|center|Vývojová doska Arduino Uno.]]


'''Literatúra:'''  
'''Literatúra:'''  
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [https://www.farnell.com/datasheets/1682209.pdf Dokumentácia k doske Arduino Uno]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
* [https://www.friendlywire.com/projects/ne555-servo-safe/SG90-datasheet.pdf Dokumentácia k použitému servomotorčeku]
* [https://naylampmechatronics.com/img/cms/Datasheets/000036%20-%20datasheet%20KY-023-Joy-IT.pdf Dokumentácia k použitému joysticku]




Riadok 17: Riadok 16:


== Analýza  a opis riešenia ==
== Analýza  a opis riešenia ==
Použíté komponenty:
[[Súbor:joystick.jpg|400px|thumb|center|Použitý joystick]]
[[Súbor:servomotor.jpg|400px|thumb|center|Použitý servomotor]]
[[Súbor:Klon.jpg|400px|thumb|center|Použitý klon Arduino Uno]]
Joystick funguje ako dva potenciometre, kde zmena polohy mení hodnotu v dvoch smeroch, x a y. Pomocou AD prevodníka som odčítal, že sa tieto hodnoty menia od 0 do 1023, kde 512 je stred. Na ovládanie dvoch servomotorov som použil Timer1. Pre tretí servomotor som musel, kvôli obmedzeniam arduino uno, použiť 8-bitový časovač Timer2,ktorý má síce menší rozsah pre nastavenie PWM ako Timer1, ale pre tento projekt je dostatočný. PWM signál má štandardnú dĺžku impulzov od 1 ms do 2ms. Pre Timer2 som použil prescaler rovný 256, pomocou ktorého som vypočítal dĺžku jedného kroku a potom pomocou nej určil rozsah OCR2:
[[Súbor:Timer2.jpg|400px|thumb|center]]
Rovnaký výpočet som robil aj pre Timer1, menil sa ale iba prescaler (je rovný 8), tak napíšem iba výsledný  rozsah OCR1:
[[Súbor:Timer1.jpg|400px|thumb|center]]


Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.


[[Súbor:GeminiAI-image3.jpg|400px|thumb|center|Celkový pohľad na zariadenie.]]


Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.
Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.
Riadok 30: Riadok 38:
=== Algoritmus a program ===
=== Algoritmus a program ===


Algoritmus programu využíva toto a toto, základné funkcie takéto a voláma ich tuto...  
Program zabezpečuje ovládanie robotického ramena pomocou odčítaných hodnôt "x" a "y" z AD prevodníka. Rameno sa skladá z troch servomotorov, horný, stredný a dolný. Stredný servomotor je ovládaný neustále podľa hodnoty "y" z joysticku. Horný a dolný servomotor ovládané pomocou hodnoty "x".Samotné servá sa pohybujú pomocou premenných dx a dy, ktoré predstavujú "kroky" servomotorčeka. Tieto premenné sa pričítajú/odčítajú v ďaľších premenný posx a posy, podľa hodnôt "x" a "y".
Výpis kódu je nižšie...
Použité funkcie:
adc_read  –  čítanie analógovej hodnoty z joysticku
uart_init – inicializácia sériovej komunikácie UART
uart_getc – čítanie znaku z UART
delay – funkcia na oneskorenie
Medzi horným a dolným servomotorom je treba prepínať, keďže chceme v jednom čase ovládať iba jeden z nich. Výber a ovládanie iba jedného je založené na dvoch režimoch, medzi ktorými sa prepína pomocou premennej „rezim“, do ktorej je funkciou getc() načítaný znak. Režim+ (znak = ' + ') zabezpečuje ovládanie spodného motora, tento režim je predvolený. Režim- (znak =' - ') zabezpečuje ovládanie horného motora. Ak do premennej „znak“ nie je načítané "+" ani "-" UART vypíše chybu a ovládanie sa zablokuje.
 




<tabs>
<tabs>
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="program"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define BAUD 9600
#define F_CPU 16000000UL
 
#include <stdio.h>
#include <avr/io.h>
#include <avr/io.h>
#include "uart.h"
#include "adc.h"
#include <util/delay.h>
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
void delay(int delay)
{
  for (int i=1; i<=delay; i++)
  _delay_ms(1);
}


int main(void)
int main(void)
{
{
  unsigned int measuredValue;
unsigned int x, y, stred = 512, dolna, horna, posx, posy,dx,dy,xmax,xmin,ymax,ymin;
char rezim = '+';
 
adc_init();
uart_init();
stdout = &mystdout;
DDRB|=(1<<PB1); //dolne servo   
DDRB |= (1<<PB2); //horne servo
DDRB|=(1<<PB3); //stredne servo
TCNT1 = 0;
ICR1  = 39999;
TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); //Timer1
TCCR1B|=(1<<WGM12)|(1<<WGM13)|(1<<CS11); 
 
TCCR2A |= (1 << COM2A1) | (1 << WGM21) | (1 << WGM20); //Timer2
TCCR2B |= (1 << CS21) | (1 << CS22);
OCR1A=3000; //dolne servo
OCR1B=3000; //horne servo
OCR2A =98; //stredne servo 
posx = 3000; //stredna hodnota horneho a dolneho serva
posy = 98; //stredna hodnota stredneho serva
 
dx = 40; //zmena x-ovej hodnoty
dy = 1; //zmena y-ovej hodnoty
//krajne hodnoty
xmax = 4000;
xmin = 2000;
ymax = 125;
ymin = 62;
//deadzone
dolna = stred-40;
horna = stred+40;
while(1)
    {
 
x = adc_read(4);
y = adc_read(5);
    //ukladanie zapisaneho znaku
if (UCSR0A & (1 << RXC0)) {
            rezim = uart_getc();
}
if ( (x < dolna)){
if(posx >xmin) posx -= dx;
else posx = xmin;
}
else if(x > horna){
if(posx <xmax) posx += dx;
else posx = xmax;
}
if ( (y < dolna)){
if(posy >ymin) posy -= dy;
else posy = ymin;
}
else if(y > horna){
if(posy <ymax) posy += dy;
else posy = ymax;
}
if(rezim == '+'){ //rezim +
OCR1A = posx;
OCR2A = posy;
printf("rezim:%c\n",rezim);
}
else if(rezim == '-'){ //rezim -
OCR1B = posx;
OCR2A = posy;
printf("rezim:%c\n",rezim);
}
else if( (rezim != '+') && (rezim != '-')) //chybny vstup
{
uart_puts("CHYBA zle zvoleny rezim\n");
}
delay(5);
    }
}
</syntaxhighlight ></tab>
<tab name="uart.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#include <avr/io.h>
 
void uart_init( void );
   
void uart_putc( char c );
void uart_puts( const char *s );
 
char uart_getc( void );
</syntaxhighlight ></tab>
 
<tab name="uart.c"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define BAUD 9600
#define F_CPU 16000000UL
#define BAUDRATE      9600
#define BAUD_PRESCALE  103  // vzor?ek z datasheetu
 
#include <avr/io.h>
#include <util/setbaud.h>
 
void uart_init( void )
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
 
#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif
 
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);  /* Enable RX and TX */
}
 
 
void uart_putc(char c)
{
  if (c == '\n')
    {
      uart_putc('\r');
    }
  loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
  UDR0 = c;
}


  while (1)
  {
    /*  relax  */ 
  }


  return(0);
void uart_puts(const char *s)
{
while(*s!='\0')
{
uart_putc(*s++);
}
}
}


char uart_getc(void) {
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
<tab name="filename.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
 
<tab name="adc.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#include <avr/io.h>
#include <avr/io.h>


Riadok 57: Riadok 231:


unsigned int adc_read(char a_pin);
unsigned int adc_read(char a_pin);
</syntaxhighlight ></tab>
<tab name="adc.c"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#include <avr/io.h>
void adc_init(void)
{
    ADMUX = (1<<REFS0);        // Vref bude Avcc
    ADCSRA = (1<<ADEN)          // AD Enable - "zapnutie" ADC
            |(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);          // nastavenie preddelica
}
unsigned int adc_read(char channel)
{
    channel &= 0x0F;
    ADMUX = (ADMUX & 0xF0)|channel;
    ADCSRA |= (1<<ADSC);        // spustenie prevodu
    while(ADCSRA & (1<<ADSC))
    { /* cakaj tu */ }          // pockam na dokoncenie prevodu
    return (ADC);
}
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
</tabs>
</tabs>
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'':  
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'':  


Riadok 66: Riadok 261:
=== Overenie ===
=== Overenie ===


Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia.
Fungovanie programu som overil zapojením a následným vyskúšaním na robotickom ramienku s tromi servomotorčekmi. Na videu je vidno ako sa rameno pomocou joysticku ovláda a ako sa menia režimy,
Na konci uvádzame fotku hotového zariadenia.


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Obrázok:Zpj.jpg|thumb|center|Zapojenie.]]


'''Video:'''
'''Video:'''
<center><youtube>D0UnqGm_miA</youtube></center>
<center><youtube>EgjB13zVYrI</youtube></center>





Aktuálna revízia z 09:16, 14. máj 2025

Záverečný projekt predmetu MIPS / LS2025 - Juraj Krasnovský

Zadanie

Cieľom projektu bolo ovládať robotické ramienko s tromi servo motormi pomocou pomocou jedného joysticku.

Vývojová doska Arduino Uno.

Literatúra:


Analýza a opis riešenia

Použíté komponenty:

Použitý joystick
Použitý servomotor
Použitý klon Arduino Uno

Joystick funguje ako dva potenciometre, kde zmena polohy mení hodnotu v dvoch smeroch, x a y. Pomocou AD prevodníka som odčítal, že sa tieto hodnoty menia od 0 do 1023, kde 512 je stred. Na ovládanie dvoch servomotorov som použil Timer1. Pre tretí servomotor som musel, kvôli obmedzeniam arduino uno, použiť 8-bitový časovač Timer2,ktorý má síce menší rozsah pre nastavenie PWM ako Timer1, ale pre tento projekt je dostatočný. PWM signál má štandardnú dĺžku impulzov od 1 ms do 2ms. Pre Timer2 som použil prescaler rovný 256, pomocou ktorého som vypočítal dĺžku jedného kroku a potom pomocou nej určil rozsah OCR2:

Rovnaký výpočet som robil aj pre Timer1, menil sa ale iba prescaler (je rovný 8), tak napíšem iba výsledný rozsah OCR1:


Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Schéma zapojenia.


Algoritmus a program

Program zabezpečuje ovládanie robotického ramena pomocou odčítaných hodnôt "x" a "y" z AD prevodníka. Rameno sa skladá z troch servomotorov, horný, stredný a dolný. Stredný servomotor je ovládaný neustále podľa hodnoty "y" z joysticku. Horný a dolný servomotor sú ovládané pomocou hodnoty "x".Samotné servá sa pohybujú pomocou premenných dx a dy, ktoré predstavujú "kroky" servomotorčeka. Tieto premenné sa pričítajú/odčítajú v ďaľších premenný posx a posy, podľa hodnôt "x" a "y". Použité funkcie: adc_read – čítanie analógovej hodnoty z joysticku uart_init – inicializácia sériovej komunikácie UART uart_getc – čítanie znaku z UART delay – funkcia na oneskorenie Medzi horným a dolným servomotorom je treba prepínať, keďže chceme v jednom čase ovládať iba jeden z nich. Výber a ovládanie iba jedného je založené na dvoch režimoch, medzi ktorými sa prepína pomocou premennej „rezim“, do ktorej je funkciou getc() načítaný znak. Režim+ (znak = ' + ') zabezpečuje ovládanie spodného motora, tento režim je predvolený. Režim- (znak =' - ') zabezpečuje ovládanie horného motora. Ak do premennej „znak“ nie je načítané "+" ani "-" UART vypíše chybu a ovládanie sa zablokuje.


#define BAUD 9600
#define F_CPU 16000000UL

#include <stdio.h>
#include <avr/io.h>
#include "uart.h"
#include "adc.h"
#include <util/delay.h>

#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
	
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

	
void delay(int delay)
{
  for (int i=1; i<=delay; i++)
  _delay_ms(1);
}	

int main(void)
{
	unsigned int x, y, stred = 512, dolna, horna, posx, posy,dx,dy,xmax,xmin,ymax,ymin;
	char rezim = '+';

	adc_init();
	uart_init();
	stdout = &mystdout;
	
	DDRB|=(1<<PB1);		//dolne servo    
	DDRB |= (1<<PB2);	//horne servo
	DDRB|=(1<<PB3);		//stredne servo
	
	TCNT1 = 0;
	ICR1  = 39999;
	TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);					//Timer1
	TCCR1B|=(1<<WGM12)|(1<<WGM13)|(1<<CS11);  

	TCCR2A |= (1 << COM2A1) | (1 << WGM21) | (1 << WGM20);		//Timer2
	TCCR2B |= (1 << CS21) | (1 << CS22);
	
	OCR1A=3000;		//dolne servo
	OCR1B=3000;		//horne servo
	OCR2A =98;		//stredne servo  
	
	posx = 3000;	//stredna hodnota horneho a dolneho serva
 	posy = 98;		//stredna hodnota stredneho serva

	dx = 40;		//zmena x-ovej hodnoty
	dy = 1;			//zmena y-ovej hodnoty
	
	
	//krajne hodnoty
	xmax = 4000;
	xmin = 2000;
	
	ymax = 125;
	ymin = 62;
	
	//deadzone
	dolna = stred-40;
	horna = stred+40;
	
	while(1)
    {
	  
	x = adc_read(4);
	y = adc_read(5);
	
    //ukladanie zapisaneho znaku
	if (UCSR0A & (1 << RXC0)) {		
            rezim = uart_getc();
	}			
			
	if ( (x < dolna)){
		if(posx >xmin) posx -= dx;
			else posx = xmin; 
	}
	else if(x > horna){
		if(posx <xmax) posx += dx;
			else posx = xmax;
	}
	
	if ( (y < dolna)){
		if(posy >ymin) posy -= dy;
			else posy = ymin; 
	}
	else if(y > horna){
		if(posy <ymax) posy += dy;
			else posy = ymax;
	}
	
	if(rezim == '+'){							//rezim +
		OCR1A = posx;
		OCR2A = posy;
		printf("rezim:%c\n",rezim);
	}		
	else if(rezim == '-'){						//rezim -
		OCR1B = posx;
		OCR2A = posy;
		printf("rezim:%c\n",rezim);
		
	}
	else if( (rezim != '+') && (rezim != '-'))	//chybny vstup
		{
			uart_puts("CHYBA zle zvoleny rezim\n");
		}				
		
	delay(5);
		
    }
}
#include <avr/io.h>

void uart_init( void );
     
void uart_putc( char c );
void uart_puts( const char *s );

char uart_getc( void );
#define BAUD 9600
#define F_CPU 16000000UL
#define BAUDRATE       9600
#define BAUD_PRESCALE  103  // vzor?ek z datasheetu

#include <avr/io.h>
#include <util/setbaud.h>

void uart_init( void ) 
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
}


void uart_putc(char c) 
{
   if (c == '\n') 
    {
       uart_putc('\r');
    }
   loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
   UDR0 = c;
}


void uart_puts(const char *s)
{
	while(*s!='\0')
	{
		uart_putc(*s++);
	}
}

char uart_getc(void) {
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}
#include <avr/io.h>

void adc_init(void);                                   // A/D converter initialization

unsigned int adc_read(char a_pin);
#include <avr/io.h>

void adc_init(void)
{
    ADMUX = (1<<REFS0);         // Vref bude Avcc
    ADCSRA = (1<<ADEN)          // AD Enable - "zapnutie" ADC
            |(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);          // nastavenie preddelica
}

unsigned int adc_read(char channel)
{
    channel &= 0x0F;
    ADMUX = (ADMUX & 0xF0)|channel;
    ADCSRA |= (1<<ADSC);        // spustenie prevodu
    while(ADCSRA & (1<<ADSC))
    { /* cakaj tu */ }          // pockam na dokoncenie prevodu
    return (ADC);
}

Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:

Zdrojový kód: zdrojaky.zip

Overenie

Fungovanie programu som overil zapojením a následným vyskúšaním na robotickom ramienku s tromi servomotorčekmi. Na videu je vidno ako sa rameno pomocou joysticku ovláda a ako sa menia režimy,

Zapojenie.

Video:



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