[ diwljina @ 23.04.2015. 13:40 ] @
U pitanju je Balluff inkrementalni enkoder sa 2+1 kanalom i 2000 markera.

Interesuje me neki algoritam na osnovu kog mogu odrediti:
1. detektovanje smera obrtanja osovine enkodera
2. brzinu obrtanja osovine rotacionog enkodera
3. ogranicenje za 2000 markera

Gledao sam na netu ali nema nista ilustrovanom samo kodovi, za pic, arduino, ili neki drugi mikrokontroler i to u assembleru ili nekom drugom jeziku.
[ veselinovic @ 23.04.2015. 15:21 ] @
1 Ako se signal prvo pojavi na A pa na B okrece se u jednu stranu, ako se okrece kontra onda se prvo pojavi signal na B pa na A.
2. Brzinu moes odrediti na vise nacina.
2a. nadjes prvi izvod signala ( bilo A bilo B)
2b. mjeris vrijeme izmedju dva signala
2c. brojis signale u nekoj jedinici vremena.

3 mi nije jasno.
[ ZAS011 @ 23.04.2015. 15:50 ] @
Ajde ti to nama malko lepše objasni, ono pod 3.
[ diwljina @ 23.04.2015. 16:10 ] @
Ovo pod 1. i 2. razumem ali mi se u kodu nesto ne slaze. Odnosno, problem je kod mene ili do hard ili softv. Sto se tice 3. stavke....

3. Npr Kanal A i B naprave zajedno po 2000 impulsa po krugu, zar ne ?
Ako okrenem 2 kruga i polovinu treceg kruga , oni naprave 5000 imp i 2 imp od R kanala, s toga bih hteo da ispis te neke pozicije izgleda ovako:
+2 rot : 1000 imp 180* ( * je stepeni ) ili - 2 rot : - 1000 imp = 180*.

Elem, pitao sam vas za ovo pod 1 i 2, zbog toga sto koristim procesor koji moze da hvata rastuce i opadajuce ivice . Tako da od 2 000 imp, ja mogu dobiti rezoluciju od
8 000 . ( 2 x 2000 - rastuca i opadajuca A ) + ( 2 x 2000 - rastuca i opadajuca B ) ucetvorostrucenu preciznost dobijam.

Tako da, ako bih koristio ovu metodu dobijanja preciznost, mislim da mi ovo komplikuje pisanje, zar ne ?
[ mikikg @ 23.04.2015. 16:23 ] @
Koji MCU koristis i koji kompajler za programe?
[ diwljina @ 23.04.2015. 16:32 ] @
Koristim Arm7 mikrokontroler i uVision4.

Da li bi te petlje za detektovanje smera trebale da budu tipa if, while ili ???

Ja sam pokusao nesto poput ovoga :

If ( kanal A ==1 ) // desilo se dogadjaj
if ( kanal B ==1) // takodje i ovde
i++;
if(kanal B==1)
if (kanal A==)
i--;


Ali ne valja bas ovo...
[ yugaja @ 23.04.2015. 21:00 ] @
Ja za rot. encodere koristim rutinu koju sam pre puno godina pronasao... U osnovi je kao sa linka: http://www.circuitsathome.com/...ding-rotary-encoder-on-arduino kombinacija lookup tabele i sitnog racuna u dva reda.. Mislim da je originalna ideja iz glave nekog rusa i radi za sve novce...

EDIT: izgleda da sam okacio link bas od tog rusa...Nisam ni citao detaljno tekst kad ono...Sta ce covek svi su na arduinu sada :)
[ diwljina @ 23.04.2015. 21:57 ] @
Ja sam ovo video jos preksinoc...U tom trenutku mi se nije cinilo korisnim. Iskren da budem, ni sada mi se ne cini korisnim, ali cu zbog Vaseg posta pogledati.
Nadam se da ce mi pomoci.
ps. ako jos neko ima neke korisne linkove-preporuke, nek okaci ovde. Unapred se zahvaljujem
[ mikikg @ 23.04.2015. 22:30 ] @
Na brzinu sam pogledao spomenuti link i program. Izgleda korektno jer koristi malu look-up tablicu.
Naravno moras da ga prepakujes u sintaksu pogodnu za C++ / uVision4.

