Arduino és a rotary enkóder

Processing/Wiring (illetve C) nyelvű programozási fogások, tippek. (AVR-Duino, Arduino, EthDuino, Diecimila, Severino, Nano, LilyPad)
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Arduino és a rotary enkóder

Hozzászólás Szerző: SzLacus »

Kezdőként birkózom egy mechanikus rotary enkóderrel(+push button), gyakorlandó a be és kimenetek kezelését, és a megszakítás kezelést. Amíg pollingoztam a dolog működött, nyilván a polling korlátaival. Akkor a megszakítás felé, vettem az irányt, ott majd nem kések le semmit. Nem ám, de a prell az tréfás dolog. Adtam neki 100 nanót, meg a kontakt kímélése érdekében a 100 ohmról se feledkeztem meg, az majd megfékezi. Hát nem teljesen, erre hamar rá kell jönnöm. Gondoltam, hogy kevés a belső felhúzó, toltam rá 1k-t. Természetesen ez sem oldotta meg, számolt ide-oda, de tévesztett néha. Ha gyorsan tekertem, akkor még bizonytalanabb volt a működés. A szerkezet a Lehel út, Dévai út sarkáról (így talán nem reklám :) ) származik, és a 100-150 csengő magyar forintos kategóriában indul. Gondoltam, kontakt hibás, és akkor is van megszakítás amikor nem kellene, ezért vásároltam egy ugyan olyan példányt, csak arra négyszer annyiért rá van írva a Bou-val kezdődő brand gyártó neve. Ennyit megér egy jól működő darab gondoltam, a barand az barand. De az is prelles, és kontaktos, nem is kicsit. Akkor sw-ból kell ezt megoldani, nincs mese. Azt gondoltam program sorokba önteni, amit a kapcsolónak csinálnia kell. Megszakítást használni két csatornán, külön fel és lefutó élre, az egyik esemény bekövetkezte után letiltani az aktuális megszakítást amin bejött (így a prell kicsukva) és kaput nyitni a következő eseménynek a várt megszakítás engedélyezésével. Amikor a várt esemény érkezik, akkor a másik csatorna tökéletesen stabil állapotban van, (kell hogy legyen) annak elemzéséből lehet tudni, hogy fel vagy lefutó élre kell számítani a következő lépésben. A csatornák láthatóvá tételére két led pont elég, az élek azonosítására pedig a soros porton kiküldött szöveg megfelelő. Amikor zavaróan sok az egymás alatti szöveg a button megnyomásával egy sor csillag küldhető a soros portra. A kód így néz ki.

Kód: Egész kijelölése

int val=0;
boolean send=false;
int button=8;
int rotaryA=2;    //int0
int rotaryB=3;    //int1
//int rotaryA=9;    //no int
//int rotaryB=10;    //no int
int zoldLed=11;
int pirosLed=12;
int fixLed=13;
volatile int encoderPos = 0;

void setup(){
pinMode(button, INPUT);
digitalWrite(button, HIGH);    //Belső felhúzóval
pinMode (rotaryA, INPUT);      //Külső Felhúzó
pinMode(rotaryB, INPUT);      //Külső PullUp
pinMode (9, INPUT);
pinMode(10, INPUT);
pinMode(zoldLed, OUTPUT);
pinMode(pirosLed, OUTPUT);
pinMode(fixLed, OUTPUT);

/*
Amikor a mehanikus "röcögtetője" fix pozíciót ad, akkor az A érintkező fix helyzetű
*/
if (digitalRead(rotaryA) == HIGH){      //Ha az A csatorna magas 
  attachInterrupt(0, rotaryHandlingLowA, RISING);}  //akkor lefutó él jön
  else{
  attachInterrupt(0, rotaryHandlingHighA, FALLING);}    //egyébként felfutó követketik
digitalWrite (zoldLed, digitalRead(rotaryA));
digitalWrite (pirosLed, digitalRead(rotaryB));
Serial.begin(9600);
Serial.println("START");
}

void loop(){
if ((send == false) && (digitalRead(button) == false)){
send=true;
Serial.println("***************");
}
if (digitalRead(button) == HIGH){
send = false;
}
}

