Operácie

Akcelerometre: Rozdiel medzi revíziami

Zo stránky SensorWiki

Balogh (diskusia | príspevky)
Vytvorená stránka „Modifikované cvičenie na DOMA: '''Úloha:''' Akcelerometre ktoré máte v mobile, alebo ako samostatný senzor, použijeme na ovládanie 3D modelu v prostredí Proc…“
 
Balogh (diskusia | príspevky)
Bez shrnutí editace
 
(22 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 4: Riadok 4:
'''Úloha:'''
'''Úloha:'''
Akcelerometre ktoré máte v mobile, alebo ako samostatný senzor, použijeme na ovládanie 3D modelu v prostredí Processing.
Akcelerometre ktoré máte v mobile, alebo ako samostatný senzor, použijeme na ovládanie 3D modelu v prostredí Processing.
Pozrite si [https://drive.google.com/file/d/1ce0D3W6obaAZDErZumvAJEj3vSSjfKJe/view?usp=sharing ukážku].
<!-- [https://drive.google.com/file/d/1UaRiMR1ZsW4bQJJLNZUkVYxNOaL64g6Q/view?usp=sharing ukážku]. -->




'''Postup:'''
'''Postup:'''


1. Údaje z akcelerometrov v mobile prenesiete cez Bluetooth alebo cez WiFi pomocou niektorej z aplikácií, ktoré poznáte
# Údaje z akcelerometrov v mobile prenesiete cez Bluetooth alebo cez WiFi pomocou niektorej z aplikácií, ktoré poznáte z predošlých cvičení. Kontrola: v programe Terminal.exe alebo podobnom skontrolujete, či prijímate správne údaje.
z predošlých cvičení. Kontrola: v programe Terminal.exe alebo podobnom skontrolujete, či prijímate správne údaje.
# Údaje prijmete v aplikácii, ktorú máte ako vzor uvedenú nižšie. Treba len:
## rozparsovať prijímané dáta na tri súradnice ax, ay a az.
## prepočítať zrýchlenia na natočenia roll, yaw a pitch.
## na základe výpočtu pohybovať objektom v okne
# Okrem vzorovej kocky, ktorú máte vo vzorovej aplikácii, vytvorte alebo stiahnite z internetu iný 3D model vo formáte .obj a demonštrujte na krátkom videu, že ním viete otáčať.  


2. Údaje prijmete v aplikácii, ktorú máte ako vzor uvedenú nižšie. Treba len:
a) rozparsovať prijímané dáta na tri súradnice ax, ay a az.
b) prepočítať zrýchlenia na natočenia roll, yaw a pitch.
c) na základe výpočtu pohybovať objektom v okne
3. Okrem vzorovej kocky, ktorú máte vo vzorovej aplikácii, vytvorte alebo stiahnite z internetu iný 3D model vo
formáte .obj a demonštrujte na krátkom videu, že ním viete otáčať.


'''Odovzdať treba:'''  
'''Odovzdať treba:'''  
Riadok 28: Riadok 27:


<source lang="cpp">
<source lang="cpp">
// https://github.com/PaulStoffregen/NXPMotionSense/tree/master/OrientationVisualiser
import processing.serial.*;
//
// https://www.pjrc.com/store/prop_shield.html


import processing.serial.*;
Serial myPort;
Serial myPort;
PImage bg;
PShape myObject;
PShape myObject;