Mozda ti nije bio interesantan na prvi pogled jer je malo slozeniji program ali to inace NE MOZE jednostavno da se resi!
Zaguljena je malo ta logika posebno kada se operise sa obe (uzlazne i silazne) ivice signala.
Komplikovano je jer ima vise potencialnih stanja i recimo ako ti se enkoder zalomi izmedju dva markera na disku pa promeni smer moze pogresno da ti detektuje i "proguta" informaciju.
Ovakvi algoritmi sa look-up tablicom bi trebali apsolutno tacno da rade (jer prate sta je bilo predhodno stanje) bez gubljenja informacija.
[ diwljina @ 24.04.2015. 02:15 ] @
Hvala Vam na pozrtvovanju ali iskreno ja nista nisam tamo razumeo. Procitao sam ono, preveo, i nista...
[ ZAS011 @ 24.04.2015. 05:57 ] @
Ako ti ništa nije jasno, kreni sa učenjem C++ iz početka.
Ako si početnik, kreni od prostijih programčića pa lagano na teže.
[ diwljina @ 24.04.2015. 18:57 ] @
Da li mislis da je normalno uciti c++ koji u principu objektno orijentisano programiranje ? Slozen je veoma i tezak za ucenje. Znam C jezik i to sasvim dovoljno za ovaj zanat. Zbog jednog enkodera ja trebam da ucim novi - drugi jezik ? Pa ne radim ja svaki dan sa enkoderima, nisam ja fabrika ...
[ ColdKeyboard @ 24.04.2015. 19:25 ] @
Kod koji ti je dat je napisan u cistom C-u, vrlo je jasan, pregledan i elegantno napisan. Drugo nema razloga da napadas ljude zato sto su ti dali primjer/savjet a ne gotov kod koji mozes copy&paste i da radi u tvom primjeru.

Ako te interesuje kako izgledaju signali sa tog enkodera imas recimo Microchip Quadrature Encoder Interface app note koji pored podesavanja i primene
na PIC-u pokazuje i algoritam rada sa vremenskim dijagramima i objasnjenjima, sve sazvakano.

1. Koji kod si napisao i ne radi?
2. Sta ti nije jasno na ovom linku sto si vec dobio? Ako znas C, uzmi razlozi kod na delove, idi liniju po liniju i gledaj sta bi trebalo da dobijes kao rezultat funkcije read_encoder() i kako ona radi.
3. Reci da je C++ tezak i kompleksan jezik je isto da kazes da je 50kg puno.

Ako ti se ne svidja sto su svi dusmani i niko nece da napise gotov kod pa da uradis samo copy&paste nego svi cekaju da vide tvoj kod pa da ti onda pomognu, predlazem da temu pokrenes na Berza poslova, tamo ce ti sigurno neko pomoci, ali za pare. :)
[ diwljina @ 24.04.2015. 20:07 ] @
Prvo ne ljutim se ali predlog koji mi je predlozio je stvarno... Da mi je rekao-preporucio da proucim rad enkodera ili da potrazim nesto drugo, pa ok...Ali ovo...
Kao kada trazis pitanje na forumu i pitas nekog da li neko zna kako se puni akumulator, a neko ti odg idi upisi srednju skolu za automehanicara.

Znam kako izgledaju signali video sam ih na osciloskopu.

Stavio sam u IRQ rutini da mi detektuje ivice i on to uradi...Sada treba neki algoritam koji ce kada se desi interapt (stigne impuls) videti stanje na drugom kanalu i uporediti ih i u zavisnosti inkrementirati ili dekrementirati.
Ja sam to uradio sa 2 glavne if petlje i u svakoj if petlji sam sa if petljom ispitao stanje drugog kanala i non stop mi se inkrementira ili dekrementira.

Sve razumem ali mi nije mi jasno od 31. - 37.
Ne moras puno filozofirati, ako znas c++ onda i sam znas koliko si ucio i da li je lako. C jezik je svakome laksi nego C++.
Ja mislim da nikome nisam trazio gotov kod sa copy-paste. Ja kod mogu okaciti ali mislim da ce malo vas razumeti jer je sastavljen od registara, nije prost kao arduino.
Ja sam trazio-zamolio algoritam, ne kod ! Znaci smisao, predlog, neku sliku kao ilustraciju. video neki itd... Tu rec DUSMANI nisam ovde izgovorio, ti si je izgovorio !
[ zica49 @ 24.04.2015. 20:23 ] @
Okaci kod da vidimo.
[ diwljina @ 24.04.2015. 20:39 ] @
Povezao sam enkoder na motor pa pored tolikog kod-a kacim samo interapt rutinu jer u njoj to radim.

