Stránka 1 z 2

Řízení RC serva PICem - servo se cuká. Proč?

Napsal: 06 úno 2014, 11:50
od VirtualMan
Ahoj!
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.

Napsal: 06 úno 2014, 14:01
od kulikus
Servsa jsou obvyle napájená z baterie. Pokud to máš z adaptéru, máš dobře vyhlazené napájení?

Napsal: 06 úno 2014, 15:19
od VirtualMan
No, já to teď napájím z takového toho 5V MiniUSB adaptéru. Je to spínaný zdroj, tak jsem to nijak nevyhlazoval. Dám tam elyt, ale předpokládám, že na výstupu z toho zdroj nějaký je.

Napsal: 06 úno 2014, 15:30
od forbidden
Je obsluha přerušení správně napsaná? Nenastane během ní třeba další přerušení od něčeho jinýho? Co kouknout na výstup osciloskopem?

Napsal: 06 úno 2014, 17:07
od VirtualMan
Oscilo mám jen takový malý žebrák - QUAD Na rozdíl od skleněné klasiky kde stopa po parsku přece jen chvilku vyhasína na tom člověk tak krátkou špičku nepostřehne.
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
}

Napsal: 06 úno 2014, 18:34
od forbidden
Quad neznám, ale zaráží mě, že v dnešní době neumí digitál, i jen tak jednoduchej, záznam, alespoň kousek.
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.

Napsal: 06 úno 2014, 19:48
od VirtualMan
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.

Napsal: 06 úno 2014, 19:55
od Mendor
Použij řadu PIC 18F, ta už priority má.

Napsal: 07 úno 2014, 18:11
od VirtualMan
Tak se přáteé musím přiznat, že poté co jsem nad tím strávil den a noc jsem nakonec hodil ručník do ringu.
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.

Napsal: 07 úno 2014, 18:58
od MiloPS3
Cau,s PICAXE-08M2 sice nedelam ale myslis si ze tenhle 8pinovej PIC ma vetci vykon nez 16F1825 ?

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

Napsal: 08 úno 2014, 11:18
od Jeejda_teda_puvodne

Napsal: 09 úno 2014, 14:35
od jankop
Nikdy jsem se servem nepracoval. Když jsem potřeboval opakovaně zapínat přístroj v záruce, který se automaticky po 8 hodinách vypnul, tak jsem koupil nejlacinější modelářský servo a napsal program. Zapojil to a naprosto žádný problém. Faktem je, že jsem to psal v assembleru.

Napsal: 11 úno 2014, 22:57
od Jeejda_teda_puvodne

Napsal: 12 úno 2014, 00:00
od Burajko
A na akom kompilery to robis? free hitec? Optimalizacia je na rychlost,velkost kodu? Rutiny z MSSP su dostatocne rychle aj z kruhovym bufferom,nevidim problem ho dat do mainu.A co mas vlastne v maine? A ake velke a ako casto chodia spravy po i2c? Velmi malo informacii... Tebe staci update kazdych 100ms,wdt nepreteka? :roll:

Napsal: 13 úno 2014, 13:26
od Jenda_KL
VirtualMan:
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.