void rotaryHandlingLowA(){
detachInterrupt(0);
digitalWrite (zoldLed, LOW);    //Debug
Serial.println("A le");
if (digitalRead (rotaryB) == LOW){    //Ha a másik vonal alacsony,
  attachInterrupt (1, rotaryHandlingHighB, FALLING);} //akkor magas következik
  else{
  attachInterrupt (1, rotaryHandlingLowB, RISING);  //Ha magas volt alacsony következik
  }
}

void rotaryHandlingHighA(){
detachInterrupt(0);
digitalWrite (zoldLed, HIGH);
Serial.println("A fel");
if (digitalRead (rotaryB) == LOW){
  attachInterrupt (1, rotaryHandlingHighB, FALLING);}
  else{
  attachInterrupt (1, rotaryHandlingLowB, RISING);
  }
}

void rotaryHandlingLowB(){
detachInterrupt(1);
digitalWrite (pirosLed, LOW);
Serial.println("B le");
if (digitalRead (rotaryA) == LOW){
  attachInterrupt (0, rotaryHandlingHighA, FALLING);}
  else{
  attachInterrupt (0, rotaryHandlingLowA, RISING);
  }
}

void rotaryHandlingHighB(){
detachInterrupt(1);
digitalWrite (pirosLed, HIGH);
Serial.println("B fel");
if (digitalRead (rotaryA) == LOW){
  attachInterrupt (0, rotaryHandlingHighA, FALLING);}
  else{
  attachInterrupt (0, rotaryHandlingLowA, RISING);
  }
}
Sajnos a működés továbbra is kívánni valót hagy maga után, mert a ledek egyáltalán nem azt mutatják, amit várnék tőle. És a com poton vett szöveg sem az, ami elvárható helyes működés esetén. Az ablakban ez van.
START
A fel
B le
A fel
B le
A le
B le
A le
Az a probléma, hogy egy csatorna kétszer egymás után ugyan abba az irányba nem lépet. Ahhoz hogy fel léphessen előtte le kell lépnie, és meg is teszi, mert a működést szkópon lestem. Az ábrát is csatolnám, ha tudnám hogyan kell. Így most csak legenda, de az ábra jó működést mutat az enkóder lábán.
A lényeg, hogy kimaradnak megszakítások, nem jön az aminek kellene, ezért tud úgy röccenni (hopp egy szakkifejezés) az enkóder, hogy nem változik a led, és a sorosra sem érkezik meg minden várt szöveg. Azt gondolom, hogy a megszakítás tiltás/engedélyezés körül lehet a gond. Vagy nem is így kell ezt csinálni, hogy eldobom, majd újra felveszem a megszakítást? Tud valaki segíteni? Van valakinek ötlete? Én meg közben megnézem szkóppal, hogy a proc lábát kímélő pár száz ohm proc felé eső lábán is korrekt-e a jel.
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Hozzászólás Szerző: SzLacus »

Az Arduino lábán is korrekt a jelfolyam, az a pár 100 ohm sorosan nem szól bele a mókába. Jól kéne kezelnem a megszakítás tiltását? Vagy máshol van a csapda? A GIFR regiszterről olvastam, de azt feltételezem, hogy a megszakítás felvételekor ezt kezelnie kell az attachInt-nek, nem nekem kell a regisztert macerálnom. És a jelenség sem az, hogy kétszer fut a megszakítás. Annál is inkább, mert amikor reset után legelőszöt fut a setupban az attachInt-, akkor is ki kéne üzenjen, de nem teszi. Ebből gondolom, hogy a GIFR kezelve van.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Na jól elszálltál. Mi ez űrprogram?

Igaz bascom de csak ennyi a megszakítás:
http://avr.tavir.hu/modules.php?name=Co ... age&pid=19

Kontakt enkóder használata
Getencoder:
Waitms Debouncetime
If Cha = 0 Then
If Chb = 0 Then Incr Encounter Else Decr Encounter
End If
Gifr = 64
Return
:D
Avatar
ampervadasz
Bitmanipulátor
Hozzászólások: 119
Csatlakozott: 2008. január 19. szombat, 7:00

Hozzászólás Szerző: ampervadasz »

Olcsó encodernek...

