www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

Enkoder krmili koračni motor
Pojdi na stran 1, 2, 3  Naslednja
 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Programiranje embedded sistemov
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Pet Maj 09, 2014 1:21 pm    Naslov sporočila:  Enkoder krmili koračni motor Odgovori s citatom

Pozdravljeni,
imam končan program za krmiljenje koračnega motorja z signalom A in B od enkoderja. Vendar rad bi spreminjal hitrost na koračnem motorju kot to počne reduktor. Ampak brez česovnih funcij delay, ker če jih uporabim mi dejansko upočasni koračni motor, ampak pri večji hitrosti enkoderja se izgubi signal in se motor ne vrti sorazmerno z enkoderjem.
Naprimer če uporabim časovno funkcijo in zavrtim enkoder počasi 1 krog mi naredi motor 2 kroga. Če pa hitro zavrtim enkoder 1krog z 1000rpm mi motor obrne manj kot 1/2 kroga. Mogoče kakšna matematična funkcija bi zadevo usposobila. Ker sem bolj začetnik mi to nikakor ne uspeva. Prosim za pomoč. LP
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Pet Maj 09, 2014 1:26 pm    Naslov sporočila:   Odgovori s citatom

Dodal sem usingned in odstranil delayMicroseconds
ŠE koda:
#define encoder_a 2 //keep this on and interrupt pin
#define encoder_b 3 //keep this on and interrupt pin
#define motor_step 4 //can be any pin
#define motor_direction 5 //can be any pin

#include <delay.h>
volatile long motor_position, encoder;
unsigned long WaitReverse = 1; //<<<
unsigned long WaitForward = 1; //<<<
unsigned long StartReverse = micros(); //<<<
unsigned long StartForward = micros(); //<<<
unsigned long microsNow = micros(); //<<<

void setup () {
//set up the various outputs
pinMode(motor_step, OUTPUT);
pinMode(motor_direction, OUTPUT);

// then the encoder inputs
pinMode(encoder_a, INPUT);
pinMode(encoder_b, INPUT);
// enable pullup as we are using an open collector encoder
digitalWrite(encoder_a, HIGH);
digitalWrite(encoder_b, HIGH);

// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, encoderPinChangeA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, encoderPinChangeB, CHANGE);
encoder = 0; //reseet the encoder position to 0
}

void loop() {
//do stuff dependent on encoder position here
//such as move a stepper motor to match encoder position
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying
microsNow = micros(); //<<<

if ((encoder > 0) && ((microsNow - StartReverse) > WaitReverse)) {
digitalWrite(motor_direction, HIGH);// move stepper in reverse
digitalWrite(motor_step, HIGH);
digitalWrite(motor_step, LOW);
//delayMicroseconds(600); //_delay_us(200); //modify to alter speed <<<
motor_position++;
encoder = 0; //encoder--;
StartReverse = micros(); //<<<
}
else if ((encoder < 0) && ((microsNow - StartForward) > WaitForward)) {
digitalWrite (motor_direction, LOW); //move stepper forward
digitalWrite (motor_step, HIGH);
digitalWrite (motor_step, LOW);
//delayMicroseconds(600); //_delay_us(200); //modify to alter speed <<<
motor_position--;
encoder = 0; //encoder++;
StartForward = micros(); //<<<
}
}

void encoderPinChangeA() {
if (digitalRead(encoder_a) == digitalRead(encoder_b)) {
encoder--;
}
else {
encoder++;
}
}

void encoderPinChangeB() {
if (digitalRead(encoder_a) != digitalRead(encoder_b)) {
encoder--;
}
else {
encoder++;
}
}
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Obelix
Član
Član



Pridružen-a: Pon 19 Maj 2008 13:59
Prispevkov: 1862
Aktiv.: 9.64
Kraj: Maribor

PrispevekObjavljeno: Pet Maj 09, 2014 1:54 pm    Naslov sporočila:   Odgovori s citatom

Reduktor zmanjša vrtljaje elektromotorja v odvisnosti od prestavnega razmerja.

Torej bi rad izdelal "elektronski reduktor" ?

Če se enkoder vrti na primer s 100 vrtljaji na minuto, bi se naj koračni motor vrtel na primer s 50 vrtljaji na minuto ?
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Pet Maj 09, 2014 5:48 pm    Naslov sporočila:   Odgovori s citatom

Nekaj takšnega samo, da se enkoder vrti z 1200rpm motor pa 190rpm in se sorazmerno lahko spreminja hitrost med enkoderjem in motorjem. Je to možno, ker na ardoino forumi ni bilo takšnega junaka, ki bi mi lahko pomagal.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
vpeter
Član
Član



Pridružen-a: Pon 11 Jun 2012 16:05
Prispevkov: 337
Aktiv.: 2.35
Kraj: Maribor okolica

PrispevekObjavljeno: Pet Maj 09, 2014 8:30 pm    Naslov sporočila:   Odgovori s citatom

Svetujem ti, da problem razdeliš na posamezne dele in jih posebej preveriš.

Preveri ali lahko vrtiš motor s pravo hitrostjo - hitrost nastavi z neko konstanto v kodi. Nato preveri ali sploh lahko dovolj hitro registriraš hitrost enkoderja. Recimo z neko spremenljivko, ki jo povečuješ. Ko boš potrdil delovanje posameznih delov pa jih združi v celoto. Sedaj namreč imaš en kompleksen program, ki ga verjetno niti ne razumeš v celoti. Zaradi tega tudi ne veš kje iskati vzrok težav.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
jerjur
Član
Član



Pridružen-a: Čet 06 Maj 2010 22:09
Prispevkov: 459
Aktiv.: 2.71
Kraj: Žiri

PrispevekObjavljeno: Pet Maj 09, 2014 9:05 pm    Naslov sporočila:   Odgovori s citatom

Najprej preveri z katero najvišjo frekvenco ti procesor še pravilno bere enkoder.
potem zračunaj hitrost vrtenja enkoderja, potem deli z razmerjem prenosa. potem pa generiraj nov niz pulzov, ki bo popolnoma neodvisen od enkoderja. Samo takšen program bo deloval.

_________________
Avtomatika je zakon
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
int47
Član
Član



Pridružen-a: Pon 15 Dec 2003 0:10
Prispevkov: 2066
Aktiv.: 9.30
Kraj: Ljubljana

PrispevekObjavljeno: Pet Maj 09, 2014 10:39 pm    Naslov sporočila:   Odgovori s citatom

Kaj, če bi uporabil kaj takšnega.
Za to ne rabiš FPGA-jev. Uporabi D flip-flope in EXOR vrata.
Prestavno razmerje nastaviš z ustrezno izbiro enkoderja in koračnega motorja.

Še ena shema, ki ne rabi extra clock signala je tukaj.

Če je zelo pomembno, da se pri spremebi smeri, ali zaustavitvi ne zgubi, ali pridobi noben korak, preveri in presimuliraj delovanje.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Sob Maj 10, 2014 10:39 am    Naslov sporočila:   Odgovori s citatom

Zanimljiva in enostavna zadeva ampak moj načrt je tak.
S tem da bom uporabil boljši driver koračnega motorja in 3A koračni motor.



Encoder driver stepper motor.jpg
 Opis:
 Velikost datoteke:  856.98 KB
 Pogledana:  13 krat

Encoder driver stepper motor.jpg


Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
int47
Član
Član



Pridružen-a: Pon 15 Dec 2003 0:10
Prispevkov: 2066
Aktiv.: 9.30
Kraj: Ljubljana

PrispevekObjavljeno: Sob Maj 10, 2014 11:56 am    Naslov sporočila:   Odgovori s citatom

A3967 zahteva minimalno širino step impulza 1us.
Zakaj je spremenljivka encoder tipa long, če je njena vrednost samo -1, 0 in 1?