Riadok 45: Riadok 39:
{
{
   size(600, 600, P3D);
   size(600, 600, P3D);
  bg = loadImage("grid10.png");


   myObject = loadShape("tinker.obj");  // vymodelovane v tinkerCADe ak tamnahram aj obj.mtl, tak to bude farebne!
   // myObject = loadShape("tinker.obj");  // objekt, ktorym chcem hybat
  // myObject.scale(2.0);                // ak je prilis maly alebo velky, zmente mu velkost
  /* Toto je niekolko prikladov, ako si vybrat seriovy port, nie je aktivne
    ani jedno, musite si niektoru moznost odkomentovat                    */


   // if you don't know anything, first list all available ports:
   // ak nic neviete, vypiste si najprv vsetky porty co mate:
   printArray(Serial.list());
   printArray(Serial.list());
// while (!keyPressed) { /* wait here, please */  }
    
    
   // if you have only ONE serial port active
   // ak mate len jeden port, alebo viete ktory v poradi je ten vas:
   //myPort = new Serial(this, Serial.list()[1], 115200); // if you have only ONE serial port active
   // myPort = new Serial(this, Serial.list()[1], 115200);  


   // if you know the serial port name
   // ak viete cislo portu:
   //myPort = new Serial(this, "COM5:", 9600);        // Windows "COM#:"
   //myPort = new Serial(this, "COM5:", 9600);        // Windows "COM#:"
   myPort = new Serial(this, "\\\\.\\COM39", 115200); // Windows, COM10 or higher
   // myPort = new Serial(this, "\\\\.\\COM39", 115200); // Windows, od COM10 vyssie
   //myPort = new Serial(this, "/dev/ttyACM0", 9600);  // Linux "/dev/ttyACM#"
   //myPort = new Serial(this, "/dev/ttyACM0", 9600);  // Linux "/dev/ttyACM#"
   //myPort = new Serial(this, "/dev/cu.usbmodem1217321", 9600);  // Mac "/dev/cu.usbmodem######"
   //myPort = new Serial(this, "/dev/cu.usbmodem1217321", 9600);  // Mac "/dev/cu.usbmodem######"
  // not used, zda sa...
  // textSize(16); // set text size
  // textMode(SHAPE); // set text mode to shape
}
}


void draw()
void draw()
{
{
   serialEvent(); // read and parse incoming serial message
   serialEvent();   // nacitaj hodnoty z prichadzajucej spravy
// background(255); // set background to white
  background(255); // biele pozadie
   background(bg); // set background to white
   lights();       // osvetlenie sceny
  lights();


   translate(width/2, height/2); // set position to centre
   translate(width/2, height/2); // pociatok suradnic bude v strede okna


  pushMatrix(); // begin object
    rotateX(radians(roll));     // argument je v radianoch <0,pi/2> co nam zabezpeci funkcia radians()
    rotateY(radians(-pitch));
    rotateZ(radians(yaw));


  float c1 = cos(radians(roll));
    drawObject();  // objekt bud nakreslime, alebo
  float s1 = sin(radians(roll));
    // shape(myObject); // zobrazime 3D model .obj
  float c2 = cos(radians(-pitch));
  float s2 = sin(radians(-pitch));
  float c3 = cos(radians(yaw));
  float s3 = sin(radians(yaw));
  /* applyMatrix( c2*c3, s1*s3+c1*c3*s2, c3*s1*s2-c1*s3, 0,
              -s2, c1*c2, c2*s1, 0,
              c2*s3, c1*s2*s3-c3*s1, c1*c3+s1*s2*s3, 0,
              0, 0, 0, 1);
*/
  rotateX(radians(roll));
  rotateY(radians(-pitch));
  rotateZ(radians(yaw));
  //drawPropShield();
  //drawRGBcross();
  shape(myObject);


  popMatrix(); // end of object


   // Print values to console
   // Ziskane hodnoty si pre istotu vypiseme aj do konzoly
   print(roll);
   print(roll);
   print("\t");
   print("\t");
Riadok 106: Riadok 83:
   println();
   println();
}
}