Tudom melyik fajta (EC-11). Bizonytalan működésű még BASCOM alól is! Ócó kici kinai...
Javaslat: Jobb kéz, ball vál, 45 fokban eldob.

Fél évet kínlódtam vele, mire rászántam magam, hogy kimérem szkóppal. Borzadalom...
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Hozzászólás Szerző: SzLacus »

Az óccó, gagyitron gyártmány, az teljesen igaz, de a Bourns gyártmány is pont azt csinálja. Az meg se óccó, se noname. Sőt a noname az kicsit határozottabban arretál, (szakkifejezéssel röccen :) ) ami nekem jobban bejön, mert határozottabban áll meg egy-egy fix helyzetben. Azt hiszem, hogy használhatónak kell lennie, különben eltűnne a piacról. Ahogy az MC14490 prell mentesítő IC sincs raktáron, a legtöbb helyen rendelhető státusban van. Az áráról ne is beszéljünk. Ez lecsippentené a prellt, de ilyen áron inkább ne tegye.
Kapu48-nak köszönet a linkekért, én is onnan indultam, és pont ilyen egyszerű volt a kód is. Csak nem vezetett eredményre, ezért kellett eddig a szétdarabolt működési fázisokat követő agymenésig eljutnom. Azzal, hogy a megfelelő élt engedem csak és mindíg csak azon a csatornán aminek következnie kell, elérem, hogy az átlós csatornát akkor vizsgálom amikor az stabil helyzetben van. Úgy gondolom, hogy ezzel kivédhető a prell is, meg a kontakt hiba is. Kivéve azt az esetet, amikor a megszakítással ellentétes csatorna, a vizsgálat pillanatában kontakt hibázik, miközben már régen stabil állapotban kéne hogy legyen. Erre nincs orvosság. Az hamis irányú impulzus lesz menthetetlenül. De erre elég kicsi az esély.
Aludtam egyet a problémára és azt találtam ki, hogy kiveszem az enkódert és a helyére teszek két tranyót, amit a loopban úgy vezérelek másik két proc lábról, mint ahogyan az enkódernek kellene. Az tuti nem lesz kontakthibás, és el tudom dönteni, hogy az enkóder megy a kukába, vagy a kódom. Egyéb konstruktív ötlet is jöhet.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Bocsi! De szerintem a kódod a hibás!

Nem lehet olyan gyorsan ki Printelni ahogy jönnek a jelek az enkódertől. Ezért lemaradsz.

Ezért kel megszakításban csak Pufferelni az adatokat.
És a Puffer tartalmát megszakításon kívül ki íratni.
Majd esetleg törölni.
:idea:
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Hozzászólás Szerző: SzLacus »

Én is a kódot gyanúsítom. Nem azért, mert a kiírás nem stimmel, az egy nagyon fontos megjegyzés, amit köszönök. Hanem mert a ledeken sem működik jól. Meglesem a szkóp ábrán, hogy reálisan kiírható-e a soros portra az infó. Sőt egyszerűen ki kommentezem a println sorokat, és a ledeknek el kell kezdeni korrekten működni. Jut eszembe, ha a println feltartja a futást akkor a led sem mutathat jót. Ó pedig már beforrasztottam a tranyós szimulációt. :-) Lehet, hogy nem lesz rá szükség. Köszi Kapu48.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

A Gifr jelző bitet pedig töröljed minden megszakítás végén!
Ez küszöböli ki hogy a közben be esett Prel INT ne érvényesüljön.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Ez a kódot kukába!
Képzelj bele, megnégyszereztet a hibák számát.
A mind2 érintkező prelez be és ki kapcsolásnál. neked így most nem 1*i prel jön bezavarni.
Hanem egymásután 4
:lol:

Ha figyelmesen elolvasnád a belinkelt oldalt!
És tanulmányoznád a négyszög jeleket.

Ki lehet következtetni, hogy a megszakítást okozó bemenetnek éppen ismert az állapota.
És a másik bemenet éppen nyugalomban van valamelyik szinten. Ezt kel kiértékelni.

Várni keveset, hogy túljussunk a preleken. (Ezt kel jól eltalálni!)

És kikapcsolni a közben bejött ismételt megszakításkéréseket, mert nincsen rá szükségünk.

8)
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Hozzászólás Szerző: SzLacus »