Ne vem, kako se digitalRead() prevede. Klic funkcij iz prekinitvene rutine samo za branje stanja enega pina ni najboljša ideja.
Poleg tega stanji encoder_a in encoder_b nista prebrani hkrati. Na začetku prekinitvene rutine v spremenljivko shrani stanje ustreznega porta.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
hamm
Član
Član



Pridružen-a: Sob 27 Okt 2012 21:47
Prispevkov: 216
Aktiv.: 1.55
Kraj: Mengeš

PrispevekObjavljeno: Sob Maj 10, 2014 12:25 pm    Naslov sporočila:   Odgovori s citatom

Kateri enkoder uporabljaš?
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Sob Maj 10, 2014 11:28 pm    Naslov sporočila:   Odgovori s citatom

Encoder je iskra 500pulzni, testiram tudi iz epson printerja.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Jaka57
Moderator
Moderator



Pridružen-a: Ned 12 Dec 2004 21:47
Prispevkov: 5766
Aktiv.: 25.97
Kraj: Grosuplje

PrispevekObjavljeno: Ned Maj 11, 2014 12:21 am    Naslov sporočila:   Odgovori s citatom

int47 je napisal/a:
A3967 zahteva minimalno širino step impulza 1us.
Zakaj je spremenljivka encoder tipa long, če je njena vrednost samo -1, 0 in 1?

Ne vem, kako se digitalRead() prevede. Klic funkcij iz prekinitvene rutine samo za branje stanja enega pina ni najboljša ideja.
Poleg tega stanji encoder_a in encoder_b nista prebrani hkrati. Na začetku prekinitvene rutine v spremenljivko shrani stanje ustreznega porta.

Ja, jaz sem obupal, kajti tema se je začela tukaj, kako bi napisal 32 bitni program za AVR, kajti program (Arduino sketch) je kao napisan v 8 bitnem načinu za Arduino ARM board (Arduino DUE) in je prepočasen.
Iz tega prispevka mi je bilo popolnoma jasno, da ni nič jasno, kar se tudi vidi iz definicij spremenljivk (long za stanja -1, 0 in 1)!
Prav tako, sem omenil, da vsaka prekinitvena rutina potrebuje določen čas, da gre v int in se iz inta vrne, pa če v sami rutini kaj naredi ali ne.
Ja, digitalRead() je funkcija, ki se prevede kakor se in je čisto lepo uporabna, če nimaš časovno zahtevnih operacij, kakorkoli, tudi to je bilo razloženo, kako se to naredi, da je to procesorsko najkrajše v Cju za nek Arduino board z mego328.
Ampak, mislim, da je osnovni problem v aritmetiki, tj. seštevanje mikrosekund in razumevanje le te aritmetike oz. koliko impulzov lahko gre v 1us, da motor naredi en korak in med to 1us in naslednjo mora biti tudi presledek, kanede? Brick wall .

_________________
Lp, Jaka
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Ned Maj 11, 2014 5:25 pm    Naslov sporočila:   Odgovori s citatom

Jaka57, ta program je bil že napisan za mini in naj bi deloval. Ko pa sem zadevo testiral nisem bil zadovoljen. Poskušal sem program popravit, dodat funkcijo direction manipulation port, ampak ne, še vedno je problem z izgubo signala na motorju. Potem sem testiral z DUE, arm 32bit je precej hitrejša in tudi tukaj je enak problem. Po mesecu testiranja, obiskov forumov, iskanje pomoči sem dojel in se nekaj naučil, da ni problem v plošči ampak v programu. Zato sem poskušal zmanjšati iz 200MicroS na 100 nato na 10microS no pri 10 in 1 se signali niso več gubili. Sedaj pa kako lahko ta program naredim še z boljšim, da lahko nastavlajm obrate na motorju kot jih reduktor. Tukaj se je pa ustavilo. Zagotovo nekdo na forumu ve kako bi se lotil te zadeve. Jaz žal tukaj nisem doma in z arduino sem začel pred 2 meseci, ter sem skoraj že obupal ampak, še se trudim.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
igo
Član
Član



Pridružen-a: Sre 11 Okt 2006 19:11
Prispevkov: 3638
Aktiv.: 17.11

