Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2024:ddosaru:marius.cristea1811 [2024/05/27 01:38]
marius.cristea1811 [Hardware Design]
pm:prj2024:ddosaru:marius.cristea1811 [2024/05/27 02:10] (current)
marius.cristea1811 [Software Design]
Line 52: Line 52:
  
 Schema cablaj: \\ Schema cablaj: \\
-{{:​pm:​prj2024:​ddosaru:​1_schcab.jpg?200|}}+{{:​pm:​prj2024:​ddosaru:​1_schcab.png?​200|}} ​\\
 Schema electrica: \\  Schema electrica: \\ 
 {{:​pm:​prj2024:​ddosaru:​1_schel.png?​200|}} \\ {{:​pm:​prj2024:​ddosaru:​1_schel.png?​200|}} \\
 Poza cablaj: \\ Poza cablaj: \\
 {{:​pm:​prj2024:​ddosaru:​1-zacablaj.jpg?​200|}} \\ {{:​pm:​prj2024:​ddosaru:​1-zacablaj.jpg?​200|}} \\
-Poza proiect: \\ 
-{{:​pm:​prj2024:​ddosaru:​1-zalook.jpg?​200|}} 
  
-Tin sa mentionez ca in schema cablajului nu este acelasi amplificator audio pe care il folosesc pentru ca nu am gasit schema exacta a componentei,​ dar este unul similar. In schema electrica am realizat manual pentru amplificatorul audio desenul.\\+Tin sa mentionez ca in schema cablajului nu este acelasi amplificator audio pe care il folosesc pentru ca nu am gasit schema exacta a componentei,​ dar este unul similar.\\
  
 ===== Conexiuni pini ===== ===== Conexiuni pini =====
 pinuri digitale: \\ pinuri digitale: \\
-SCK - pin 13 pentru microSD card reader si LCD (la comun) ​\\ +SCK - pin 13 pentru microSD card reader si LCD \\ 
-MOSI - pin 11 pentru microSD card reader si LCD (la comun) ​\\+MOSI - pin 11 pentru microSD card reader si LCD  \\
 pin 4 - CS microSD card reader \\ pin 4 - CS microSD card reader \\
 pin 8 - RES LCD \\ pin 8 - RES LCD \\
 pin 9 - DC LCD \\ pin 9 - DC LCD \\
 +pin 9 - Speaker (pe arduino nano) \\
 pin 10 - CS LCD \\ pin 10 - CS LCD \\
 pinuri analog: \\ pinuri analog: \\
  
-pin 2: input pentru speaker conectat la IN - amplificator \\ +pin A0,A1,A2,A3,A4: pinii pentru butoane \\
-pin 0,1,3,4,5: pinii pentru butoane \\+
  
  
Line 84: Line 82:
  
 <note tip> <note tip>
-Descrierea codului aplicaţiei (firmware): + 
-  * mediu de dezvoltare ​(if any) (e.g. AVR Studio, CodeVisionAVR) +  * mediu de dezvoltare: Arduino IDE \\ 
-  * librării şi surse 3rd-party (e.g. Procyon AVRlib) +  * librarii: Adafruit_GFX;​ Adafruit_ST7735;​ TMRpcm 
-  ​* algoritmi şi structuri pe care plănuiţi să le implementaţi +  ​
-  * (etapa 3) surse şi funcţii implementate+
 </​note>​ </​note>​
  
-===== Rezultate Obţinute =====+Codul pentru joc: \\ 
 +<file PM_project>​
  
-<note tip+#​include ​<Adafruit_GFX.h
-Care au fost rezultatele obţinute în urma realizării proiectului vostru+#include <​Adafruit_ST7735.h> 
-</note>+#​include ​<SPI.h>
  
-===== Concluzii =====+// Definirea pinilor pentru LCD 
 +#define TFT_CS ​    10 
 +#define TFT_RST ​   8 
 +#define TFT_DC ​    9
  
-===== Download =====+// Definirea pinilor pentru butoane 
 +#define BUTTON_UP ​     A0 
 +#define BUTTON_DOWN ​   A4 
 +#define BUTTON_LEFT ​   A1 
 +#define BUTTON_RIGHT ​  A2 
 +#define BUTTON_SELECT ​ A3
  
-<note warning> +// Crearea unui obiect Adafruit_ST7735 pentru ecranul LCD 
-O arhivă ​(sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ surseschemeetc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CSTFT_DCTFT_RST);
  
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:​pm:​prj20??:​c?​** sau **:​pm:​prj20??:​c?:​nume_student** (dacă este cazul). **Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +// Dimensiuni grilă 
-</​note>​+#define GRID_SIZE 3 
 +#define CELL_SIZE 30 
  
-===== Jurnal =====+// Debounce 
 +unsigned long lastDebounceTime ​0; 
 +unsigned long debounceDelay ​200;
  
-<note tip+// Starea jocului 
-Puteți avea șo secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului+char board[GRID_SIZE][GRID_SIZE];​ 
-</note>+int currentPlayer = 0; // 0 pentru X, 1 pentru O 
 +int currentRow = 0, currentCol = 0; 
 + 
 +// Structuri pentru a ține evidența mutărilor fiecărui jucător 
 +struct Move { 
 +  int row; 
 +  int col; 
 +}; 
 + 
 +Move movesX[3];​ 
 +Move movesO[3];​ 
 +int moveCountX = 0; 
 +int moveCountO = 0; 
 + 
 +// Calcularea coordonatelor pentru centrare 
 +int gridStartX = (tft.width() - (GRID_SIZE * CELL_SIZE)) / 2; 
 +int gridStartY = (tft.height() - (GRID_SIZE * CELL_SIZE) - 40) / 2; 
 + 
 +bool gameWon = false; 
 +bool alreadyDisplayed = false; 
 +unsigned long winTime; 
 + 
 +void setup() { 
 +  Serial.begin(9600);​ 
 + 
 +  // Inițializarea LCD-ului 
 +  tft.initR(INITR_BLACKTAB);​ 
 +  tft.fillScreen(ST77XX_BLACK);​ // Curățarea ecranului și umplerea cu negru 
 + 
 +  // Inițializarea pinilor pentru butoane 
 +  pinMode(BUTTON_UP,​ INPUT_PULLUP);​ 
 +  pinMode(BUTTON_DOWN,​ INPUT_PULLUP);​ 
 +  pinMode(BUTTON_LEFT,​ INPUT_PULLUP);​ 
 +  pinMode(BUTTON_RIGHT,​ INPUT_PULLUP);​ 
 +  pinMode(BUTTON_SELECT,​ INPUT_PULLUP);​ 
 + 
 +  // Inițializarea tablei de joc 
 +  for (int i = 0; i GRID_SIZE; i++) { 
 +    for (int j = 0; j < GRID_SIZE; j++) { 
 +      board[i][j] = ' '; 
 +    } 
 +  } 
 + 
 +  // Desenarea grilei 
 +  drawGrid();​ 
 +  highlightCell(currentRow,​ currentCol, true); 
 +
 + 
 + 
 +void loop() { 
 +  if (gameWon) { 
 +    if (millis() - winTime ​10000) { // Așteaptă 10 secunde înainte de resetare 
 +      ​resetBoard();​ 
 +      gameWon = false; 
 +      alreadyDisplayed = false; 
 +      tft.fillScreen(ST77XX_BLACK);​ 
 +      drawGrid();​ 
 +    } else { 
 +      if (!alreadyDisplayed) { 
 +        char winner; 
 +        if (currentPlayer == 0) { 
 +          winner = '​X';​ 
 +        } else { 
 +          winner = '​O';​ 
 +        } 
 +        displayWinner(winner);​ 
 +        alreadyDisplayed = true; 
 +        currentPlayer = 0; 
 +      } 
 +    } 
 +    return; 
 +  } else { 
 +    readButtons();​ 
 +    // Evidențiere celula curentă 
 +    highlightCell(currentRow,​ currentCol, true); 
 +  } 
 +
 + 
 +void readButtons() { 
 +  if (millis() - lastDebounceTime > debounceDelay) { 
 +    if (digitalRead(BUTTON_UP) == LOW) { 
 +      lastDebounceTime = millis(); 
 +      moveCursor(0,​ -1); // Muta sus 
 +    } 
 +     
 +    if (digitalRead(BUTTON_DOWN) == LOW) { 
 +      lastDebounceTime = millis(); 
 +      moveCursor(0,​ 1); // Muta jos 
 +    } 
 +     
 +    if (digitalRead(BUTTON_LEFT) == LOW) { 
 +      lastDebounceTime = millis(); 
 +      moveCursor(-1,​ 0); // Muta stânga 
 +    } 
 +     
 +    if (digitalRead(BUTTON_RIGHT) == LOW) { 
 +      lastDebounceTime = millis(); 
 +      moveCursor(1,​ 0); // Muta dreapta 
 +    } 
 + 
 +    if (digitalRead(BUTTON_SELECT) == LOW) { 
 +      lastDebounceTime = millis(); 
 +      placeMark();​ // Selecteaza miscare 
 +    } 
 +  } 
 +
 + 
 +void drawGrid() { 
 +  for (int = 1; < GRID_SIZE; i++) { 
 +    tft.drawLine(gridStartX + CELL_SIZE * i, gridStartY, gridStartX + CELL_SIZE * i, gridStartY + GRID_SIZE * CELL_SIZE, ST77XX_WHITE);​ 
 +    tft.drawLine(gridStartX,​ gridStartY + CELL_SIZE * i, gridStartX + GRID_SIZE * CELL_SIZE, gridStartY + CELL_SIZE * i, ST77XX_WHITE);​ 
 +  } 
 +
 + 
 +void highlightCell(int row, int col, bool highlight) { 
 +  // Curățăm celula anterioară (dacă există) 
 +  for (int i = 0; i < GRID_SIZE; i++) { 
 +    for (int j = 0; j < GRID_SIZE; j++) { 
 +      if (i == row && j == col) continue; 
 +      int x = gridStartX + j * CELL_SIZE;​ 
 +      int y = gridStartY + i * CELL_SIZE;​ 
 +      tft.drawRect(x,​ y, CELL_SIZE, CELL_SIZE, ST77XX_WHITE);​ 
 +      if (board[i][j] != ' ') { 
 +        drawMark(i, j, board[i][j]);​ 
 +      } 
 +    } 
 +  } 
 + 
 +  // Evidențiem celula curentă 
 +  int x = gridStartX + col * CELL_SIZE;​ 
 +  int y = gridStartY + row * CELL_SIZE;​ 
 +  tft.drawRect(x,​ y, CELL_SIZE, CELL_SIZE, highlight ? ST77XX_BLUE : ST77XX_WHITE);​ 
 +  // Redesenăm conținutul celulei după evidențiere pentru a nu o pierde 
 +  if (board[row][col] != ' ') { 
 +    drawMark(row,​ col, board[row][col]);​ 
 +  } 
 +
 + 
 +void moveCursor(int dx, int dy) { 
 +  currentCol = (currentCol + dx + GRID_SIZE) % GRID_SIZE;​ 
 +  currentRow = (currentRow + dy + GRID_SIZE) % GRID_SIZE;​ 
 +
 + 
 +void placeMark() { 
 +  if (board[currentRow][currentCol] == ' ') { 
 +    char mark = currentPlayer == 0 ? '​X'​ : '​O';​ 
 +    board[currentRow][currentCol] = mark; 
 +    drawMark(currentRow,​ currentCol, mark); 
 + 
 +    // Adaugă mutarea la istoricul mutărilor jucătorului curent 
 +    if (currentPlayer == 0) { 
 +      if (moveCountX >= 3) { 
 +        Move oldestMove = movesX[moveCountX % 3]; 
 +        board[oldestMove.row][oldestMove.col] = ' '; 
 +        drawMark(oldestMove.row,​ oldestMove.col,​ ' '); 
 +      } 
 +      movesX[moveCountX % 3] = {currentRow,​ currentCol};​ 
 +      moveCountX++;​ 
 +    } else { 
 +      if (moveCountO >= 3) { 
 +        Move oldestMove = movesO[moveCountO % 3]; 
 +        board[oldestMove.row][oldestMove.col] = ' '; 
 +        drawMark(oldestMove.row,​ oldestMove.col,​ ' '); 
 +      } 
 +      movesO[moveCountO % 3] = {currentRow,​ currentCol};​ 
 +      moveCountO++;​ 
 +    } 
 + 
 +    // Verifică dacă jucătorul curent a câștigat 
 +    if (checkWin(currentRow,​ currentCol, mark)) { 
 +      winTime = millis(); // Setează timpul ​de câștig 
 +      gameWon = true;     // Setează starea de câștig 
 +      return; 
 +    } 
 + 
 +    // Schimbă jucătorul 
 +    currentPlayer = 1 - currentPlayer;​ 
 +    displayCurrentPlayer();​ 
 + 
 +  } 
 +
 + 
 +void drawMark(int row, int col, char mark) { 
 +  int x = gridStartX + col * CELL_SIZE + CELL_SIZE / 2 - 5; 
 +  int y = gridStartY + row * CELL_SIZE + CELL_SIZE / 2 - 8; 
 +  tft.setCursor(x,​ y); 
 +  tft.setTextColor(ST77XX_WHITE);​ 
 +  tft.setTextSize(2);​ 
 +  if (mark == ' ') { 
 +    // Curățăm marca 
 +    tft.fillRect(gridStartX + col * CELL_SIZE + 1, gridStartY + row * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2, ST77XX_BLACK);​ 
 +  } else { 
 +    tft.print(mark);​ 
 +  } 
 +
 + 
 +bool checkWin(int row, int col, char mark) { 
 +  // Verifică rândul 
 +  if (board[row][0] == mark && board[row][1] == mark && board[row][2] == mark) return true; 
 +  // Verifică coloana 
 +  if (board[0][col] == mark && board[1][col] == mark && board[2][col] == mark) return true; 
 +  // Verifică diagonalele 
 +  if (board[0][0] == mark && board[1][1] == mark && board[2][2] == mark) return true; 
 +  if (board[0][2] == mark && board[1][1] == mark && board[2][0] == mark) return true; 
 +  return false; 
 +
 + 
 +void displayWinner(char winner) { 
 +  tft.fillScreen(ST77XX_BLACK);​ 
 + 
 +  // Definim variabilele pentru a stoca limitele textului 
 +  int16_t x1, y1; 
 +  uint16_t w, h; 
 + 
 +  // Creăm textul complet ​care va fi afișat 
 +  String text = "​Player "; 
 +  text += winner; 
 +  text += " won!";​ 
 + 
 +  // Setăm dimensiunea textului 
 +  tft.setTextSize(1);​ 
 + 
 +  // Obținem limitele textului 
 +  tft.getTextBounds(text.c_str(),​ 0, 0, &x1, &y1, &w, &h); 
 + 
 +  // Calculăm pozițiile cursorului pentru a centra textul 
 +  int16_t centeredX = (tft.width() - w) / 2; 
 +  int16_t centeredY = (tft.height() - h) / 2; 
 + 
 +  // Setăm culoarea textului 
 +  tft.setTextColor(ST77XX_WHITE);​ 
 + 
 +  // Setăm cursorul la poziția calculată 
 +  tft.setCursor(centeredX,​ centeredY);​ 
 + 
 +  // Afișăm textul 
 +  tft.print(text);​ 
 + 
 +  // Coordonatele centrului smiley face-ului 
 +  int16_t smileyX = tft.width() / 2; 
 +  int16_t smileyY = centeredY / 2; // Poziționăm smiley face-ul deasupra textului 
 + 
 +  // Dimensiunea smiley face-ului 
 +  int16_t radius = 20; 
 + 
 +  // Desenam smiley face-ul 
 +  tft.drawCircle(smileyX,​ smileyY, radius, ST77XX_WHITE);​ 
 +  tft.fillCircle(smileyX - radius / 3, smileyY - radius / 3, 2, ST77XX_WHITE);​ 
 +  tft.fillCircle(smileyX + radius / 3, smileyY - radius / 3, 2, ST77XX_WHITE);​ 
 +  drawArc(smileyX,​ smileyY, radius - 5, 0, 180, ST77XX_WHITE);​ 
 +
 + 
 +void drawArc(int16_t x, int16_t y, int16_t radius, int16_t startAngle, int16_t endAngle, uint16_t color) { 
 +  for (int16_t angle = startAngle; angle <= endAngle; angle++) { 
 +    float rad = angle * 3.14 180; 
 +    int16_t x1 = x + cos(rad) * radius; 
 +    int16_t y1 = y + sin(rad) * radius; 
 +    tft.drawPixel(x1,​ y1, color); 
 +  } 
 +
 + 
 +void resetBoard() { 
 +  for (int i = 0; i < GRID_SIZE; i++) { 
 +    for (int j = 0; j < GRID_SIZE; j++) { 
 +      board[i][j] = ' '; 
 +    } 
 +  } 
 +  moveCountX = 0; 
 +  moveCountO = 0; 
 +  drawGrid();​ 
 +  highlightCell(currentRow,​ currentCol, true); 
 +
 + 
 +void displayCurrentPlayer() { 
 +  // Șterge zona jucătorului curent 
 +  tft.fillRect(0,​ GRID_SIZE * CELL_SIZE + gridStartY, tft.width(),​ 20, ST77XX_BLACK);​ 
 + 
 +  // Definim variabilele pentru a stoca limitele textului 
 +  int16_t x1, y1; 
 +  uint16_t w, h; 
 + 
 +  // Creăm textul complet care va fi afișat 
 +  String text = "​Player:​ "; 
 +  text += (currentPlayer == 0) ? '​X'​ : '​O';​ 
 + 
 +  // Setăm dimensiunea textului 
 +  tft.setTextSize(1);​ 
 + 
 +  // Obținem limitele textului 
 +  tft.getTextBounds(text.c_str(),​ 0, 0, &x1, &y1, &w, &h); 
 + 
 +  // Calculăm pozițiile cursorului pentru a centra textul 
 +  int16_t centeredX = (tft.width() - w) / 2; 
 +  int16_t centeredY = gridStartY + GRID_SIZE * CELL_SIZE + 5; 
 + 
 +  // Setăm cursorul la poziția calculată 
 +  tft.setCursor(centeredX,​ centeredY);​ 
 + 
 +  // Setăm culoarea textului 
 +  tft.setTextColor(ST77XX_WHITE);​ 
 + 
 +  // Afișăm textul 
 +  tft.print(text);​ 
 +
 + 
 +</file> 
 + 
 +Codul pentru muzica: \\ 
 +<file music> 
 +#include <​SPI.h>​ 
 +#include <​SD.h>​ 
 +#include <​TMRpcm.h>​ 
 + 
 +#define CS_SD 4 
 +#define Speaker 9 
 +TMRpcm audio; 
 + 
 +void setup() { 
 +  Serial.begin(9600);​ 
 + 
 +  if(!SD.begin(CS_SD)) { 
 +    Serial.println("​A esuat initializarea cardului SD"​);​ 
 +    while(1); 
 +  } 
 + 
 +  audio.CSPin = CS_SD; 
 +  audio.speakerPin = Speaker; 
 +  audio.setVolume(6);​ 
 + 
 +
 + 
 +void loop() {   
 +  if (!audio.isPlaying()) { 
 +    audio.play("​powerup.wav"​);​ 
 +  } 
 +
 + 
 + 
 + 
 + 
 + 
 +</​file>​ 
 +===== Rezultate Obţinute ===== 
 + 
 + 
 +{{:​pm:​prj2024:​ddosaru:​1-zalook.jpg?​200|}} 
 + 
 +Acesta este rezultatul final al proiectului. Am facut cutia astfel incat sa se poata deschida pentru a se vedea cablajul. LCD-ul si butoanele se pot inlatura sau baga in cutie.
  
 +<​html>​
 +<iframe width="​700"​ height="​435"​ src="​https://​youtube.com/​embed/​kd_nhWqsvPM?​feature=share"​ title="​YouTube video player"​ frameborder="​0"​ allow="​accelerometer;​ autoplay; clipboard-write;​ encrypted-media;​ gyroscope; picture-in-picture;​ web-share"​ referrerpolicy="​strict-origin-when-cross-origin"​ allowfullscreen></​iframe>​
 +</​html>​
pm/prj2024/ddosaru/marius.cristea1811.1716763110.txt.gz · Last modified: 2024/05/27 01:38 by marius.cristea1811
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0