#define MR0I_CHANNEL_A (1<<4)
#define MR0I_CHANNEL_B (1<<5)
------------------------------
__irq void T0ISR(void) // kada se desi interapt ...
{
static int value;
int vrednost;
char jbuffer [20];

value = T0IR;
snprintf(jbuffer,20,"%d",vrednost);

// ako stigne impuls na kanal a ( a kanal a je port na mcu) , i ako stigne impuls na kanal b, inkrementiraj vrednost pozicije
if( T0IR & MR0I_CHANNEL_A )
{
if( T0IR & MR0I_CHANNEL_B)
vrednost++;
}

// ako stigne impuls na kanal b ( a kanal a je port na mcu) , i ako stigne impuls na kanal a, dekrementiraj vrednost pozicije
if( T0IR & MR0I_CHANNEL_B )
{
if( T0IR & MR0I_CHANNEL_A)
vrednost--;
}
UART0_Ispisi_Tekst(MOJTIP jbuffer);
/*ovde ide jos neki kod ali nije vazan, vezano je za resetovanje itd... ne krijem nista, da ne mislite, vec sam kacio na drugim forumima kod pa su mi trazili samu srz*/
}
[ goran_68 @ 24.04.2015. 20:57 ] @
Ovoliki kod u prekidnoj rutini nije dobra praksa. Pogotovo tu nema mesta ovoj serijskaoj komunikaciji. To se sve radi kada izađeš iz prekidne rutine. Prekidna rutina samo beleži šta se i kad dogodilo. Sve ostalo ide van.

Ovo nikako ne ide ovako:

Code:

// ako stigne impuls na kanal a ( a kanal a je port na mcu) , i ako stigne impuls na kanal b, inkrementiraj vrednost pozicije
if( T0IR & MR0I_CHANNEL_A ) 
{    
if( T0IR & MR0I_CHANNEL_B)
vrednost++;
}


Moraš da imaš prethodno stanje (kada je stigao neki signal) i sadašnje. Upoređivanjem određuješ šta se dogodilo.

Probaj kod sa linka koji si dobio.
[ ColdKeyboard @ 24.04.2015. 20:59 ] @
Ne znam kako su ti podeseni interrup-i, trebalo bi da su interrupt on change, tj. i na silaznu i na uzlaznu ivicu od oba ta kanala.

Ako su ti na istom portu svi pinovi, posmatraj ih sve istovremeno.

Takodje treba da imas uvid u prethodno stanje + trenutno stanje, na osnovu toga racunas da li se motor vrti na jednu ili na drugu stranu.
Ako hoces brzinu, onda pored prethodnog stanja dodas i neki tajmer, kada se desi interrupt zapises vreme, u sledecem interrupt-u uzmes novo vreme - staro i dobio si koliko je vremena proslo, a na osnovu pozicije enkodera znas koliko se motor pomerio, podelis predjeni put sa vremenom i imas brzinu.

Kako ti se zove port na kome su ti nakaceni ulazni signali enkodera i kako si podesio interrupt?
[ diwljina @ 24.04.2015. 22:54 ] @
Obojica ste u pravu. Ne razumem ovaj deo sa linka od 31. do 37 linije koda.

U interaptu sam ja podesio kada stigne impuls, kakav god. Ali ja mogu da stavim (MISLIM) ali to nisam uspeo jos, da kada stigne rastuca ili opadajuca ivica da se desi irq.
Nisu port 2 je a , port 4 je b, port 6 je I...

Taj uvid ne znam kako, jer ja ga restartujem i postavim na 0, a sto se tice brzine to znam, to nije tesko...
[ veselinovic @ 25.04.2015. 06:47 ] @
Ja bih razmisljao malo o hardverskim poboljsanjima.
Recimo, stavio bih jedno EXOR kolo, na ulaze doveo A i B. Na izlazu dobijem signal za interapt.
Ima jos hardverskih mogucnosti za dalju obradu interapta, pa bi se moglo dobiti dva signala
X i Y, gdje je X inkrementiranje a Y dekremntirane.
Probaj nije tesko.
Evo ti ideja za interapt signal.
U eri mikrokontrolera cesto se zaboravi digitalna elektronika, a moze mnogo pomoci.
[ mikikg @ 25.04.2015. 10:11 ] @
@veselinovic

Da to moze da bude od pomoci ali u sustini nema nesto preterane potrebe za tim.

Interapt rutina ISR mora (veoma preporucljiva) da se u svakom slucaju koristi.
Kad se vec udje u ISR, par komandi vise-manje ne pravi neku bitnu razliku.

Cak pojedini MCU imaju interno specifican hardware za baratanje sa njima (QE modul, npr STM32F3 i F4 uglavnom imaju), predvidjeni za vrlo brze signale koji rade nezavisno od procesora i posle se samo periodnicno po potrebi cita njihovo stanje.

---

Sto se tice C i C++, kod Keil uVision su skoro svi primeri uradjeni u C++, koriste se objekti i strukture (variable) i ako se to ne razume, to je ogroman hendikep za programera!
Naravno, moze i bez C++ ali onda mora da se poznaje detaljno HW i odprilike se tako onda stize na Asemblerski nivo jer mora da se poznaju svi registri i sta/koji rade.

