- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 23

Thema: 'Schiefes Koordinatensystem' begradigen

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    41
    Beiträge
    2.009
    Anzeige

    Praxistest und DIY Projekte
    Also ich hab mal den Algorithmus nachgebaut (zumindest versucht).

    Eigentlich müsste er so laufen, nur ich erhalte als Positionen immer 0 / 0.

    Code:
    #define Iterations 5
    #define LCD_Width 128
    #define LCD_Height 64
    
    // Calibration values; set with defaults
    ui16_t r0_x = 101;
    ui16_t r1_x = 867;
    ui16_t r2_x = 848;
    ui16_t r3_x = 102;
    ui16_t r0_y = 145;
    ui16_t r1_y = 150;
    ui16_t r2_y = 802;
    ui16_t r3_y = 759;
    
    
    
    void TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp)
    {
      ui8_t cycle;
      ui16_t x_raw;
      ui16_t y_raw;
      ui32_t main_det;
      double W = 0; // iteration parameter
      double LV_x = 0;  // solving vector X
      double LV_y = 0;  // solving vector Y
      double D_x  = 0;  // det. x
      double D_y  = 0;  // det. y
      double factor_x = 0;
      double factor_y = 0;
    
      TPAD_GetPos(&xraw, &yraw);
    
      // calculate constant values for iteration:
    
      // (r1_x - r0_x) = D20 (Excel cell D20)
      // (r1_y - r0_y) = E20
      // (r3_x - r0_x) = D21
      // (r3_y - r0_y) = E21
      // D = D20 * E21 - E20 * D21
      
      main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_y - r0_y));
    
      // (r - r0) = (x_raw - r0_x) = D23
      // (r - r0) = (y_raw - r0_y) = E23
      // (r0-r1)-(r3-r2) = (r0_x - r1_x) - (r3_x - r2_x) = D24
      // (r0-r1)-(r3-r2) = (r0_y - r1_y) - (r3_y - r2_y) = E24
    
      // Iteration:
      for (cycle = 0 ; cycle < Iterations ; cycle++)
      {
        LV_x = (x_raw - r0_x) - (W * ((r0_x - r1_x) - (r3_x - r2_x))); // = D31
        LV_y = (y_raw - r0_y) - (W * ((r0_y - r1_y) - (r3_y - r2_y))); // = E31
    
        D_x = (LV_x * (r3_y - r0_y)) - (LV_y * (r3_x - r0_x)); // = D33
        D_y = (LV_y * (r1_x - r0_x)) - (LV_x * (r1_y - r0_y)); // = E34
    
        factor_x = D_x / main_det; // = D36
        factor_y = D_y / main_det; // = E37
        W = factor_x * factor_y;
      }
    
      *xp = (factor_x * (LCD_Width - 1));
      *yp = (factor_y * (LCD_Height - 1));
    }
    Werd den Fehler natürlich weiter verfolgen.
    #ifndef MfG
    #define MfG

  2. #12
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Jaecko,

    ich hab noch zuviel Watte im Kopp um Deinen Code gründlich zu lesen, aber die Zeile

    main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_y - r0_y));

    müsste meiner Meinung nach

    main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_x - r0_x));

    heissen.

    Ciao,

    mare_crisium

  3. #13
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    41
    Beiträge
    2.009
    Stimmt, da bin ich durcheinandergekommen.
    Hab den Algorithmus jetzt mal neu aufgebaut und dabei noch einige "Fehler" im alten gefunden. U.a. hab ich zu wenig gecastet.
    (ui16_t * ui16_t ist wieder ui16_t, obwohl z.B. eine ui32_t erwartet wird)

    Jetzt funktionierts schon fast perfekt. Hier ist ein Video, in dem das Programm einfach gesagt nur folgendes durchführt:
    - Hol die Rohwerte der Position.
    - Berechne mit dem "mare_cirisum-Algorithmus" die echte Position
    - Pinsel das Pixel an der entsprechenden Stelle weiss.

    http://www.youtube.com/watch?v=fdpV7baRqgs

    Wie man auf dem Video sieht, geht das in der linken Displayhälfte schon perfekt. Nur in der rechten ist noch ein kleiner Offset nach unten drin.
    Ich vermute, dass ich da nochmal irgendwo nen Cast vergessen hab.
    Lässt sich aber auch noch rausfinden.

    Hier der neue Algorithmus:

    Code:
    // Those values are determined by a calibration procedure (touch all 4 corners)
    // Here they are loaded with default values
    ui16_t r0[2] = { 101, 145 };
    ui16_t r1[2] = { 867, 150 };
    ui16_t r2[2] = { 848, 802 };
    ui16_t r3[2] = { 102, 759 };
    
    // variables for precise algorithm; declared here to save stack memory
      ui16_t r_raw[2];    // raw value vector
      double W = 0;       // Iteration parameter; Start value = 0
      i16_t r1_r0[2];    // solution vector for r1 - r0
      i16_t r3_r0[2];    // solution vector for r3 - r0
      i16_t rraw_r0[2];  // solution vector for rraw - r0
      i32_t D;           // determinant
      i32_t D_part[2];   // partial solution for determinant
      double factor[2];  // solution vector factors
      i16_t r01_r32[2];  // solution vector for (r0 - r1) - (r3 - r2)
      double solVec[2];  // soluton vector
      double D_XY[2];    // determinant D_X, D_Y
    
    
    #define LCD_Width   128
    #define LCD_Height   64
    #define Iterations   4
    #define X 0
    #define Y 1
    
    
    void TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp)
    {
      ui8_t step;
    
      // Check if constant 'Iteration' is defined already. If not, use default value of 5.
      #ifndef Iterations
        #define Iterations 5
      #endif
    
      TPAD_GetPos(&r_raw[X], &r_raw[Y]); // get raw values via 'old' method (ADC-Values)
    //  r_raw[X] = 560; // test value
    //  r_raw[Y] = 200; // test value
      // Constant values, needed for calculation; constant for a single iteration:
      
      // r1-r0
      r1_r0[X] = r1[X] - r0[X];
      r1_r0[Y] = r1[Y] - r0[Y];
    
      // r3-r0
      r3_r0[X] = r3[X] - r0[X];
      r3_r0[Y] = r3[Y] - r0[Y];
    
      // Determinant
      D_part[0] = (i32_t) r1_r0[X] * (i32_t) r3_r0[Y];
      D_part[1] = (i32_t) r1_r0[Y] * (i32_t) r3_r0[X];
      D = D_part[0] - D_part[1];
    
      // r_raw - r0
      rraw_r0[X] = r_raw[X] - r0[X];
      rraw_r0[Y] = r_raw[Y] - r0[Y];
      
      // (r0 - r1) - (r3 - r2)
      r01_r32[X] = (r0[X] - r1[X]) - (r3[X] - r2[X]);
      r01_r32[Y] = (r0[Y] - r1[Y]) - (r3[Y] - r2[Y]);
    
      // Iteration Step 0
      for (step = 0 ; step < Iterations ; step++)
      {  
      
        // Solution vector
        solVec[X] = (double) rraw_r0[X] - (W * (double) r01_r32[X]);
        solVec[Y] = (double) rraw_r0[Y] - (W * (double) r01_r32[Y]);
    
        // Determinant
        D_XY[X] = -(((double) r3_r0[X] * solVec[Y]) - ((double) r3_r0[Y] * solVec[X]));
        D_XY[Y] =   ((double) r1_r0[X] * solVec[Y]) - ((double) r1_r0[Y] * solVec[X]);
    
        // factor
        factor[X] = (double) D_XY[X] / (double) D;
        factor[Y] = (double) D_XY[Y] / (double) D;
    
        // New iteration parameter:
        W = factor[X] * factor[Y];
      }
      *xp = (ui16_t) (factor[X] * ((double) (LCD_Width - 1)));
      *yp = (ui16_t) (factor[Y] * ((double) (LCD_Height - 1)));
    }
    #ifndef MfG
    #define MfG

  4. #14
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Hi, Jaecko,

    auf Deinem Video sieht das schon ziemlich gut aus ! Ich hätte auch nicht gedacht, dass die Umrechnung so schnell geht.

    Mit meinen beschränkten C-Kenntnissen (bin ein Pascal-Veteran) habe ich in Deinem Programm keinen Fehler gefunden. Der Sprung in der rechten Hälfte des Touchscreens könnte imho daher kommen, dass ein signed Typ als unsigned interpretiert wird oder umgekehrt... In diesem Sinne kommen mir die Zeilen

    *xp = (ui16_t) (factor[X] * ((double) (LCD_Width - 1)));
    *yp = (ui16_t) (factor[Y] * ((double) (LCD_Height - 1)));

    verdächtig vor.

    Ciao,

    mare_crisium

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    41
    Beiträge
    2.009
    Sooo... jetzt gehts. Dieser Fehler in der rechten Hälfte war ein "Fehler" in der Kombination Algorithmus + Displayansteuerung. War manchmal so, dass es ging und der Displayinhalt plötzlich als ganzes verschoben wurde. Also konnts kein Rechenfehler sein (da ja bereits gezeichnete Pixel nicht verändert werden).

    Im Algorithmus können als Endergebnis Positionen rauskommen, die ausserhalb des Display-Bereichs liegen (u.a. häufiger "inf"). Da das Display ja nur 128x64 Pixel hat, scheints der Treiber nicht zu packen, wenn er grössere bzw. unendliche Werte kriegt.

    Packt man in die Funktion unter die Zuweisungen von *xp und *yp noch die folgenden Zeilen, dann gehts (bis auf wenige Ausreisserpixel, die aber im Video auch zu sehen sind) fehlerfrei.

    Code:
      *xp = (i16_t) (factor[X] * ((double) (LCD_Width - 1)));
      *yp = (i16_t) (factor[Y] * ((double) (LCD_Height - 1)));
    
      // prevent 'tilt' of display driver by eliminating invalid values
      if (*xp > (LCD_Width - 1))
      {
        *xp = LCD_Width - 1;
      }
      if (*yp > (LCD_Height - 1))
      {
        *yp = LCD_Height - 1;
      }

    (Ein neues Video folgt demnächst)
    #ifndef MfG
    #define MfG

  6. #16
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Na, Jaecko,

    prima, dass es jetzt läuft ! Was meinst Du mit "häufiger inf"? Division durch Null?

    Bin gespannt auf das nächste Video. Zeichne mal einen Weihnachtsbaum!

    Frohe Weihnacht

    mare_crisium

  7. #17
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    41
    Beiträge
    2.009
    Hier mal der Baum... keine Schönheit, aber glaub man erkennts:
    http://www.youtube.com/watch?v=wPJbjVy5GlQ

    Ich hab mir in der Funktion mal die Werte von xp/yp bzw. factor[n] ausgeben lassen. Stellenweise ist es so, dass dort statt dem eigentlichen Wert (der auch dann stimmt, wenns am Bildschirm falsch dargestellt ist), "inf" drinsteht. Und sobald dieses "inf" zum ersten Mal auftaucht, spinnt das Display.

    Das komische: Die einzige Division ist durch die Determinante... und die ist durch die vorgegebenen Werte aber konstant != 0.

    Nen Pipelineeffekt halt ich jetzt mal für unwahrscheinlich.
    (also, dass die Berechnung schon ausgeführt wird, während ein vorheriges Ergebnis noch nicht fertig ist)

    Ebenfalls frohe Weihnachten.
    #ifndef MfG
    #define MfG

  8. #18
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    10.03.2005
    Alter
    35
    Beiträge
    967
    Hast du dir mal die ADC Werte ausgeben lassen und die dazugehörigen Ausreiserpixelpositionen? Sind das Messfehler vom ADC?
    Ich würde ja gern die Welt verändern..., doch Gott gibt mir den Quellcode nicht!

  9. #19
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    41
    Beiträge
    2.009
    Die ganzen Werte stimmen. Der Fehler scheint erst bei der Division aufzutreten, und da eben auch nicht immer.

    Und auch wenn andere ADC-Werte kommen, passiert rein mathematisch nichts "schlimmes". Die Zielkoordinaten sind dann einfach woanders, aber nicht unendlich.

    Im grossen und ganzen funktionierts ja, und wenn man weiss, dass man unendliche Werte abfangen/ignorieren muss, dann isses eh perfekt.
    #ifndef MfG
    #define MfG

  10. #20
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Jaecko,

    Na, das ist doch eine schöner Baum - sogar mit ein bisschen Schneegestöber (vor allem auf der rechten Seite) !

    Um einen pile-up-Effekt noch sicherer auszuschliessen, würde ich die Berechnung der unveränderlichen Grössen (z.B. der Determinante) nur einmal, nämlich beim Kalibrieren des Touchscreens, ausführen und sie in globalen Variablen speichern. Das verringert die Rechenzeit für TPAD_Get_PosPrecise und beugt etwelchen pile-ups vor. Statt des Wertes D der Determinante würde ich (1/D) speichern, so dass in der Routine nur multipliziert werden muss.

    Mathematisch gesehen, wird die Determinante nur dann Null, wenn das Eingabeviereck echt krank verzerrt ist, z.B. so, dass zwei Seiten zusammenfallen oder dass eine Seite fast auf Null zusammengeschnurrt ist. Bei Werten, die im normalen Betrieb auftreten, sind die beiden Elemente in der Hauptdiagonalen immer grösser als Null und immer deutlich grösser als die beiden anderen - das sind optimale Bedingungen für endliche Lösungen.

    Ciao,

    mare_crisium

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress