egy mobil robot építésének története

Robotkocsi

Robotkocsi

Mi, merre, hány méter? (2. rész)

használható odometria

2019. augusztus 14. - dralisz82

Ahogy arra a legutóbbi bejegyzésben már utaltam, a mágnesek számát növelni kellett ahhoz, hogy normális enkóderünk legyen. Normális alatt közel 50%-os pulzusszélességet értek, azaz az érzékelők ugyanannyi fokos elforgatáson keresztül érzékeljenek alacsony és magas állapotot. Mint kiderült, ehhez a mágnesek számát legalább háromszorozni kell, azonban így sem lett tökéletes az eredmény, így végül 24 mágnest építettem be, de itt már nagy hangsúlyt fektettem a pontos elhelyezésükre, valamint mérni kezdtem a jeleket, hogy láthassam, hogy min kell változtatni.

Mágnestartó, a nagy újítás

Az előző kialakításhoz képest az igazán nagy újítás, hogy a mágneseket nem egyesével ragasztottam be a kerékbe, hanem készítettem egy mágnestartó sablont. Ehhez TinkerCAD-et ragadtam és felfűtöttem a 3D nyomtatót, majd a ragasztópisztolyt. Az eredmény a képeken látható:

robotkocsi_108_magnestarto_keret.png

robotkocsi_109_magnestarto_keret.jpg
robotkocsi_110_magnestarto_keret.jpg robotkocsi_111_magnestarto_keret.jpg

 

Ennyi mágnesnél már muszáj volt ezt meglépni, de nem csak a beszerelés egyszerűsödött, hanem sokkal pontosabb is lett az eredmény. Ráadásul a bepattintható tartók könnyen eltávolíthatók, ha változtatásra lesz szükség (kiegészítés: lett).

Geometria

24 db mágnes elhelyezése a körön azt jelenti, hogy azok 15°-onként vannak. A szenzorokat így 7.5°-ra tettem egymástól egy újabb tartóra átszerelve. Ez a 7.5° végre kellőképp kicsi ahhoz, hogy egy mágnes úgy ússzon át az egyik szenzor hatósugarából a másikéba, hogy előbb kezdi érzékelni az új szenzor, utána "veszíti szem elől" a régi – tehát a szenzorok átfedésben érzékelnek. Eddig ez nem volt meg, mert bőven 50% alatti volt a mágnesesen aktív szakaszok aránya a körön. Mint kiderült, a mágnesek azonban így túl közel kerültek egymáshoz. A táblázat mutatja a szenzorok által érzékelt jelek szekvenciáját:

Előre:
Zöld Sárga
1 1
0 1
1 1
1 0
1 1
Hátra:
Zöld Sárga
1 1
1 0
1 1
0 1
1 1

 

Ahogy látható, hiányzik a 00 állapot, ami nélkül nem lehet megbízhatóan érzékelni az irányváltást, tehát ugyanabba az elméleti problémába futottam bele, mint amikor túl kevés mágnes volt, csak inverz módon. A két jelsorozat igazából megegyezik.

Miután logikai analizátorral is felmértem a helyzetet (lásd a következő fejezetet), visszatértem a 18 mágneses elrendezéshez, mert az közelebb áll az 50%-hoz, viszont a 7.5°-os szenzortartót meghagytam, úgy gondolkodva, hogy – bár egy picit eltolódik a két jel fázisa az ideális 90°-tól (ez a 90° nem összekeverendő a kerék kerületén mért szögekkel!), fontosabb, hogy a szenzorok átfedésben maradjanak.

Az átalakítás után bíztató eredményeket kaptam:

Előre:
Zöld Sárga
1 1
0 1
0 0
1 0
1 1
Hátra:
Zöld Sárga
1 1
1 0
0 0
0 1
1 1

 

Ez már egy olyan kimenet, amit egy kvadratúra-enkódertől várunk: az állapotátmenetekből minden esetben eldönthető a forgásirány (érdemes gondolatban kipróbálni a fenti táblázat segítségével).

Logikai analizátor - út a XXI. századba

Miután szert tettem erre az eszközre, úgy éreztem, korábban egy sötét szobában tapogatóztam csupán. A logikai analizátor minden digitális technikával kicsit is komolyabban foglalkozó számára egy kötelező műszer! Szerencsére nem szükséges venni egyet, hála az Arduinok népszerűségének.

Éppen volt nálam kölcsönben egy Arduino Mega, a neten pedig találtam egy logikai analizátor firmware-t rá, amivel egy 8 csatornás, akár 4 MHz mintavételezésű logikai analizátorrá alakítható a kártya. Ráadásul a firmware a szabványos SUMP protokollt is támogatja, így a nyílt forráskódú Sigrok PulseView programmal is használható.

robotkocsi_112_logikai_analizator.jpg

A PulseView nagyon jó felhasználói felülettel rendelkezik és rengeteg extra funkciója van. Egyetlen szépséghibája az Arduino + Sigrok kombinációnak, hogy a beérkező jeleket jobbról balra mutatja az időtengelyen, de ezzel együtt lehet élni, ha nem akarjuk használni a rengeteg protokoldekóder egyikét sem. A hiba egyébként ismert, így a nyílt forráskódnak köszönhetően várhatóan hamarosan javításra kerül. (FRISSÍTÉS: Végül én adtam ki rá egy javítást először. :) )

A dekóderek közül én csak az impulzusok hosszát mérő "Timing" eszközt használtam, ami így is tökéletesen működik, és számomra most ez volt fontos:

robotkocsi_113_logikai_analizator.png