PrispevekObjavljeno: Ned Maj 11, 2014 7:10 pm    Naslov sporočila:   Odgovori s citatom

Še dobro, da ne uporabljam Arduino okolja ...
Koda:

// Ob zaznanem koraku enkoderja nazaj se poveča EnNaprej in zmanjša EnNazaj
// Ob zaznanem koraku enkoderja naprej se zmanjša EnNaprej in poveča EnNazaj
void encoderPinChangeA()
{
  if (digitalRead(encoder_a) == digitalRead(encoder_b))
    {
    EnNaprej--;
    EnNazaj++;
    }
    else
    {
    EnNaprej++;
    EnNazaj--;
    }
}

void encoderPinChangeB()
{
  if (digitalRead(encoder_a) != digitalRead(encoder_b))
    {
    EnNaprej++;
    EnNazaj--;
    }
    else
    {
    EnNaprej--;
    EnNazaj++;
    }
}


// Tako se ohrani PrestavnoRazmerje med vhodnimi impulzi iz enkoderja in izhodnimi impulzi za gonilnik koračnega motorja
// Primer:
// Naj bo PrestavnoRazmerje 20 impulzov enkoderja (E-impulzi) = 1 impulz motorja (M-impulzi).
// Narediš 15 E-impulzov v smeri Naprej, nato narediš 25 E-impulzov v smeri Nazaj.
// Imaš 2 možnosti interpretacije.
// 1. možnost:
// Ker v smeri Naprej nisi dosegel PrestavnegaRazmerja, motor ne bo dobil M-impulza Naprej. Nazaj pa si presegel 20 E-impulzov, zato bo motor dobil M-impulz Nazaj, 10 presežnih impulzov pa se bo upoštevalo v kvoto za naslednji M-impulz Nazaj.
// 2. možnost:
// Ker v smeri Naprej nisi dosegel PrestavnegaRazmerja, motor ne bo dobil M-impulza Naprej. Nazaj pa si sicer presegel 20 E-impulzov, a si moral najprej priti do prejšnjega stanja EnNazaj, torej preden si zavrtel 15 E-impulzov Naprej. Torej si začel odštevati od 35 (PrestavnoRazmerje+15), zato motor ne bo dobil M-impulza Nazaj, saj števec EnNazaj po 25-Eimpulzih Nazaj še ni prišel do 0.

// Če je zahtevana pozicijska natančnost, uporabiš 2. možnost.
// Ko se en števec  zmanjšuje, se drugi povečuje.
// V zanki se gleda, kdaj je EnNaprej ali EnNazaj enak 0.
// Ko je eden izmed njiju enak 0, dobi gonilnik impulz ustrezne smeri, oba števca pa se postavita na stanje PrastavnoRazmerje.
// Ker se v prekinitvi en zmanjšuje, drug pa povečuje, ne moreta biti hkrati 0.
// 0.....EnNaprej.....PrestavnoRazmerje....................2*PrestavnoRazmerje-1
// 0..........PrestavnoRazmerje...........EnNazaj..........2*PrestavnoRazmerje-1
// ali
// 0..........PrestavnoRazmerje.........EnNaprej...........2*PrestavnoRazmerje-1
// 0.....EnNazaj.....PrestavnoRazmerje.....................2*PrestavnoRazmerje-1

void loop()
{
  if (EnNaprej==0)
    {
    digitalWrite (motor_direction, LOW); //move stepper forward
      EnNaprej=PrestavnoRazmerje;
    digitalWrite (motor_step, HIGH);
      EnNazaj=PrestavnoRazmerje;
    digitalWrite (motor_step, LOW);
    }   
  if (EnNazaj==0)
    {
    digitalWrite(motor_direction, HIGH);// move stepper in reverse
      EnNazaj=PrestavnoRazmerje;
    digitalWrite (motor_step, HIGH);
      EnNaprej=PrestavnoRazmerje;
    digitalWrite (motor_step, LOW);
    }
}
//Ker je vsaka vrstica v if stavku sestavljena iz vsaj nekaj ukazov, ki trajajo ___ mikrosekund, se z mešanjem vrstic odpravi potreba po mikro pavzah pri M-impulzih za gonilnik motorja.
Ne da se mi računati, vrednosti konstante PrestavnoRazmerje.
Važno je le, da je tip (int, long,...) spremenljivk EnNaprej in EnNazaj takšen, da je z njim možno zapisati dvakratno vrednost konstante PrestavnoRazmerje.