void serialEvent()
void serialEvent()
Riadok 112: Riadok 90:
   int newLine = 13; // new line character in ASCII
   int newLine = 13; // new line character in ASCII
   String message;
   String message;
   do {
   do {
     message = myPort.readStringUntil(newLine); // read from port until new line
     message = myPort.readStringUntil(newLine);     // read from port until new line
     if (message != null) {
     if (message != null) {
       String[] list = split(trim(message), " "); // rozdelime to medzerami (mozem sem dat napr. ciarky)
       String[] list = split(trim(message), " ");   // hodnoty su oddelene medzerami (ale mozem sem dat napr. ciarky)
       if (list.length >= 4 && list[0].equals("Orientation:")) {  // tu vyhodime zo zaciatku slovo Orientation: ale nemusi to byt vobec
       if (list.length >= 4 && list[0].equals("Orientation:")) {  // tu vyhodime zo zaciatku slovo Orientation: ale nemusi to byt vobec
         aX = float(list[1]); // convert to float yaw
         aX = float(list[1]); // convert to float yaw
Riadok 121: Riadok 100:
         aZ = float(list[3]); // convert to float roll
         aZ = float(list[3]); // convert to float roll
          
          
         aX = map(aX,-1023,1023,-9.81,9.81);
         /* Tuto treba dopisat prevod zrychlenia v jednotlivych osiach na natocenia */
         aY = map(aY,-1023,1023,-9.81,9.81);
        /* Vasa uloha je namiesto pevnej hodnoty vlozit vypocet                    */
         aZ = map(aZ,-1023,1023,-9.81,9.81);
 
        yaw=45;    // tu predpokladame, ze hodnoty nam chodia v stupnoch, ale vase senzory mozno davaju radiany alebo nasobky g
         pitch=-45;
         roll=45;      
          
          
        pitch = 180 * atan (aX/sqrt(aY*aY + aZ*aZ))/ PI;
        roll = 180 * atan (aY/sqrt(aX*aX + aZ*aZ))/ PI;
        yaw = 180 * atan (aZ/sqrt(aX*aX + aZ*aZ))/ PI;
       
       
        //yaw=45;
        //pitch=-45;
        //roll=45;
       }
       }
     }
     }
Riadok 138: Riadok 112:
}
}


void drawRGBcross()
 
void drawObject()
{
{
  /* function contains shape(s) that are rotated with the IMU */
   stroke(0); // black outline
   stroke(0); // black outline
   fill(100, 128, 50); // fill color PCB green
   fill(255, 215, 0); // gold color
  fill(255, 215, 0); // gold color
   box(100,100, 100); // cube
   box(100,100, 100); // cube


  // arrows
  stroke(0, 0, 250); // set outline colour to blue
  translate(100, 100, 100); // set position to other edge of Arduino box
  box(1, 1, 200); // draw Arduino board base shape
  stroke(0, 250,0); // set outline colour to darker teal
  box(200, 1, 1); // draw Arduino board base shape
  stroke(250,0,0); // set fill colour to lighter teal
  box(1, 200, 1); // draw Arduino board base shape
/*
  stroke(0); // set outline colour to black
  fill(80); // set fill colour to dark grey
  translate(60, -10, 90); // set position to edge of Arduino box
  box(170, 20, 10); // draw pin header as box
  translate(-20, 0, -180); // set position to other edge of Arduino box
  box(210, 20, 10); // draw other pin header as box
 
*/
}
}
</source>


void drawPropShield()
'''Tipy:'''
{
  // 3D art by Benjamin Rheinland
  stroke(0); // black outline
  fill(0, 128, 0); // fill color PCB green
  box(190, 6, 70); // PCB base shape


  fill(255, 215, 0); // gold color
* Na vytvorenie 3D objektu môžete použiť napr. TinkerCAD
  noStroke();
** TinkerCAD návody na tomto YouTube kanáli: https://www.youtube.com/playlist?list=PLmh6bwr3ZDwAzcU1krZOvCDkJEuO8nUhv
* Ak k vyexportovanému objektu pridáte aj .mtl súbor, objekt bude farebný
* Tento demo program v Processingu otáča objektom pomocou myšky ([http://senzor.robotika.sk/mems/OrientationDemo.zip OrientationDemo.zip])
* Prevod natočenia z akcelerometrov na yaw, pitch a roll je popísaný v týchto troch článkoch:
** Mark Pedley: ''[https://www.nxp.com/docs/en/application-note/AN3461.pdf Tilt Sensing Using a Three-Axis Accelerometer]''. Application Note AN3461. Freescale Semiconductor, 2013.
** Talat  Ozyagcilar: ''[https://www.nxp.com/docs/en/application-note/AN4248.pdf Implementing a Tilt-Compensated eCompass using Accelerometer and Magnetometer Sensors]'' Application Note AN4248. Freescale Semiconductor,  2012.
** Talat  Ozyagcilar: ''[https://www.nxp.com/docs/en/application-note/AN4249.pdf Accuracy of Angle Estimation in eCompass and 3D Pointer Applications]'' Application Note AN4249. Freescale Semiconductor,  2015.
Ale predpokladám, že vám bude stačiť toto, kde G sú jednotlivé zrýchlenia a ϕ = roll and θ = pitch:


  //draw 14 contacts on Y- side
<math>
  translate(65, 0, 30);
\tan \phi_{xyz} = \frac{G_{py}}{G_{pz}}
  for (int i=0; i<14; i++) {
</math>
    sphere(4.5); // draw gold contacts
    translate(-10, 0, 0); // set new position
  }


  //draw 14 contacts on Y+ side
<math>
  translate(10, 0, -60);
\tan \theta_{xyz} = \frac{-G_{px}}{G_{py}\sin \phi + G_{pz}\cos \phi} = \frac{-G_{px}}{\sqrt{G_{py}^2 + G_{pz}^2}}
  for (int i=0; i<14; i++) {
</math>
    sphere(4.5); // draw gold contacts
    translate(10, 0, 0); // set position
  }


  //draw 5 contacts on X+ side (DAC, 3v3, gnd)
Implementácia by mohla vyzerať napríklad takto (atan2 dáva výsledky v radiánoch)
  translate(-10,0,10);
  for (int i=0; i<5; i++) {
    sphere(4.5);
    translate(0,0,10);
  }


  //draw 4 contacts on X+ side (G C D 5)
<source lang="cpp">
  translate(25,0,-15);
  for (int i=0; i<4; i++) {
    sphere(4.5);
    translate(0,0,-10);
  }


  //draw 4 contacts on X- side (5V - + GND)
roll = atan2(accelerationY, accelerationZ);
  translate(-180,0,10);
  for (int i=0; i<4; i++) {
    sphere(4.5);
    translate(0,0,10);
  }


  //draw audio amp IC
pitch = atan2(-accelerationX, sqrt(accelerationY*accelerationY + accelerationZ*accelerationZ));
  stroke(128);
  fill(24);    //Epoxy color
  translate(30,-6,-25);
  box(13,6,13);


  //draw pressure sensor IC
yaw =  atan2(accelerationZ, sqrt(accelerationX*accelerationX + accelerationZ*accelerationZ));
  stroke(64);
</source>
  translate(32,0,0);
    
  fill(192);
   box(10,6,18);


  //draw gyroscope IC
* Ak vám nefunguje on-line prenos dát, môžete toto zadanie spraviť tiež aj off-line, teda zo záznamu.  Najprv nafilmujete ruku s mobilom, ktorou spravíte niekoľko jasne definovaných pohybov, potom doplníte video o ukážku, že objekt sa pohybuje v súlade s pohybom ruky, hoci aj nahraným v inom čase.
  stroke(128);
** Na načítanie údajov zo súboru v programe Processing použite [https://processing.org/reference/createReader_.html createReader()] - pozrite si príklad a bude to jasné.
  translate(27,0,0);
** Pri načítaní dát zo súboru však musíte program trocha spomaliť, pretože zo súboru tie data dokážete čítať oveľa rýchlejšie ako ste ich zozbierali. Preto je vhodné po výpočte natočenia program zastaviť a "počkať" na ďalšiu vzorku, napríklad pomocou funkcie [https://processing.org/reference/delay_.html delay();].
  fill(24);
  box(16,6,16);


  //draw flash memory IC
* Ak je objekt ktorý kreslíte príliš malý alebo veľký, zmeňte mu veľkosť príkazom <code>myObject.scale(2.0);</code> hneď po nahraní, za príkazom <code>loadShape()</code>
  translate(40,0,-15);
  box(20,6,20);


  //draw accelerometer/magnetometer IC
  translate(-5,0,25);
  box(12,6,12);


  //draw 5V level shifter ICs
  translate(42.5,2,0);
  box(6,4,8);
  translate(0,0,-20);
  box(6,4,8);
}
</source>


'''Tipy:'''
[[Súbor:logoMatlab.png|80px|left]] Ak vám to nepôjde ani jedným z uvedených spôsobov, skúste to ešte pomocou aplikácie [https://play.google.com/store/apps/details?id=com.mathworks.matlabmobile&hl=en&gl=US MATLAB Mobile].<BR>
 
Ukážkový program na spracovanie dát a zobrazenie 3D objektu v Matlabe nájdete na [https://senzor.robotika.sk/mems/LiveAccelerometerData.html samostatnej stránke tu].
* Na vytvorenie 3D objektu môžete použiť napr. TinkerCAD (návody na tomto YouTube kanáli: https://www.youtube.com/playlist?list=PLmh6bwr3ZDwAzcU1krZOvCDkJEuO8nUhv
* Ak k vyexportovanému objektu pridáte aj .mtl súbor, objekt bude farebný
* Tento demo program v Processingu otáča objektom pomocou myšky








<BR>
<BR>
<BR>


[[MEMS inteligentné senzory a aktuátory#Cvi.C4.8Denia|Návrat na zoznam cvičení...]]
[[MEMS inteligentné senzory a aktuátory#Cvi.C4.8Denia|Návrat na zoznam cvičení...]]


[[Category:MEMS]]
[[Category:MEMS]]

Aktuálna revízia z 07:28, 9. apríl 2022

Modifikované cvičenie na DOMA:


Úloha: Akcelerometre ktoré máte v mobile, alebo ako samostatný senzor, použijeme na ovládanie 3D modelu v prostredí Processing. Pozrite si ukážku.


Postup:

  1. Údaje z akcelerometrov v mobile prenesiete cez Bluetooth alebo cez WiFi pomocou niektorej z aplikácií, ktoré poznáte z predošlých cvičení. Kontrola: v programe Terminal.exe alebo podobnom skontrolujete, či prijímate správne údaje.
  2. Údaje prijmete v aplikácii, ktorú máte ako vzor uvedenú nižšie. Treba len:
    1. rozparsovať prijímané dáta na tri súradnice ax, ay a az.
    2. prepočítať zrýchlenia na natočenia roll, yaw a pitch.
    3. na základe výpočtu pohybovať objektom v okne
  3. Okrem vzorovej kocky, ktorú máte vo vzorovej aplikácii, vytvorte alebo stiahnite z internetu iný 3D model vo formáte .obj a demonštrujte na krátkom videu, že ním viete otáčať.


Odovzdať treba:

  • video na ktorom vidno ako otáčate objektom pohybom mobilu
  • zdrojový kód v Processingu (.pde)
  • model objektu (.obj)


Vzorový program

import processing.serial.*;

Serial myPort;
PShape myObject;

float yaw = 0.0;
float pitch = 0.0;
float roll = 0.0;

void setup()
{
  size(600, 600, P3D);

  // myObject = loadShape("tinker.obj");  // objekt, ktorym chcem hybat
  // myObject.scale(2.0);                 // ak je prilis maly alebo velky, zmente mu velkost
 
  /* Toto je niekolko prikladov, ako si vybrat seriovy port, nie je aktivne
     ani jedno, musite si niektoru moznost odkomentovat                    */

  // ak nic neviete, vypiste si najprv vsetky porty co mate:
  printArray(Serial.list());
  
  // ak mate len jeden port, alebo viete ktory v poradi je ten vas:
  // myPort = new Serial(this, Serial.list()[1], 115200); 

  // ak viete cislo portu:
  //myPort = new Serial(this, "COM5:", 9600);        // Windows "COM#:"
  // myPort = new Serial(this, "\\\\.\\COM39", 115200); // Windows, od COM10 vyssie
  //myPort = new Serial(this, "/dev/ttyACM0", 9600);   // Linux "/dev/ttyACM#"
  //myPort = new Serial(this, "/dev/cu.usbmodem1217321", 9600);  // Mac "/dev/cu.usbmodem######"
}

void draw()
{
  serialEvent();   // nacitaj hodnoty z prichadzajucej spravy
  background(255); // biele pozadie
  lights();        // osvetlenie sceny

  translate(width/2, height/2); // pociatok suradnic bude v strede okna

    rotateX(radians(roll));     // argument je v radianoch <0,pi/2> co nam zabezpeci funkcia radians()
    rotateY(radians(-pitch));
    rotateZ(radians(yaw));

    drawObject();  // objekt bud nakreslime, alebo
    // shape(myObject); // zobrazime 3D model .obj


  // Ziskane hodnoty si pre istotu vypiseme aj do konzoly
  print(roll);
  print("\t");
  print(-pitch);
  print("\t");
  print(yaw);
  println();
}


void serialEvent()
{
  float aX, aY, aZ;
  int newLine = 13; // new line character in ASCII
  String message;

  do {
    message = myPort.readStringUntil(newLine);     // read from port until new line
    if (message != null) {
      String[] list = split(trim(message), " ");   // hodnoty su oddelene medzerami (ale mozem sem dat napr. ciarky)
      if (list.length >= 4 && list[0].equals("Orientation:")) {  // tu vyhodime zo zaciatku slovo Orientation: ale nemusi to byt vobec
        aX = float(list[1]); // convert to float yaw
        aY = float(list[2]); // convert to float pitch
        aZ = float(list[3]); // convert to float roll
        
        /* Tuto treba dopisat prevod zrychlenia v jednotlivych osiach na natocenia */ 
        /* Vasa uloha je namiesto pevnej hodnoty vlozit vypocet                    */

        yaw=45;    // tu predpokladame, ze hodnoty nam chodia v stupnoch, ale vase senzory mozno davaju radiany alebo nasobky g
        pitch=-45;
        roll=45;        
        
      }
    }
  } while (message != null);
}


void drawObject()
{
  stroke(0); // black outline
  fill(255, 215, 0); // gold color
  box(100,100, 100); // cube

}

Tipy:

Ale predpokladám, že vám bude stačiť toto, kde G sú jednotlivé zrýchlenia a ϕ = roll and θ = pitch:

Implementácia by mohla vyzerať napríklad takto (atan2 dáva výsledky v radiánoch)

roll = atan2(accelerationY, accelerationZ);

pitch = atan2(-accelerationX, sqrt(accelerationY*accelerationY + accelerationZ*accelerationZ));

yaw =  atan2(accelerationZ, sqrt(accelerationX*accelerationX + accelerationZ*accelerationZ));


  • Ak vám nefunguje on-line prenos dát, môžete toto zadanie spraviť tiež aj off-line, teda zo záznamu. Najprv nafilmujete ruku s mobilom, ktorou spravíte niekoľko jasne definovaných pohybov, potom doplníte video o ukážku, že objekt sa pohybuje v súlade s pohybom ruky, hoci aj nahraným v inom čase.
    • Na načítanie údajov zo súboru v programe Processing použite createReader() - pozrite si príklad a bude to jasné.
    • Pri načítaní dát zo súboru však musíte program trocha spomaliť, pretože zo súboru tie data dokážete čítať oveľa rýchlejšie ako ste ich zozbierali. Preto je vhodné po výpočte natočenia program zastaviť a "počkať" na ďalšiu vzorku, napríklad pomocou funkcie delay();.
  • Ak je objekt ktorý kreslíte príliš malý alebo veľký, zmeňte mu veľkosť príkazom myObject.scale(2.0); hneď po nahraní, za príkazom loadShape()


Ak vám to nepôjde ani jedným z uvedených spôsobov, skúste to ešte pomocou aplikácie MATLAB Mobile.

Ukážkový program na spracovanie dát a zobrazenie 3D objektu v Matlabe nájdete na samostatnej stránke tu.






Návrat na zoznam cvičení...