Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2014:teeter-game

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
Poslední revize Obě strany příští revize
2014:teeter-game [2015/01/19 00:46]
Roman Deneš
2014:teeter-game [2015/01/19 02:03]
Roman Deneš
Řádek 5: Řádek 5:
 Na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]] realizujte androidovou hru teeter. Na základě údajů z gyroskopu se na displeji bude pohybovat kulička. Cílem hry je dopravit kuličku na požadované místo. Při pohybu je nutné se vyhnout případným překážkám (stěny, díry). Na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]] realizujte androidovou hru teeter. Na základě údajů z gyroskopu se na displeji bude pohybovat kulička. Cílem hry je dopravit kuličku na požadované místo. Při pohybu je nutné se vyhnout případným překážkám (stěny, díry).
  
 +
 +  ​
 ==== Použitá zařízení ==== ==== Použitá zařízení ====
 Projekt je realizován na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]],​ který obsahuje 2.4" displej ​ QVGA TFT s rozlišením 240x320. Dále byl použit akcelerometr [[http://​www.dipmicro.com/​store/​GY521-MOD|GY-521]]. Projekt je realizován na vývojovém kitu [[http://​www.st.com/​web/​catalog/​tools/​FM116/​SC959/​SS1532/​PF259090|32F429IDISCOVERY]],​ který obsahuje 2.4" displej ​ QVGA TFT s rozlišením 240x320. Dále byl použit akcelerometr [[http://​www.dipmicro.com/​store/​GY521-MOD|GY-521]].
  
 +{{ :​2014:​teeter-game:​imag_teeter.jpg?​300 |Použitá zařízení}}
 +
 +  ​
 Zapojení PINů: Zapojení PINů:
  
Řádek 32: Řádek 37:
 ==== Realizace: ==== ==== Realizace: ====
  
-Celý layout hry je uložen v SDRAM pamětí a při interakci vykreslován na displej zařízení. Nejprve bylo nutné definovat makro pro přístup do paměti na základě souradnic x, y. Pamět není mapována hned od prvního dostupného místa, jelikož některé z dalších knihoven taktéž využívali ​tento prostor a docházelo ke konfliktům. Z toho důvodu je matice v paměti posunuta o přibližně 7 MB.+Celý layout hry je uložen v SDRAM pamětí a při interakci vykreslován na displej zařízení. Nejprve bylo nutné definovat makro pro přístup do paměti na základě souradnic x, y. Pamět není mapována hned od prvního dostupného místa, jelikož některé z dalších knihoven taktéž využívaly ​tento prostor a docházelo ke konfliktům. Z toho důvodu je matice v paměti posunuta o přibližně 7 MB.
  
 <code cpp> <code cpp>
Řádek 42: Řádek 47:
 #define MATRIX_GET_VALUE(x,​ y)       ​TM_SDRAM_Read8(OFFSET + x * Y_SIZE + y) #define MATRIX_GET_VALUE(x,​ y)       ​TM_SDRAM_Read8(OFFSET + x * Y_SIZE + y)
 </​code>​ </​code>​
 +
 +Na jednotlivé pozice se pomocí funkce DrawLayout "​vykreslil"​ požadovaný layout v závislosti na aktuální úrovni. ​ Pod číslem 11 jsou uloženy stěny. Pod číslem 12 pak rozšířený prostor do kterého kulička nemůže vstoupit. Tento prostor odpovídá poloměru kuličky. Pod čísly 5 a 6 jsou jednotlivé díry. K nim odpovídají středu jsou uloženy pod čísly 4 a 7. Pro vykreslování děr (kruhů) je použita modifikovaná funkce z knihovny [[http://​stm32f4-discovery.com/​2014/​06/​library-18-ili9341-ltdc-stm32f429-discovery/​|tm_stm32f4_ili9341_ltdc]]. Místo vykreslování jednotlivých pixelů funkce provádí zápis do paměti.
 +
 +Na konci funkce je pak dvojitá smyčka, která na základě číselných údajů z matice vykresluje na displej jednotlivé barevné pixely.
 +
 +<​code>​
 +    for(i = 0; i < 240; i++){
 +     ​  ​ for(j = 0; j < 320; j++){
 +        if((MATRIX_GET_VALUE(i,​ j)) < 6)
 +        TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_GREEN);​
 +        if((MATRIX_GET_VALUE(i,​ j)) == 6)
 +        TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_YELLOW);​
 +        if((MATRIX_GET_VALUE(i,​ j)) == 11)
 +         ​  ​ TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_YELLOW);​
 +     ​  ​ }
 +    }
 +</​code>​
 +
 +V následující supersmyčce jsou opakovaně čteny data z připojeného akcelerometru,​ které jsou dále zpracována. Nejprve jsou váhována (60 % předchozí hodnoty + 40% z nově načtené hodnoty). Od těchto hodnot je vždy odečtena referenční hodnota, která se načte při zapnutí přistroje. Toto opatření je zejména kvůli nedokonalému připevnění sensoru, který nemusí být v naprosto stejné poloze jako deska.
  
 <code cpp> <code cpp>
-// cteni dat z akceletometru 
         if (sensor1)         if (sensor1)
         TM_MPU6050_ReadAll(&​MPU6050_Data0);​         TM_MPU6050_ReadAll(&​MPU6050_Data0);​
- 
-    Xpos_old = Xpos; 
-    Ypos_old = Ypos; 
  
     // Nacteni vychozi pozice     // Nacteni vychozi pozice
Řádek 62: Řádek 82:
         Y_axis = (Q*Y_axis + (10-Q)*(MPU6050_Data0.Accelerometer_Y - Y_axis_ref))/​10;​         Y_axis = (Q*Y_axis + (10-Q)*(MPU6050_Data0.Accelerometer_Y - Y_axis_ref))/​10;​
  
-        // zmena polohy +           </code> 
-    ​  ​   if(X_axis < -th1){+            
 +Dále se uloží současná poloha a provede se změna na základě údajů z akcelerometru. Zde ukázka pouze pro jeden směr. Poslední podmínka ošetřuje okraj displeje.  
 + 
 +      <​code>​ 
 +          ​  ​   if(X_axis < -th1){
         Xpos++;         Xpos++;
-            if(X_axis < -th2)+               if(X_axis < -th2)
             Xpos++;             Xpos++;
-                if(X_axis < -th3)+                   if(X_axis < -th3)
                 Xpos++;                 Xpos++;
         if(Xpos > 228)         if(Xpos > 228)
         Xpos = 228;         Xpos = 228;
         }         }
 +                                ​
 +                                // dalsi tri smery ...
 +            ​
 +         </​code> ​     ​
  
-        if(X_axis > th1)+Za předpokladu,​ že nově získaná poloha není dostupná ​(zeď), provede se načtení staré polohy. Tato akce probíhá pro oba směry ​(x, yjednotlivě.
-        Xpos--;​ +
-            if(X_axis > th2) +
-            Xpos--;​ +
-                if(X_axis > th3) +
-                Xpos--;​ +
-          if(Xpos < 11) +
-        Xpos = 11; +
-        }+
  
-        if(Y_axis > th1){ +Nově získaná poloha se vykresluje pomocí funkce DrawBall. Nejprve se smaže stará kulička a následně se vykreslí na nových souřadnicích. ​
-        Ypos++;​ +
-            if(Y_axis > th2) +
-            Ypos++;​ +
-                if(Y_axis > th3) +
-                Ypos++;​ +
-     ​  ​        ​ if(Ypos > 308) +
-            Ypos = 308; +
-        }+
  
-        if(Y_axis ​-th1){ +<code> 
-    ​  ​   Ypos--;​ +void DrawBall(uint16_t Xpos, uint16_t ​Ypos, uint16_t Xpos_old, uint16_t Ypos_old
-       ​  ​   if(Y_axis < -th2) +{
-            Ypos--; +
-           ​  ​   if(Y_axis < -th3+
-    ​  ​           Ypos--;​ +
-        if(Ypos < 11) +
-            Ypos = 11; +
-            }+
  
-        // setrvacnost 
-        Xpos += (Xpos-Xpos_old)/​2;​ 
-        Ypos += (Ypos-Ypos_old)/​2;​ 
  
-        // pohyb podel zdi + TM_ILI9341_DrawFilledCircle(Xpos_old, Ypos_old, 10, ILI9341_COLOR_BLACK); 
-        if((MATRIX_GET_VALUE(XposYpos)) > 10){ + TM_ILI9341_DrawFilledCircle(Xpos_old, ​Ypos_old, 10, ILI9341_COLOR_BLACK);
-        if((MATRIX_GET_VALUE(XposYpos_old)) < 11){ +
-               Ypos = Ypos_old+
-    ​  ​   } +
-        else if((MATRIX_GET_VALUE(Xpos_old, ​Ypos)) < 11){ +
-                   Xpos = Xpos_old; +
-        } +
-        else{ +
-        Xpos = Xpos_old; +
-         Ypos = Ypos_old; +
-        } +
-        }+
  
-        // konec hry + TM_ILI9341_DrawFilledCircle(Xpos, Ypos, 10, ILI9341_COLOR_BLUE); 
-        if((MATRIX_GET_VALUE(Xpos, Ypos)) == 5){ + TM_ILI9341_DrawFilledCircle(Xpos, Ypos, 10ILI9341_COLOR_BLUE);
-    ​  ​   DrawDrop(Xpos, Ypos, Xpos_oldYpos_old, LVL_count); +
-        }+
  
-        // dalsi kolo + Delayms(15)
-        if((MATRIX_GET_VALUE(Xpos,​ Ypos)) == 6){+
 +</​code> ​       ​
  
-        DrawDrop(XposYpos, Xpos_old, Ypos_old, LVL_count);​ +Před každým vykreslením kuličky je ještě volána funkce ReDrawLayout,​ která překresluje ​(obnovuje) layout v okolí kuličky. Jde především o vykreslení děrkteré mohou být smazány procházecí kuličkou v těsném okolí.
-        LVL_count++;​ +
-        LVL_change = 1;+
  
-         Xpos = 220; +<​code>​  
-         Ypos = 300; +void ReDrawLayout(uint16_t ​Xpos, uint16_t ​Ypos){
-        Xpos_old = 220; +
-        Ypos_old = 300;+
  
-        }+    ​static uint16_t i, j;
  
 +       for(i = (Xpos-20); i < (Xpos+20); i++){
 +          for(j = (Ypos-20); j < (Ypos+20); j++){
 +           ​ if((MATRIX_GET_VALUE(i,​ j)) < 6)
 +           ​ TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_GREEN);​
  
 +           ​ if((MATRIX_GET_VALUE(i,​ j)) == 6)
 +           ​  ​  ​TM_ILI9341_DrawPixel(i,​ j, ILI9341_COLOR_YELLOW);​
  
-        ReDrawLayout(XposYpos); +          if((MATRIX_GET_VALUE(ij)) == 11
-    ​ DrawBall(XposYposXpos_old, Ypos_old);+            ​  ​ TM_ILI9341_DrawPixel(ijILI9341_COLOR_YELLOW); 
 +          } 
 +       } 
 +
 +</​code> ​
  
-        if(LVL_change == 1){+V případě, že kulička spadne do díry (načtená souřadnice má hodnotu 5 nebo 6je volána funkce DrawDrop, která provede animaci kuličky do díry a vykreslení (mezi)výsledků.
  
-        LVL_change = 0; +<​code> ​ 
-    ​  ​   DrawLayout(LVL_count);+void DrawDrop(uint16_t Xpos, uint16_t Ypos, uint16_t Xpos_old, uint16_t Ypos_old, uint8_t level) 
 +{
  
  
-        }+ TM_ILI9341_DrawFilledCircle(Xpos_old,​ Ypos_old, 10, ILI9341_COLOR_BLACK);​ 
 + 
 + TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 + 
 + 
 + uint16_t i, j; 
 + uint16_t Xmid, Ymid; 
 + int16_t deltaX, deltaY; 
 + 
 +    for(i = (Xpos-22); i < (Xpos+22); i++){ 
 +     ​  ​ for(j = (Ypos-22); j < (Ypos+22); j++){ 
 +     ​  ​ if((MATRIX_GET_VALUE(i,​ j) == 4 )|(MATRIX_GET_VALUE(i,​ j) == 7 )){ 
 +     ​  ​ Xmid = i; 
 +     ​  ​ Ymid = j; 
 +     ​   ​} 
 +       ​  ​ } 
 +    } 
 + 
 +    deltaX = (Xmid-Xpos);​ 
 +    deltaY = (Ymid-Ypos);​ 
 + 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos,​ Ypos, 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+deltaX/​4,​ Ypos+deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+deltaX/​4,​ Ypos+deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+2*deltaX/​4,​ Ypos+2*deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+2*deltaX/​4,​ Ypos+2*deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xpos+3*deltaX/​4,​ Ypos+3*deltaY/​4,​ 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 +    TM_ILI9341_DrawFilledCircle(Xpos+3*deltaX/​4,​ Ypos+3*deltaY/​4,​ 10, ILI9341_COLOR_BLACK);​ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 10, ILI9341_COLOR_BLUE);​ 
 +    Delayms(50);​ 
 + 
 + 
 +    // 
 + if((MATRIX_GET_VALUE(Xpos,​ Ypos)) == 5){ 
 + 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 12, ILI9341_COLOR_BLUE2);​ 
 +    TM_ILI9341_DrawFilledCircle(Xmid,​ Ymid, 10, ILI9341_COLOR_BLUE);​ 
 + 
 + 
 + Delayms(1250);​ 
 + 
 + 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +    Delayms(250);​ 
 +    TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 +     ​ Delayms(250);​ 
 +        TM_ILI9341_Fill(ILI9341_COLOR_BLACK);​ 
 +        Delayms(250);​ 
 +        TM_ILI9341_Fill(ILI9341_COLOR_RED);​ 
 + 
 + TM_ILI9341_Puts(50,​ 100, "Game Over", &​TM_Font_16x26,​ 0x0000, ILI9341_COLOR_RED);​ 
 + 
 + while(1){} 
 + 
 +
 +             // Obdobne i pro MATRIX_GET_VALUE(Xpos,​ Ypos)) == 6 -> dalsi kolo. 
 + 
 +
 + 
 + 
 +</​code>​  
 + 
 +==== Závěr ==== 
 + 
 +V projektu byl místo interního gyroskopu využit externí akcelerometr,​ jelikož se na danou aplikace hodí lépe. Zadání bylo splněno, hra je plně funkční.  
 + 
 +Video je k dispozici na adrese https://​www.youtube.com/​watch?​v=NFYOeizr5jU&​feature=youtu.be. Výsledný soubor je uložen v souborovém systému.
  
-           } 
-           </​code>​ 
2014/teeter-game.txt · Poslední úprava: 2015/01/19 02:17 autor: Roman Deneš