A jelek értelmezéséhez fontos tudni, hogy az A3144-es hall-szenzor inverz logikai jelet ad, tehát akkor húzza földre a kimenetét, amikor mágneses teret érzékel. Így már látható is a fenti ábrán, hogy 24 mágnes esetén kb. 2/3-os kitöltési tényezővel jócskán sikerült túllépni az ideális 50%-ot.

A következő mérést már a 18 mágneses és 7.5°-os szenzortávolságos verzióval készítettem:

robotkocsi_114_logikai_analizator.png

A képen szemmel látható, hogy elég jó pontossággal közelítik a jelek az 50%-os kitöltést (a sűrűbb és ritkább szakaszok a sebességváltozásból, a kerék felgyorsulásából és lelassulásából adódnak). A középső hosszabb konstans szakasztól jobbra egy előre, balra egy hátrafelé forgás jeleit láthatjuk. Elhelyeztem két kurzort is a képen, amik jól mutatják, hogy előreforgásnál a 6-os jel lefutó élénél (ne feledjük, hogy továbbra is visszafelé, jobbról balra futnak a jelek) magas a 4-es jel állapota, míg a bal oldali hátrafelé forgás esetén pont a 6-os jel felfutó élénél magas a 4-es jel szintje (az ellenkező éleknél pedig alacsony).

Szoftver

A forgásirány eldöntéséhez minden állapotátmenetet figyelni kell, tehát az előző részben bemutatott implementációhoz képest mindkét szenzor fel- és lefutó jeleihez is megszakításkezelőt kötöttem. Ez azt is jelenti, hogy egy mágnes elmozdulása egy körülfordulás során nem kétszer, hanem négyszer detektálható, ami az enkóderünk felbontását egészen vállalható 18*4=72 pulzus/körülfordulás (pulse per rotation - PPR) magasságokba röpíti.

Nézzük a kódot:

void Odometry::hallAriseISR(void) {
   if(hallB->read() == 0) {
    // 00 -> 10
    dir = BW;
  } else {
    // 01 -> 11
    dir = FW;
  }

  if(dir == FW)
    odoPos++;
  else
    odoPos--;

  odoCount++;
  calcSpeed();
}

void Odometry::hallAfallISR(void) {
  if(hallB->read() == 0) {
    // 10 -> 00
    dir = FW;
  } else {
    // 11 -> 01
    dir = BW;
  }

  if(dir == FW)
    odoPos++;
  else
    odoPos--;

  odoCount++;
  calcSpeed();
}

void Odometry::hallBriseISR(void) {
  if(hallA->read() == 0) {
    // 00 -> 01
    dir = FW;
  } else {
    // 10 -> 11
    dir = BW;
  }

  if(dir == FW)
    odoPos++;
  else
    odoPos--;

  odoCount++;
  calcSpeed();
}

void Odometry::hallBfallISR(void) {
  if(hallA->read() == 0) {
    // 01 -> 00
    dir = BW;
  } else {
    // 11 -> 10
    dir = FW;
  }

  if(dir == FW)
    odoPos++;
  else
    odoPos--;

  odoCount++;
  calcSpeed();
}

void Odometry::calcSpeed() {
  // Prevent division by zero -> side effect: measuring limit under 833 RPM (@72 PPR)
  if(timer.read_ms() == previousTime)
    return;

  // Current speed calculation
  currentSpeed = (WHEELCIRCUMFERENCE / PPR) * 100 / (timer.read_ms() - previousTime);

  // Highest speed calculation
  if((previousSpeed + currentSpeed)/2 > highestSpeed)
    highestSpeed = (previousSpeed + currentSpeed)/2;

  // Average speed calculation
  speedSum += currentSpeed; // TODO: this will overflow once, far in the future
  avgSpeed = speedSum / odoCount;

  previousTime = timer.read_ms();
  previousSpeed = currentSpeed;

  hallTimeout.detach();
  hallTimeout.attach(callback(this, &Odometry::clearSpeed), 1);
}

void Odometry::clearSpeed() {
  currentSpeed = 0;
}

A megszakításkezelők magukért beszélnek (ezért érdemes kommentezni a kódot). A hallTimeout és a clearSpeed() függvény szúrhat szemet a szemlélőnek. Erre a sebességnullázásra azért van szükség, mert az ISR-ek csak akkor frissítik a sebesség értékét, amikor új impulzus érkezik. Ha megáll az autó, akkor nem fog ilyesmi történni, így egy idő után más módon kell nullára állítani a sebességet. Ehhez a timeout értékét 1 másodpercnek választottam, ami azt jelenti, hogy ha olyan lassan forog a kerék, hogy két érzékelt pozíció között pont ennyi idő telik el, az a leglassabb érzékelhető sebesség. 72 pozícióval egy 1 fordulat / 72 másodperc alatt történik ekkor, azaz 1/72-ed fordulat per másodpercre, átváltva 4.79 mm / másodpercre jön ki a leglassabb érzékelhető sebesség. Ez a 4.79 mm egyébként a legkisebb érzékelhető elmozdulásnak is a mértéke.

robotkocsi_115_odometria_teszt.jpg robotkocsi_116_odometria_teszt.jpg
robotkocsi_117_odometria_teszt.jpg robotkocsi_118_odometria_teszt.jpg

 

 

Ezekkel az értékekkel már elégedett vagyok, a forgásirányváltás is minden esetben detektálható, erre már lehet építeni. A következő bejegyzésben arról írok majd, hogy mihez is kezdtem az odometriából kinyert adatokkal.

 

A bejegyzés trackback címe:

https://robotkocsi.blog.hu/api/trackback/id/tr5014594684

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása