Řízení RC serva PICem - servo se cuká. Proč?
Moderátor: Moderátoři
- VirtualMan
- Příspěvky: 63
- Registrován: 18 bře 2005, 00:00
- Bydliště: Brno
Řízení RC serva PICem - servo se cuká. Proč?
Třeba má někdo zkušenost a poradí, možná na to jdu blbě. Nevím.
PIC 16F1825, servo připojeno na výstup RA4
TMR0 mám nastavený na 100 Hz. (vím že RC serva běžně běhají na 50 Hz, ale při 50 Hz se mi cukání projevovalo víc, asi proto že servo stihlo zajet dál, než přišla další "oprava" polohy)
V obsluze přerušení od TMR0 si nastavím do TMR1 počet cyklů, odpovídající požadované poloze serva, RA4 nahodím do jedničky a spustím odpočet TMR1
V obsluze přerušení od TMR1 zase odpočet zastavím a shodím RA4 do nuly.
Servo jaksi udržuje tuto polohu, ale sem-tam někdy i víckrát za sekundu poskočí, jako by ho někdo nakopnul. Jakoby ta jednička na pinu RA4 nespadla do nuly nebo co. (nevyvolá se včas přerušení od TMR1, nebo se nevyvolá vůbec?)
Nenapadá mě, co by se kde dalo vymyslet líp, ale třeba má na to někdo lepší mast a já to řeším nějak blbě...
Díky za každé nakopnutí správným směrem.
- VirtualMan
- Příspěvky: 63
- Registrován: 18 bře 2005, 00:00
- Bydliště: Brno
- VirtualMan
- Příspěvky: 63
- Registrován: 18 bře 2005, 00:00
- Bydliště: Brno
Ale s těma přerušeníma to může být ono. Mám tam ještě přerušení od sériové linky, protože to pracuje jako I2C slave.
Takže bych měl do obsluhy toho přerušení od TMR1 přidat na začátek zákaz všech přerušení nebo jak o udělat? Neumím nastavit prioritu přerušení (pokud to vůbec u PIC jde...)
Kód: Vybrat vše
void interrupt() {
if (SSP1IF_bit){ // Od I2C mastera prisla nova data
SSP1IF_bit = 0;
++rear %= maxque; // Inkrementace kruhového bufferu
if (front == rear) return; // pokud je buffer plný, nedelej nic
else {
Buff[rear].Status = SSPSTAT;
Buff[rear].Value = SSPBUF;
}
CKP_bit = 1;
}
if (TMR0IF_bit) { // preruseni od TMR0
TMR0IF_bit = 0;
TMR0 = 100; // Nastavit novy odpocet
ServoHandler(); // Nastaveni polohy serva, port A4=1
}
if (TMR1IF_bit) { // Odpocet pulsu pro servo dobehnul
TMR1ON_bit = 0; // Zastav citac TMR1
LATA4_bit = 0; // Ukonci puls pro servo - port A4 = 0
TMR1IF_bit = 0; // Clear interrupt flag bit
}
}
Kód: Vybrat vše
void ServoHandler(void){
int PosDiff;
PosDiff = NewServoPos-CurrentPos; // Velikost zmeny polohy serva
if (PosDiff >5) { // Odchylku mensi nez 5 ignoruj
CurrentPos += sqrt(PosDiff); // polohu upravujeme v jednom kroku jen
} else if (PosDiff <5) { // o druhou odmocninu celkové odchylky
CurrentPos -= sqrt(PosDiff*-1);
}
TMR1H = ((CurrentPos & 0xff00) >> 8) ^ 0xFF; // Nastav nové hodnoty
TMR1L = (CurrentPos & 0x00ff) ^ 0xFF; // pro odpocet
LATA4_bit = 1;
TMR1ON_bit = 1; // Spustit odpocitavani
}- forbidden
- Příspěvky: 9442
- Registrován: 14 úno 2005, 00:00
- Bydliště: Brno (JN89GF)
- Kontaktovat uživatele:
V Cčku to nezkontroluju, ale základ v obsluze je ihned po skoku na vektor přerušení veškerý přerušení globálně zakázat. PIC žádný priority nemá, ale tento konkrétní z hlavy neznám. Nevylučuju, že některý typy to můžou mít.
- VirtualMan
- Příspěvky: 63
- Registrován: 18 bře 2005, 00:00
- Bydliště: Brno
forbidden píše:Quad neznám, ale zaráží mě, že v dnešní době neumí digitál, i jen tak jednoduchej, záznam, alespoň kousek..
No, to on samozřejmě umí zaznam, i přehrávání, ale už asi dva roky mi při pokusu o záznam píše Write error a já nevím proč. Přehrání na nový firmware nepomohlo. Asi má nějak nadrbnutý filesytem, a funkci na formátování nemá.
forbidden píše:V Cčku to nezkontroluju, ale základ v obsluze je ihned po skoku na vektor přerušení veškerý přerušení globálně zakázat. PIC žádný priority nemá, ale tento konkrétní z hlavy neznám. Nevylučuju, že některý typy to můžou mít.
Jo, to zkusím. Já se s PICkem moc nekamarádím, toto je moje třetí aplikace, tak se v tom tady tak nějak plácám a většinu času se hrabu v datasheetu a googlu.
- VirtualMan
- Příspěvky: 63
- Registrován: 18 bře 2005, 00:00
- Bydliště: Brno
Vyzkoušel jsem mnoho způsobů, různě navzájem blokoval přerušení a dělal různé kličky jak přerušení obsluhovat v požadovaném pořadí, ale nic nezabralo, a poloha serva při žádné z variant nebyla stabilní.
Když jsem v obsluze přerušení od TMR1 blokoval přerušení od I2C, tak měl zase problémy I2C master, prostě nebylo to ono. Master má zase jiné úkoly, které musí stíhat v reálném čase, proto jsem chtěl obsluhu serva přesunout na tento druhý procesor, kterému bych jen přes I2C diktoval polohu serva.
Udělat obsluhu serva přes dva časovače a přerušení není problém, chodí to krásně a servo drží polohu jako přibité.
Udělat funkční I2C komunikaci master-slave s kruhovým bufferem a následným zpracováním přijatých dat někde v main proceduře také lze, a chodí to pěkně, možná by ani nebylo nutné dělat CRC kontrolu.
Skloubit tyhle dvě věci dohromady je ale možná nad síly toho procesoru. I2C slave obsluha je natolik časově náročná, že udržet šířku pulsu pro servo s tolerancí pár mikrosekund se asi nedá. Nad moje síly je to určitě.
Na netu jsem našel spoustu odkazů na nějaké řízení serv, dokonce i šestnáct najednou, několik jsem jich vyzkoušel, ale bez úspěchu.
Taky jsem tam ale našel dost rozsáhlý popis od člověka, který asi před dvěma lety poměrně dlouho řešil přesně stejný problém jako já, prakticky totožné zadání. Věnoval tomu mnohem více času, a bohužel taky dospěl ke stejnému výsledku.
Takže ještě zkusím pro přenos požadované polohy použít místo I2C mormální PWM signál a měřit/počítat si šířku pulsu (ale tady taky moc nevěřím že by to bylo stabilní) a nebo zkusím, jestli by si s tím neporadil jiný procesor. Zajímavým kandidátem se zdá být PICAXE-08M2.
serva nejsou moc haklivy na frekvenci impulzu, takze jestli je krmis 200Hz nebo 40Hz je za urcitych okolnosti sumak ...
skus trochu popsat co to ma delat a jak cca casove narocny je to
preruseni musi bejt samozrejme co nejkratsi
- Jeejda_teda_puvodne
- Příspěvky: 142
- Registrován: 08 dub 2012, 00:00
- Jeejda_teda_puvodne
- Příspěvky: 142
- Registrován: 08 dub 2012, 00:00
Pic neovládám, jako stará škola jedu v asembleru na AVR, ale:
obsluha několika serv s taktem 40Hz a jedna sériová linka musí být zívačka pro jakýkoliv procesor.
Priorita přerušení se projeví v momentě, kdy se naráz setkají dvě přerušení.
Každý procesor je má seřazené podle priorit, u některých se dají priority měnit.
Přerušit přerušení lze taky, to už ale vyžaduje velmi dobrou kontrolu nad kódem.
Hlavně v přerušení se nedělaj matematický orgie typu sqrt, výpočet odchylky apod., to se řeší v mainu.
Dále neznám způsob exekuce intu na PICu, ale zaráží mě, jak je to napsané, že se musí testovat nějaké bity. Problém bych viděl v provedení
if (front == rear) return kdy ukončí celý INT při souběhu požadavků a na timer se nedostane, to ale hádám.