Vítejte na Elektro Bastlírn?
Nuke - Elektro Bastlirna
  Vytvořit účet Hlavní · Fórum · DDump · Profil · Zprávy · Hledat na fóru · Příspěvky na provoz EB

Vlákno na téma KORONAVIRUS - nutná registrace


Nuke - Elektro Bastlirna: Diskuzní fórum

 FAQFAQ   HledatHledat   Uživatelské skupinyUživatelské skupiny   ProfilProfil   Soukromé zprávySoukromé zprávy   PřihlášeníPřihlášení 

Problem riadenie serva

 
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Programování PIC, ATMEL, EEPROM a dalších obvodů
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
pokrivnik



Založen: Feb 05, 2009
Příspěvky: 79

PříspěvekZaslal: po listopad 07 2011, 12:38    Předmět: Problem riadenie serva Citovat

Zdravim Vás, mám taký menší problém. Rozhodol som sa riadiť servá z PC pomocou mojej Atmegy8. No problém je v tom, že keď servo pripojím, tak prvý príkaz mi vykoná a natočí sa na požadovanú pomohu, no to je všetko. Na ďalšie príkazy nereaguje. Kód prikladam. Servá neriadim cez ORC port, ale jednotlivé piny. PWM je tvorené softvérovo cez CTC. V prerušení počítam 20ms. Malo by to byť všetko OK, osciloskop bohužiaľ nemám, takže neviem zistiť či to je na 100% tak.

Tak Vás týmto prosím o pomoc. Či som náhodou niekde niečo neprehliadol, stať sa môže všetko Very Happy



serva.txt
 Komentář:
serva

Stáhnout
 Soubor:  serva.txt
 Velikost:  2.63 kB
 Staženo:  172 krát

Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pokrivnik



Založen: Feb 05, 2009
Příspěvky: 79

PříspěvekZaslal: po listopad 07 2011, 16:11    Předmět: Citovat

problem vyrieseny. napisal som si to odznova a chyba bola v navratovej hodnote funkcie. Laughing

Ale chcel by som sa opýtať na Váš názor. Či mi zvládne procesor ešte niekoľko operácií, ako nejaké AD prevody + odosielanie všetkých dát do PC, bez ovplyvnenia chodu serv? Alebo by bolo idálnejšie ísť s frekvenciou ešte vyššie pre istotu? Teraz tam mam 8MHz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zaky



Založen: Oct 30, 2010
Příspěvky: 6661
Bydliště: Praha

PříspěvekZaslal: po listopad 07 2011, 17:17    Předmět: Citovat

Čekat 20 ms v přerušení je špatně. V přerušení jen nastav timer a vrať se do programu. Po uplynutí času přijde přerušení od timeru, obsloužíš ho, znovu nastavíš timer a tak stále dokola a máš téměř veškerý výpočetní čas k dispozici.
Michal
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pokrivnik



Založen: Feb 05, 2009
Příspěvky: 79

PříspěvekZaslal: po listopad 07 2011, 18:06    Předmět: Citovat

ono je to cez prerusenie, ibaze prerusenie nastava kazdu 1ms, a jeden cyklus je konecny ked prejde 20 preruseni. Iny sposob na ovladanie dvoch serv ma ani nenapada.
mna by len zaujimalo, ci sa da nejak spocitat, ako dlho trva to jedno prerusenie. respektive ci by to niekto vedel. mam taky pocit ze by sa to malo dat cez pocet instrukcii ktore sa vykonavaju nie?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mtajovsky



Založen: Sep 19, 2007
Příspěvky: 3698
Bydliště: Praha

PříspěvekZaslal: po listopad 07 2011, 18:50    Předmět: Citovat

Vidím tam vícero věcí. Například se funkce smer() volá jak z main(), tak z rutiny přerušení. Přitom smer() pracuje s globálními proměnnými slovo1 a pohyb. To není dobrý postup. Například na řádku

else if(!strcmp(slovo1,dozae)

v rutime smer()

se slovo 1 otestuje, a než se stačí provést kód na podmínce závislý, tak se může stát, že rutina

ISR(USART_RXC_vect)

to slovo1 přepíše:

slovo1[x]=recchar();

Takže rutina smer() okracuje s hlediska podmínky s vadnými daty.

Obdobně pro data pohyb. Navíc, proč smer() vrací hodnotu pohyb, když tuto hodnotu rovnou nastavuje?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
AB1



Založen: Nov 23, 2009
Příspěvky: 312

PříspěvekZaslal: út listopad 08 2011, 7:51    Předmět: Citovat

Tvůj kód není moc dobrý.
Při předděliči 1024 trvá jeden krok čítače 128 us.
Pro OCR2 = 8 vychází impuls 8*128 = 1024 us.
Pro OCR2 = 16 vychází impuls 16*128 = 2048 us.
Takže můžeme nastavit jenom 8 nebo 9 poloh serva.
Hodnota OCR2 = 20 v kódu je už mimo rozsah serva.

Nejlépe je použít osvědčený režim Fast pwm a čítač1.
Mimo jiné pak nepotřebujeme přerušení.
kód:
// servo2.c
// Řízení dvou serv, připojených k PB1, PB2
// Atmega8, F_CPU = 8 MHz
// Avr-gcc

#include <avr/io.h>             
#include <util/delay.h>         
 
//---------------------------------------------------------------------

int main (void)
{
// fast pwm, mode 14 , TOP=ICR1
   TCCR1A  = (1<<WGM11);
   TCCR1B  = (1<<WGM12) | (1<<WGM13);   
   TCCR1B |= (1<<CS11);  //prescale 8, step = 1 us             

// clear OC1A, OC1B on compare
   TCCR1A |= (1<<COM1A1) | (1<<COM1B1);                 

// periode = 20 ms (50 Hz)
   ICR1 = 20000;                           

   OCR1A=1500;// 1.5 ms (center)
   OCR1B=1500;// 1.5 ms
 
   DDRB   |= (1<<PB1) | (1<<PB2); // OC1A, OC1B output
   
     for(;;)  //test servo1                 
     {
         OCR1A = 1000;                   // 1000 us - left
         _delay_ms(1500);         

         OCR1A = 1500;                   // 1500 us - center
         _delay_ms(1500);         

         OCR1A = 2000;                   // 2000 us - right
         _delay_ms(1500);         

      }//for
}//main
//---------------------------------------------------------------------
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pokrivnik



Založen: Feb 05, 2009
Příspěvky: 79

PříspěvekZaslal: út listopad 08 2011, 17:39    Předmět: Citovat

mtajovsky:
Takže ak som pochopil dobre, je lepšie hodnotu premennej slovo1 najprv zapísať vo funkcii smer(); do nejakej premenej, napr. temp, definovanej v tejto funkcii a potom túto porovnávať v if?

A to, že vracia funkcia smer(); pohyb je už opravené.

AB1:
Preddeličku mám ale nastavenú na 32. Tak jedno prerušenie pri hodnote OCR=250 je presne 1ms.
V tomto prípade sa strednej hodnote serva rovná OCR 125, a u krajných hodnôt je to 0 a 250. Tam je podľa môjho názoru clekom dostačujúci krok.

Tvoj príklad ma tiež napadol, no vylučuje použitie ďalších serv. No na riadenie auta je určite výhodnejší.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mtajovsky



Založen: Sep 19, 2007
Příspěvky: 3698
Bydliště: Praha

PříspěvekZaslal: út listopad 08 2011, 19:10    Předmět: Citovat

pokrivnik napsal(a):
mtajovsky:
Takže ak som pochopil dobre, je lepšie hodnotu premennej slovo1 najprv zapísať vo funkcii smer(); do nejakej premenej, napr. temp, definovanej v tejto funkcii a potom túto porovnávať v if?


To by mohlo být lepší. Musíte ale předpokládat, že přerušení může přijít kdykoliv. Ten problém je obecnější a chce to trochu teorie. V podstatě jde o to, že pokud existuje více úseků programu, které pracují s stejnými proměnnými a mohou být vykonávány asynchronně (z hlediska programu), třeba na základě asynchronního přerušení, tak je potřeba přístup k těm proměnným nějak ošetřit - serializovat. V principu byste měl na dobu, co trvá jak otestování proměnné, tak vykonávání kódu, který je na této proměnné závislý, zakázat přerušení té rutině, která by chtěla proměnnu měnit. Jelikož je nanejvýš žádoucí zakazovat přerušení na nejkratší možnou dobu, je celý program třeba navrhovat s ohledem na tuto potřebu. Vazeb mezi rutinu přerušení a kódem na popředí by mělo být co nejméně, například rutina příjmu znaku by mohla někde uložit znak nebo řetězec a jen signalizovat událost příchodu dat pro běh na popředí, který by měl data co nejrychleji někam převzít a po tuto dobu zakázat přerušení, aby se mu data nezměnila pod rukama. Složitější možnost je jen signalizovat, že si přebírám data, ale potom musí být driver schopen odložit rozpracovanou IO operaci do fronty a ve spolupráci s během na popředí se k ní vrátit po uvolnění dat. Tahle technika byla poprvé uvedena na OS RSX11 firmou DEC a dočtete se o ní na

http://en.wikipedia.org/wiki/Talk%3ARSX-11

jako o "fork queue" nebo i jinde při hledání hesla "RSX11 fork".

Sežeňte si něco o multiprogramování, o threadech a jejich synchronizaci, pokud tomu chcete porozumět.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
AB1



Založen: Nov 23, 2009
Příspěvky: 312

PříspěvekZaslal: út listopad 08 2011, 22:07    Předmět: Citovat

pokrivnik:
Pardon, špatně jsem přečetl předdělič.

Několik poznámek:
1. Proměnné, které jsou použity v hlavním programu i v přerušení musí být deklarovány jako volatile.

2. Kód přerušení má být co nejkratší, mimo jiné v něm nemá být volání funkcí.

3. V přerušení COMP nemusíš dorovnávat čas impulsů do 2 ms. Servu je jedno, jestli je mezera mezi impulsy 18, 20 nebo 22 ms.

4. Jestli dobře rozumím, tak z PC chceš jenom testovat pohyb serva doleva nebo doprava.
Potom je lepší posílat servu jednobajtové příkazy, ne stringy které pak musíš pracně dekódovat.

Vyzkoušel jsem úspěšně následující kód
kód:
//Atmega8 8 MHz
#include <avr/io.h>
#include <util/delay.h>         
#include <avr/interrupt.h>     
#include "uart.h"

#define SERVO1_ON    PORTB |=  (1<<PB0);
#define SERVO1_OFF   PORTB &= ~(1<<PB0);
#define SERVO2_ON    PORTB |=  (1<<PB1);
#define SERVO2_OFF   PORTB &= ~(1<<PB1);

volatile uint8_t servo1_puls, servo2_puls; // 1 - 250 pro puls 1 - 2 ms

//----- main ---------------------------------------------

int main()      
{
   uart_init();
   DDRB = (1<<0) | (1<<1);
 
   TCCR2   = (1<<WGM21);           //CTC
   TCCR2  |= (1<<CS21)|(1<<CS20);  //presc=32, step 4 us
   TIMSK   = (1<<OCIE2);           //enable interrupt COMPARE A
   UCSRB  |= (1<<RXCIE);           //enable interrupt RX
 
   sei();

   servo1_puls = 125;              //center position 
   servo2_puls = 125;   


   while(1)      
   {

//odkomentuj pro test bez uart
/*   
      UCSR0B &= ~(1<<RXCIE0);      //disable int RX
      servo1_puls = 1;   
      servo2_puls = 1;   
      _delay_ms(1500);     

      servo1_puls = 125; //center 
      servo2_puls = 125;   
      _delay_ms(1500);     

      servo1_puls = 250; //right 
      servo2_puls = 250;   
      _delay_ms(1500);     
*/   
   }
}

//----- end main -----------------------------------------

ISR(TIMER2_COMP_vect)
{
static uint8_t count;

   count++; 
   switch (count)
   {
      case 1:      
      {
         SERVO1_ON;
         OCR2 = 250;
         break;
      }
      case 2:      
      {
         OCR2 = servo1_puls;      
         break;
      }
      case 3:      
      {
         SERVO1_OFF;
         SERVO2_ON;
         OCR2 = 250;      
         break;
      }
      case 4:
      {
         OCR2 = servo2_puls;           
         break;
      }
      case 5:
      {
         SERVO2_OFF;
         OCR2 = 250;        
         break;
      }
      case 22:           
      {
         count = 0;   
         break;
      }
   }//switch   
}

//---------------------------------------------------------------------------
/*
Klávesami A a S posunujeme servo1 na jednu nebo druhou stranu.
Klávesami Q a W řídíme podobně druhé servo.
*/
 
ISR(USART_RXC_vect)
{
uint8_t recv_byte;

   recv_byte = UDR;
   if((recv_byte == 'A') || (recv_byte == 'a'))
      servo1_puls = servo1_puls + 5;
 
   if((recv_byte == 'S') || (recv_byte == 's'))
     servo1_puls = servo1_puls - 5;

   if((recv_byte == 'Q') || (recv_byte == 'q'))
      servo2_puls = servo2_puls + 5;

   if((recv_byte == 'W') || (recv_byte == 'w'))
      servo2_puls = servo2_puls - 5;
}
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Programování PIC, ATMEL, EEPROM a dalších obvodů Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra.
Nemůžete odpovídat na témata v tomto fóru.
Nemůžete upravovat své příspěvky v tomto fóru.
Nemůžete mazat své příspěvky v tomto fóru.
Nemůžete hlasovat v tomto fóru.
Nemůžete připojovat soubory k příspěvkům
Můžete stahovat a prohlížet přiložené soubory

Powered by phpBB © 2001, 2005 phpBB Group
Forums ©
Nuke - Elektro Bastlirna

Informace na portálu Elektro bastlírny jsou prezentovány za účelem vzdělání čtenářů a rozšíření zájmu o elektroniku. Autoři článků na serveru neberou žádnou zodpovědnost za škody vzniklé těmito zapojeními. Rovněž neberou žádnou odpovědnost za případnou újmu na zdraví vzniklou úrazem elektrickým proudem. Autoři a správci těchto stránek nepřejímají záruku za správnost zveřejněných materiálů. Předkládané informace a zapojení jsou zveřejněny bez ohledu na případné patenty třetích osob. Nároky na odškodnění na základě změn, chyb nebo vynechání jsou zásadně vyloučeny. Všechny registrované nebo jiné obchodní známky zde použité jsou majetkem jejich vlastníků. Uvedením nejsou zpochybněna z toho vyplývající vlastnická práva. Použití konstrukcí v rozporu se zákonem je přísně zakázáno. Vzhledem k tomu, že původ předkládaných materiálů nelze žádným způsobem dohledat, nelze je použít pro komerční účely! Tento nekomerční server nemá z uvedených zapojení či konstrukcí žádný zisk. Nezodpovídáme za pravost předkládaných materiálů třetími osobami a jejich původ. V případě, že zjistíte porušení autorského práva či jiné nesrovnalosti, kontaktujte administrátory na diskuzním fóru EB.


PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Čas potřebný ke zpracování stránky 0.16 sekund