dodano:
500Ei = 1Eo
1200rpm [Eo/min] = 600000Ei/min = 10000Ei/sek

200Mi = 1Mo
190rpm [Mo/min] = 38000Mi/min = 633,33Mi/sek

PrestavnoRazmerje = 15,789474...Ei/Mi

Ei so Enkoderjevi impulzi
Eo je Enkoderjev obrat
Mi so Motorjevi impulzi
Mo je Motorjev obrat

Cela konstanta je torej 15 ali 16.
Če rabiš točno, je pa "malo" več hecanja (poudarek je na besedici "več").
Prestavno razmerje=15 Ei/Mi
Na vsak drug Mi dodaš še en Ei.
Na vsak četrti Mi dodaš še en Ei.
Na vsak 28. Mi dodaš še en Ei.
Na vsak 280. Mi dodaš še en Ei.
...
Odšteješ celo število, decimalke pomnožiš z "a", da je več kot 1.
Odšteješ celo število in decimalke pomnožiš z "b", da je več kot 1.
...
K= celo št + 1/a + 1/(a*b) + 1/(a*b*c) + 1/(a*b*c*d) ...
a=2 , b=2 , c=7 , d=10 , ...

To pomeni, da je Prestavno razmerje sproti spreminja.
Ob vsakem novem Mi (znotraj if(EnNaprej==0) oklepaja) pod že obstoječimi vrsticami dodaš:
Zmanjšaš števec A--.
Ko je 0 (if A==0), dodaš Ei++ in A=2.
Zmanjšaš števec B--.
Ko je 0 (if B==0), dodaš Ei++ in B=4.
Zmanjšaš števec C--.
Ko je 0 (if C==0), dodaš Ei++ in C=28
Zmanjšaš števec D--.
Ko je 0 (if D==0), dodaš Ei++ in D=280 (to je pa že problem pri 8-bitnih int številih)

Na neskončno decimalk žal ne bo šlo nikoli.

Saj matematika super deluje. Teoretično. Praktično pa jo je treba samo uporabiti.

Ali uporabiti celoštevilsko PrestavnoRazmerje (pri K=16 je 187,5Mo/1200Eo).

_________________
Teoretično je praksa posledica teorije, praktično je pa ravno obratno. (igo 2001)
LP, Igor
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo Pošlji E-sporočilo
Mikim
Član
Član



Pridružen-a: Ned 10 Okt 2010 1:11
Prispevkov: 141
Aktiv.: 0.86
Kraj: Brežice

PrispevekObjavljeno: Pon Maj 12, 2014 8:49 pm    Naslov sporočila:   Odgovori s citatom

Odlično Igor,
a žal zadeva mi nikako ne uspe. Skoz imam neke napake v programu.
nekako mi ni jasno z (EnNaprej) tega arduino koda na razume.
Še veliko se bom moral učit, da te zadeve začnem razumet.
LP
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> Programiranje embedded sistemov Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Pojdi na stran 1, 2, 3  Naslednja
Stran 1 od 3

 
Pojdi na:  
Ne, ne moreš dodajati novih tem v tem forumu
Ne, ne moreš odgovarjati na teme v tem forumu
Ne, ne moreš urejati svojih prispevkov v tem forumu
Ne, ne moreš brisati svojih prispevkov v tem forumu
Ne ne moreš glasovati v anketi v tem forumu
Ne, ne moreš pripeti datotek v tem forumu
Ne, ne moreš povleči datotek v tem forumu

Uptime: 47 dni


Powered by phpBB © 2001, 2005 phpBB Group