Ovladani osmi serv pomoci UARTu
Moderátor: Moderátoři
Myslela jsem generovat je softwarově, všech 8 najednou. Samotné generování bez nějaké brutální optimalizace spolkne 35% času procesoru, 65% zbývá na komunikaci, což je až až (v assembleru, ne v C).Anonym píše:viz konec 1. stranycelé to jde udělat pomocí dvou přerušení, od UARTu a od Timeru a zvládne to i tina2313
Krásně se tam vejdou teoreticky, bez režie. Není nutné aby začínaly nastejně, jen musí začínat vždy ve stejný okamžik, což na předchozí stránce uvedené řešení nesplňuje. Šly by použít dva čítače, jeden bude generovat přerušení po 2.5ms a druhým se bude měřit délka impulsu. Ale 8x 12.5% střída se tam nenacpe, možná 12.4%piitr píše:A je vážně nutné, aby ty pulzy začínaly nastejně? Když je budu generovat po sobě, tak těch 8 pulzů po 2,5ms se mi do těch 20ms krásně vejde. A v každé chvíli hlídám jen jeden puls, na což mi 2us krásně stačí.
![Smile :)](./images/smilies/icon_smile.gif)
Ale to je, když dovolíte, omyl.jen musí zaèínat vždy ve stejný okamžik
Postupné posílání impulsù do serv je bìžnì používáno u modeláøských RC souprav.
Pro servo je dùležité, aby každých cca 20 ms dostalo øídící impuls. Celkem ho nezajímá, jestli vedlejší servo dostává svùj impuls souèasnì s ním, nebo jindy.
V mém programu se mi procesor nezdá nijak moc zatížený.
Uart pøijme napø. každých 6 ms 24 bajtù.
Procedura v hlavním programu trvá asi 7 mikrosec a opakuje se nejdøíve za 1 ms.
(Uvažuji nejbìžnìjší rozsah serv 1 až 2 ms.)
To jsme si asi nerozumněli. Impuls pro jedno servo musí začínat vždy ve stejný okamžik, jinak by se měnila střída.AA píše:Ale to je, když dovolíte, omyl.jen musí začínat vždy ve stejný okamžik
Postupné posílání impulsů do serv je běžně používáno u modelářských RC souprav.
Pro servo je důležité, aby každých cca 20 ms dostalo řídící impuls. Celkem ho nezajímá, jestli vedlejší servo dostává svůj impuls současně s ním, nebo jindy.
Edit:
Ale teď koukám, že ty serva vlastně nekoukají na střídu, ale jen na délku impulsu, tak pak je to úplně jedno. Se omlouvám, dělala jsem s nima jen jednou a už je to nějaký pátek.
No, je fakt, že se to tam nevejde krásně, ale akorát. Muselo by se trošku někde slevit, ale asi ne moc. Kdyby se slevit nechtělo, tak mě napadlo ještě jedno řešení, ale je dost složité:
Pulzy by se překrývaly, ale nezačínaly by všechny nastejně. Jejich začátky a konce by se spočítaly tak, aby:
1) Délky pulzů byly správné.
2) Začátky a konce pulzů byly od sebe dostatečně daleko, aby se neměnily dva výstupy najednou, protože ta změna může zabrat tak 10-20 instrukcí.
Při daných hodnotách si myslím, že by to mělo být vždy spočitatelné.
Má to ale nevýhodu, že při změně hodnoty se bude pohybovat jak náběžná, tak sestupná hrana, ale to by snad až tak nevadilo.
Pulzy by se překrývaly, ale nezačínaly by všechny nastejně. Jejich začátky a konce by se spočítaly tak, aby:
1) Délky pulzů byly správné.
2) Začátky a konce pulzů byly od sebe dostatečně daleko, aby se neměnily dva výstupy najednou, protože ta změna může zabrat tak 10-20 instrukcí.
Při daných hodnotách si myslím, že by to mělo být vždy spočitatelné.
Má to ale nevýhodu, že při změně hodnoty se bude pohybovat jak náběžná, tak sestupná hrana, ale to by snad až tak nevadilo.
Serva samozrejme nemusi dostavat povel vsechna najednou, musim jenom vyzkouset, jak moc jim vadi rozdilna perioda ridiciho impulsu.
(u posledniho serva se muze dost menit)
Program si predstavuju nejak takto:
(fromat vysilanych dat bude 1byte adresa s MSB=1 a 16byte dat s MSB=0)
(data budou 10b rozdelenych na 3+7)
(u posledniho serva se muze dost menit)
Program si predstavuju nejak takto:
(fromat vysilanych dat bude 1byte adresa s MSB=1 a 16byte dat s MSB=0)
(data budou 10b rozdelenych na 3+7)
Kód: Vybrat vše
int vstup[8];
int vystup[9];
unsigned char adresa,prijem[16],prijmout,buff,servo;
//adresa - nastavena adresa tohoto ovladace
//prijem - prijate byte
//prijmout - pocet byte k prijeti
//buff - SW buffer pro RX buffer, ten se myslim po prvnim precteni smaze
//servo - index serva, servo[8] je doplnek do 2ms bez vystupu
Preruseni od UART RX:
{
buff=prijaty byte; //presunuti hodnoty z RX bufferu
if(buff>127) prijmout=0; //prisla nejaka adresa
if(buff==adresa) prijmout=15; //prisla moje adresa
if(prijmout>0) //prijem pozic
{
prijem[15-prijmout]=buff;
prijmout--;
}
}
Preruseni citace1 CTC:
{
PORTA=0;
OCR1A=vystup[servo]; //nastaveni nove hodnoty do citace
if (servo<8) //servo existuje - yapnout vystup
{
PORTA=1<<servo;
servo++;
}
else servo=0; //doplnek, vynulovat index
}
Main:
{
for (int i=0;i<=7;i++) //slepeni 3+7 bitu na 10b
{
vstup[i]=0;
vstup[i]=prijem[2*i]<<7;
vstup[i]=vstup[i]+prijem[2*i+1];
}
Prepocitat hodnoty z "vstup" do "vystup"
vystup[8]=40000-vystup[0]-...-vystup[7]; //doplnek do 2ms
}
Principielně je to bezva. Ten kód jsem nezkoumal do detailu, ale asi bych trošku upravil to přerušení od čítače. Nelíbí se mi tam to PORTA=0. Tím budeš mít mezi jednotlivými pulzy mezeru.
V praxi by to chtělo, aby zpoždění obou větví až k zápisu do PORTA bylo stejné, takže by to asi bylo lepší řešit v assembleru. Kdo ví, jak se přeloží to 1 << servo. S tím natažením timeru si budeš muset pohrát, nevím, jak se to v tom C řeší. Já to řešil u PICu instrukcí ADDWF TMR0 s tím, že je třeba si zjistit, jak se to chová, protože mezi čtením a zápisem do TMR0 se jeho hodnota ještě asi stihne změnit. Chce to kouknout do datasheetu.
Kód: Vybrat vše
natahni casovac na vystup[servo]+cas posledniho preruseni;
if ( servo < 8 )
{
PORTA = 1 << servo;
servo++;
}
else
{
PORTA = 0;
servo = 0;
}
Mezera by nemusela byt az tak kriticka a hlavne bude mit nemennou delku, takze to nijak velky problem nebude, pripadne ji muzu zmerit a pridat jako korekci do prepocitavani hodnot.
Ten CTC rezim neustale porovnava hodnotu citace a hodnotou OCR1A a pri souhlasu se snuluje a provede preruseni.
Na ten zapis nove hodnoty bude vzdy minimalne 0,5ms, takze snad casu dost.
Jeste me napadlo, ze by bylo dobre tam pridat osetreni, ze kdyz neprijde vsech 16 datovych bytu, takze se hodnoty zahodi a pouziji se minule, ale to az nekdy.
Ten CTC rezim neustale porovnava hodnotu citace a hodnotou OCR1A a pri souhlasu se snuluje a provede preruseni.
Na ten zapis nove hodnoty bude vzdy minimalne 0,5ms, takze snad casu dost.
Jeste me napadlo, ze by bylo dobre tam pridat osetreni, ze kdyz neprijde vsech 16 datovych bytu, takze se hodnoty zahodi a pouziji se minule, ale to az nekdy.