Azt meg tudja-e valaki mondani, hogy a GIFR az Arduinóban hogyan elérhető, A megszakítás végrehajtása közben beesett kérést (prell) szeretném törölni. A környezet AVRduino328 (by Robert), az arduino 1.0.1 verzió. Az eszközök >alappanel menüben a Duemilanove Atm328 van kiválasztva.
Az asm volatile ("GIFR=64"::); sor hatástalan.
A proc leírása szerint ennél az atmegánál EIFR a neve a regiszternekés másik bit az érdekes. Viszont az asm volatile ("EIFR |=1"::); sor a következő fordítási hibát adja.
D:\Users\Laci\AppData\Local\Temp/cckbAF6f.s: Assembler messages:
D:\Users\Laci\AppData\Local\Temp/cckbAF6f.s:403: Error: unknown opcode `eifr'
Köszönet az eddigi segítségekért, bár az egyik tanács a gagyitron márkájú jeladót javasolja kidobni, nem figyelembe véve a leírásomat, miszerint a BOURNS gyártmány is ugyan olyan mint a noname. De nem javasol helyette másikat, vagyis a kontakt elvű enkódert dobjam ki?
A másik tanács a kódot dobatja a kukába, amiben van igazság, de jobban örültem volna, ha arra hívja fel a figyelmemet, hogy az összes helyen fordítva használtam a RISING-eket és FALLING-okat.
Hogyan kell jól használni a mechanikus enkódert? Kezelői menüt szeretnék vele kialakítani. Pollozva? De ha gyorsan tekeri, akkor téveszteni fog, mert lemaradhat az eseményről. Megszakításban pedig a prellt kell kezelni, és a kontakt esetleges kh problémáit amennyire csak lehet. Ezt próbálom felépíteni ezzel a pillanatnyilag jogosan "agymenésnek" nevezhető változattal. Ezért a fenti alapkérdés a GIFR vs EIFR témában. Ja és elolvastam figyelmesen, sőt meg is értettem a belinkelt dolgokat már az első kérdésemet megelőzően, mert magam is megtaláltam. Először magam próbálom megfejteni ami elém kerül, és ha nem boldogulok vele, akkor jövök segítségért ide, hiszen mint mondtam kezdő vagyok arduinozásban.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Arduino:
TILOS lenyúlni HW szintig. Ez a rendszer összeborulását eredményezi. És az Arduinoból kilépsz a C/C++ szintre...


Enkóderkezelés:
http://www.arduino.cc/playground/Main/RotaryEncoders
Lehet válogatni!
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Kezdőként az Arduinioban meg kell nézni, hogy van-e hozzá függvénykönyvtár.
A GIFR és társai esetén a rugalmasabb, hazsnálhatóbb, hordozhatóbb Bascom-AVR a javasolt (Arduino alapokat ad, Bascom-AVR magasabb szintű programozást, a C meg elmebajt :) - mondjuk 1 év használat alapján)
A hozzászólást 1 alkalommal szerkesztették, utoljára Robert 2012. október 15. hétfő, 10:23-kor.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Ez 1 jó Bascomos Forum volt!

Mára csak Arduinosra korcsosult!
Mindenki fapados rendszeren akar Űrprogramot fejleszteni
:evil:
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Hozzászólás Szerző: Robert »

Á, ez csak addig van így, amíg a tervezett (deceber közepe (?)) "60+3 nap alatt Bascom-AVR" tanfolyam el nem indul.

Ehhez az alapozó elektronikai cikkek most készülnek, és a héten indul a honlapon a sorozat....


Szóval ha nem is látszik, de a háttérben az események készülnek-forronganak :). Aztán ha kitör - lesz itt forgalom!
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Hozzászólás Szerző: kapu48 »

Visszatérve a Rotarys problémára.

A prelek által bejött ismételt megszakításkéréseket mégiscsak törölni kellene.

Ha közben máshonnan is érkezhet, megszakítás az csak bonyolítja a helyzetet, amit meg kel oldani.

Megkel vizsgálni a megszakítást jelző regisztert honnan jött megszakítás?
És ez alapján törölni a megfelelő jelző Biteket.

Ez a feladat viszont már C programozási ismereteket kíván.

8)
Válasz küldése