This shows you the differences between two versions of the page.
|
pm:prj2025:fstancu:dan.vrinceanu [2025/05/27 23:50] dan.vrinceanu [Rezultate Obţinute] |
pm:prj2025:fstancu:dan.vrinceanu [2025/05/28 09:28] (current) dan.vrinceanu [Main application flow] |
||
|---|---|---|---|
| Line 78: | Line 78: | ||
| * LCD-ul afișează din nou: Mod: Manual | * LCD-ul afișează din nou: Mod: Manual | ||
| - | ===GitHub:=== | + | ==== Motivația Alegerii Bibliotecilor ==== |
| - | https://github.com/ | + | |
| - | {{:pm:prj2025:fstancu:img_2148.jpg?300|}} | + | === Arduino Libraries === |
| - | {{:pm:prj2025:fstancu:img_2149.jpg?260|}} | + | |
| + | ==== Motivația Alegerii Bibliotecilor ==== | ||
| + | |||
| + | === ESP32 Robotics Libraries === | ||
| + | |||
| + | #include <DabbleESP32.h> // Control Bluetooth cu aplicația mobilă Dabble (GamePad virtual) | ||
| + | #include <ESP32Servo.h> // Compatibilitate PWM pentru control precis al servomotoarelor pe ESP32 | ||
| + | #include <NewPing.h> // Măsurători rapide și stabile cu senzorul ultrasonic HC-SR04 | ||
| + | #include <Wire.h> // Comunicație I²C între ESP32 și periferice | ||
| + | #include <LiquidCrystal_I2C.h> // Afișare text pe LCD 16x2 cu interfață I²C | ||
| + | |||
| + | Justificare: | ||
| + | Am ales aceste biblioteci pentru a realiza un sistem robotic autonom cu control manual prin Bluetooth și feedback vizual. | ||
| + | |||
| + | - `DabbleESP32` permite interacțiunea prin aplicația mobilă fără componente fizice externe. | ||
| + | - `ESP32Servo` este necesară pentru compatibilitate cu PWM-ul specific ESP32, esențial în orientarea senzorului ultrasonic. | ||
| + | - `NewPing` asigură măsurători eficiente ale distanței fără blocaje, utile pentru evitarea obstacolelor. | ||
| + | - `Wire` este standard pentru comunicație I²C, permițând integrarea simplă a mai multor senzori sau afișaje. | ||
| + | - `LiquidCrystal_I2C` oferă un mod convenabil de a afișa mesaje de stare, diagnostic sau feedback pentru utilizator. | ||
| + | |||
| + | ==== Laboratoarele ==== | ||
| + | |||
| + | === Laboratorul 0: GPIO === | ||
| + | Folosit pentru controlul pinilor digitali – pornirea/opirea motoarelor, citirea stării senzorului IR. | ||
| + | |||
| + | === Laboratorul 1: UART === | ||
| + | Utilizat pentru comunicarea serială cu computerul prin Serial.begin() – afişează mesaje de stare și debug. | ||
| + | |||
| + | === Laboratorul 3: Timere. PWM === | ||
| + | PWM este folosit pentru a controla poziția servomotorului (ex: rotirea senzorului ultrasonic pentru detectarea obstacolelor). | ||
| + | |||
| + | === Laboratorul 6: I2C === | ||
| + | |||
| + | Folosit pentru comunicarea cu ecranul LCD 1602 prin interfața I2C – afişează mesaje despre obstacole, prăpastii sau conexiunea cu aplicația. | ||
| + | |||
| + | ==== Element de Noutate al Proiectului ==== | ||
| + | |||
| + | Integrarea controlului manual prin Bluetooth (Dabble) cu un sistem autonom de evitare a obstacolelor și prăpastiilor. | ||
| + | Robotul poate schimba direcția și viteza în timp real, oferind feedback pe LCD și folosind un servomotor pentru scanare laterală. | ||
| + | Această combinație de autonomie și interactivitate mobilă face proiectul versatil și inovator. | ||
| + | |||
| + | ==== Calibrarea senzorilor ==== | ||
| + | Senzor ultrasonic (HC-SR04) | ||
| + | Am setat o distanță maximă de detecție (200 cm) și un prag pentru obstacol (20 cm). | ||
| + | Am testat valorile în monitorul serial pentru a verifica funcționarea corectă. | ||
| + | Senzor IR | ||
| + | Am calibrat detectarea marginii ca semnal LOW. | ||
| + | Am verificat comportamentul apropiind senzorul de o margine (ex. masă). | ||
| + | Servomotor + senzor ultrasonic | ||
| + | Am setat unghiuri fixe (50° și 130°) pentru scanare laterală. | ||
| + | Am verificat că senzorul măsoară distanța corect în ambele direcții. | ||
| + | |||
| + | |||
| + | ===== Main application flow ===== | ||
| + | |||
| + | **Setup** | ||
| + | * Inițializează comunicația serială la 115200 baud. | ||
| + | * Configurează pinurile pentru: | ||
| + | - Motoare (IN1, IN2, IN3, IN4) | ||
| + | - Senzor IR (prăpastie) | ||
| + | - Ultrasunete (TRIG, ECHO) | ||
| + | - Servomotor (SERVO_PIN) | ||
| + | * Atașează servomotorul și îl poziționează inițial la 90°. | ||
| + | * Inițializează conexiunea Bluetooth cu aplicația Dabble. | ||
| + | * Configurează magistrala I2C (Wire.begin) pentru LCD. | ||
| + | * Inițializează LCD-ul (16x2) și aprinde lumina de fundal. | ||
| + | * Afișează mesaj pe ecran: "Conecteaza-te, sefule". | ||
| + | |||
| + | <code cpp> | ||
| + | void setup() | ||
| + | { | ||
| + | Serial.begin(115200); | ||
| + | setUpPinModes(); | ||
| + | Dabble.begin("MyBluetoothCar"); | ||
| + | |||
| + | Wire.begin(25, 26); // SDA, SCL | ||
| + | lcd.init(); | ||
| + | lcd.backlight(); | ||
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Conecteaza-te"); | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("sefule "); | ||
| + | |||
| + | Serial.println("Dabble și LCD inițiate, aștept conectarea..."); | ||
| } | } | ||
| - | ===== Rezultate Obţinute ===== | + | </code> |
| - | {{:pm:prj2025:fstancu:img_dan1.jpg?400|}} | + | |
| - | {{:pm:prj2025:fstancu:img_dan2.jpg?400|}} | + | |
| + | --- | ||
| - | ===== Concluzii ===== | + | **Main Loop** |
| + | * Procesează comenzile de la Dabble. | ||
| + | * Dacă aplicația nu e conectată: | ||
| + | - Afișează mesaj și iese temporar din buclă. | ||
| + | * La prima conectare: | ||
| + | - Afișează "Mod: Manual" pe LCD. | ||
| + | * Dacă se apasă Triunghi (▲): | ||
| + | - Activează modul automat (evitarea obstacolelor + margini). | ||
| + | * Dacă se apasă X (✖): | ||
| + | - Dezactivează modul automat și revine la control manual. | ||
| + | * Dacă modul automat este activ: | ||
| + | - Apelează `avoidObstacles()` și iese din `loop`. | ||
| + | * Altfel: | ||
| + | - Controlează robotul în mod **manual** cu D-pad: | ||
| + | - ▲ = înainte | ||
| + | - ▼ = înapoi | ||
| + | - ◄ = stânga | ||
| + | - ► = dreapta | ||
| + | - Nimic = oprește | ||
| - | ===== Download ===== | + | <code cpp> |
| + | void loop() | ||
| + | { | ||
| + | Dabble.processInput(); | ||
| - | <note warning> | + | if (!Dabble.isAppConnected()) |
| - | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | { |
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Conecteaza-te "); | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("sefule "); | ||
| + | delay(1000); | ||
| + | return; | ||
| + | } | ||
| - | 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**. | + | static bool wasConnected = false; |
| - | </note> | + | if (!wasConnected) |
| + | { | ||
| + | lcd.clear(); | ||
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Mod: Manual"); | ||
| + | wasConnected = true; | ||
| + | } | ||
| - | ===== Jurnal ===== | + | if (GamePad.isTrianglePressed()) |
| + | { | ||
| + | Serial.println("Mod obstacole+prapastie activat"); | ||
| + | obstacleAvoidanceMode = true; | ||
| - | <note tip> | + | lcd.clear(); |
| - | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | + | lcd.setCursor(0, 0); |
| - | </note> | + | lcd.print("Mod: Obstacole+"); |
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("Prapastii "); | ||
| + | } | ||
| + | |||
| + | if (GamePad.isCrossPressed()) | ||
| + | { | ||
| + | Serial.println("Mod automat oprit, revenire la manual"); | ||
| + | obstacleAvoidanceMode = false; | ||
| + | stopMotors(); | ||
| + | |||
| + | lcd.clear(); | ||
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Mod: Manual"); | ||
| + | } | ||
| + | |||
| + | if (obstacleAvoidanceMode) | ||
| + | { | ||
| + | avoidObstacles(); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if (GamePad.isUpPressed()) moveForward(); | ||
| + | else if (GamePad.isDownPressed()) moveBackward(); | ||
| + | else if (GamePad.isLeftPressed()) turnLeft(); | ||
| + | else if (GamePad.isRightPressed()) turnRight(); | ||
| + | else stopMotors(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | --- | ||
| + | |||
| + | **Auxiliary Functions** | ||
| + | |||
| + | <code cpp> | ||
| + | // Configurează toate pinurile relevante și inițializează servomotorul. | ||
| + | void setUpPinModes() | ||
| + | { | ||
| + | pinMode(IN1, OUTPUT); | ||
| + | pinMode(IN2, OUTPUT); | ||
| + | pinMode(IN3, OUTPUT); | ||
| + | pinMode(IN4, OUTPUT); | ||
| + | pinMode(IR_SENSOR_PIN, INPUT); | ||
| + | |||
| + | myServo.attach(SERVO_PIN); | ||
| + | myServo.write(90); | ||
| + | Serial.println("Servomotor inițiat la 90°"); | ||
| + | } | ||
| + | |||
| + | // Mișcări de bază pentru robot: | ||
| + | void moveForward() | ||
| + | { | ||
| + | GPIO.out_w1ts = (1 << IN1) | (1 << IN3); // Set IN1 și IN3 HIGH | ||
| + | GPIO.out_w1tc = (1 << IN2) | (1 << IN4); // Set IN2 și IN4 LOW | ||
| + | Serial.println("Înainte"); | ||
| + | } | ||
| + | |||
| + | void moveBackward() | ||
| + | { | ||
| + | GPIO.out_w1ts = (1 << IN2) | (1 << IN4); // Set IN2 și IN4 HIGH | ||
| + | GPIO.out_w1tc = (1 << IN1) | (1 << IN3); // Set IN1 și IN3 LOW | ||
| + | Serial.println("Înapoi"); | ||
| + | } | ||
| + | |||
| + | void turnLeft() | ||
| + | { | ||
| + | GPIO.out_w1ts = (1 << IN2) | (1 << IN3); // IN2 și IN3 HIGH | ||
| + | GPIO.out_w1tc = (1 << IN1) | (1 << IN4); // IN1 și IN4 LOW | ||
| + | Serial.println("Stânga"); | ||
| + | } | ||
| + | |||
| + | void turnRight() | ||
| + | { | ||
| + | GPIO.out_w1ts = (1 << IN1) | (1 << IN4); // IN1 și IN4 HIGH | ||
| + | GPIO.out_w1tc = (1 << IN2) | (1 << IN3); // IN2 și IN3 LOW | ||
| + | Serial.println("Dreapta"); | ||
| + | } | ||
| + | |||
| + | void stopMotors() | ||
| + | { | ||
| + | GPIO.out_w1tc = (1 << IN1) | (1 << IN2) | (1 << IN3) | (1 << IN4); // Toți LOW | ||
| + | Serial.println("Oprire"); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | --- | ||
| + | |||
| + | **Sensor and Navigation Functions** | ||
| + | |||
| + | <code cpp> | ||
| + | // Returnează distanța măsurată cu ultrasunete. | ||
| + | int readPing() | ||
| + | { | ||
| + | delay(70); | ||
| + | int cm = sonar.ping_cm(); | ||
| + | if (cm == 0) cm = MAX_DISTANCE; | ||
| + | |||
| + | Serial.print("Distanță: "); | ||
| + | Serial.print(cm); | ||
| + | Serial.println(" cm"); | ||
| + | return cm; | ||
| + | } | ||
| + | |||
| + | // Rotește servomotorul spre dreapta, măsoară, revine. | ||
| + | int lookRight() | ||
| + | { | ||
| + | myServo.write(50); | ||
| + | delay(500); | ||
| + | int distance = readPing(); | ||
| + | myServo.write(90); | ||
| + | return distance; | ||
| + | } | ||
| + | |||
| + | // Rotește servomotorul spre stânga, măsoară, revine. | ||
| + | int lookLeft() | ||
| + | { | ||
| + | myServo.write(130); | ||
| + | delay(500); | ||
| + | int distance = readPing(); | ||
| + | myServo.write(90); | ||
| + | return distance; | ||
| + | } | ||
| + | |||
| + | // Evită obstacole și margini. Apelată în mod automat. | ||
| + | void avoidObstacles() | ||
| + | { | ||
| + | int senzorIR = digitalRead(IR_SENSOR_PIN); // LOW = prăpastie | ||
| + | int distanceR = 0; | ||
| + | int distanceL = 0; | ||
| + | distance = readPing(); | ||
| + | |||
| + | if (senzorIR == LOW) | ||
| + | { | ||
| + | stopMotors(); | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("Prapastie STOP "); | ||
| + | delay(200); | ||
| + | |||
| + | moveBackward(); | ||
| + | delay(400); | ||
| + | stopMotors(); | ||
| + | delay(200); | ||
| + | |||
| + | turnLeft(); // întoarcere completă | ||
| + | delay(700); | ||
| + | stopMotors(); | ||
| + | delay(200); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if (distance <= OBSTACLE_DISTANCE) | ||
| + | { | ||
| + | stopMotors(); | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("Obstacol STOP "); | ||
| + | delay(100); | ||
| + | moveBackward(); | ||
| + | delay(300); | ||
| + | stopMotors(); | ||
| + | delay(200); | ||
| + | |||
| + | distanceR = lookRight(); | ||
| + | delay(200); | ||
| + | distanceL = lookLeft(); | ||
| + | delay(200); | ||
| + | |||
| + | if (distanceR >= distanceL) | ||
| + | { | ||
| + | turnRight(); | ||
| + | delay(500); | ||
| + | stopMotors(); | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | turnLeft(); | ||
| + | delay(500); | ||
| + | stopMotors(); | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | moveForward(); | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print("Drum liber "); | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | |||
| + | {{:pm:prj2025:fstancu:img_2148.jpg?300|}} | ||
| + | {{:pm:prj2025:fstancu:img_2149.jpg?260|}} | ||
| + | } | ||
| + | ===== VIDEO ===== | ||
| + | https://www.youtube.com/shorts/16-T-_LEwkY | ||
| + | |||
| + | ===== Rezultate Obţinute ===== | ||
| + | {{:pm:prj2025:fstancu:img_dan1.jpg?307|}} | ||
| + | {{:pm:prj2025:fstancu:img_dan2.jpg?300|}} | ||
| + | |||
| + | |||
| + | ===== Concluzii ===== | ||
| + | Acest proiect este un robot autonom controlabil prin Bluetooth, capabil să evite obstacole și prăpastii cu ajutorul senzorilor, oferind în același timp control manual precis prin aplicația Dabble. Este o combinație reușită între inteligență integrată, interfață prietenoasă și control adaptiv al motoarelor. | ||
| + | ===== Download ===== | ||
| + | {{:pm:prj2025:fstancu:bluetoothcar_v1.1_vrinceanu.zip|}} | ||
| ===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
| - | <note> | + | LCD Help: |
| - | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | https://www.youtube.com/watch?v=860eErq9c3E> |
| - | </note> | + | |
| - | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | + | Piese: |
| + | https://sigmanortec.ro | ||
| + | https://www.optimusdigital.ro/ro/ | ||