---

Dalje, sta ovde nije jasno?
Ovo je C jezik, koriste se nizovi i osnovne logicke operacije (shift, and, or)?!
Ako ovo nije jasno, hmm, taj programer je u velikom problemu ...

Code:
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}




[ draganko2000 @ 28.04.2015. 13:06 ] @
Evo dio koda u mikroC PRO for PIC, koji u prekidnoj rutini odredjuje smjer vrtnje enkodera.


sbit enkoderA at RB0_bit;
sbit enkoderB at RB1_bit;
sbit enkoderA_Direction at TRISB0_bit;
sbit enkoderB_Direction at TRISB1_bit;

long impENKO=0;

GIE_bit=1; // Omoguci sve prekide
INT0IE_bit=1; // Omoguci vanjski prekid na RB0 (INT0)
INTEDG0_bit=1; // prekid na POZITIVNU ivicu na RB0

.
.
.

void interrupt() {

if (INT0IF_bit==1) { // prekid sa RB0

if(enkoderB==0) impENKO++; // smjer CW,
if(enkoderB==1) impENKO--; // smjer CCW,

INT0IF_bit=0;
}

}

Da bi se dobilo 2x vise impulsa potrebno je omoguciti prekid i na zadnju ivicu na RB0.
Ako bi se koristio prekid na prednju i zadnju ivicu na RB1 (kao na RB0) dobili bi 4x vise impulsa!
[ bogdan.kecman @ 28.04.2015. 13:55 ] @
@draganko, jedina mana toga sto si stavio je sto moras da imas dobar externi debouncing inace ces da imas haos, kad se malo zaprlja enkoder krenes da dobijas signale napred nazad ko blesave, posebno kod mehanickih enkodera

ima sema, zas011 je stavljao vec 2-3 puta, da sa enkodera direkt dobijes + i - signal, 2 flipflopa

na primer


za encoder rutinu sa debouncingom pogledaj https://sourceforge.net/p/arhi...EAD/tree/SID/SID_GEN4.X/main.c
isr je od linije 184

Code:

    if (INTCON3bits.INT1IF) { //ENC1 falling edge
     if ((isr_started - debounce_B_prev) > DEBOUNCE_TIME)  {
            if (PIN_E2) {
                if (encoder > encoderMIN) encoder--;
                changed = 1;
                debounce_B_prev = isr_started;
            } else {
                if (encoder < encoderMAX) encoder++;
                changed = 1;
                debounce_B_prev = isr_started;
            }
        }
        INTCON3bits.INT1IF = 0;
        
    } else if (INTCON3bits.INT2IF) { //ENC2 falling edge    
        if (isr_started - debounce_B_prev > DEBOUNCE_TIME) {

#ifndef DETENT_DOUBLE
            if (PIN_E1) {
                if (encoder < encoderMAX) encoder++;
                changed = 1;
                debounce_B_prev = isr_started;
            } else {
                if (encoder > encoderMIN) encoder--;
                changed = 1;
                debounce_B_prev = isr_started;
            }
#endif
        }
        INTCON3bits.INT2IF = 0;
    } else if ...

[ draganko2000 @ 28.04.2015. 14:44 ] @
Signale od enkodera (A i B) prenosim preko RS485, a prije enkodera koristim i optokapler sa s
mit trigerom.
[ bogdan.kecman @ 28.04.2015. 14:57 ] @
kao sto rekoh neophodan je externi debouncing, kako ces isti da izvedes nebitno je .. ja sam do duse poceo da dodajem sw debouncing cak i kada postoji hardwerski, opekoh se par puta
[ draganko2000 @ 28.04.2015. 15:05 ] @
Hvala na sugestiji za sw debouncing.
[ bogdan.kecman @ 28.04.2015. 15:24 ] @
nema na cemu, kao sto vidis to je samo par linija koda vise, nista znacajno, naravno podrazumeva da imas neki tajmer u kodu no ako radis bilo sta ozbiljno verovatno vec imas tako da te to nista ne kosta (kod mene ako pogledas ceo fajl vidis da ima "millis" varijabla koja se inkrementuje za 2 u tajmeru na svake dve milisekunde) .. ako imas vec hw debouncing idealno je da izracunas vreme koje debounceuje hw i isto vreme podesis za sw tako da sve radi skladno ali ako hw slucajno zakaze (npr iscuri ti kapacitet konda pred schmidt-om posle godinu dana) sw to iskompenzuje i sve i dalje radi kako treba :) ... e sad kad te mrzi da racunas, stavis neko vreme za sw debounce da ti enkoder radi lepo bez hw debouncinga i onda vratis nazad hw i vozi misko :D