This shows you the differences between two versions of the page.
|
pm:prj2025:fstancu:veaceslav.safronii [2025/05/19 02:23] veaceslav.safronii [Hardware Design] |
pm:prj2025:fstancu:veaceslav.safronii [2025/05/30 00:05] (current) veaceslav.safronii [Rezultate Obţinute] |
||
|---|---|---|---|
| Line 40: | Line 40: | ||
| | Butoane tactile | Pentru input manual | | | Butoane tactile | Pentru input manual | | ||
| | Placa de prototipare cablaj | PCB | | | Placa de prototipare cablaj | PCB | | ||
| + | |||
| + | |||
| + | |||
| + | {{:pm:prj2025:fstancu:proiect_poza_glove.jpg?400|}} | ||
| ===== Software Design ===== | ===== Software Design ===== | ||
| - | <note tip> | ||
| - | Descrierea codului aplicaţiei (firmware): | ||
| - | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | ||
| - | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | ||
| - | * algoritmi şi structuri pe care plănuiţi să le implementaţi | ||
| - | * (etapa 3) surse şi funcţii implementate | ||
| - | </note> | ||
| - | ===== Rezultate Obţinute ===== | + | **Mediu de dezvoltare** |
| - | <note tip> | + | - **PlatformIO** - Mediu integrat de dezvoltare (IDE) bazat pe Visual Studio Code, specializat pentru dezvoltarea sistemelor embedded |
| - | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | - **Framework-ul Arduino** pentru ESP32, care oferă un strat de abstractizare peste SDK-ul nativ ESP-IDF |
| - | </note> | + | |
| - | ===== Concluzii ===== | + | **Librării și surse third-party** |
| - | ===== Download ===== | + | - **Biblioteca BLE Arduino** - Implementarea oficială a stivei Bluetooth Low Energy pentru ESP32 |
| + | - **Biblioteca MPU6050** - Adaptată și optimizată pentru comunicarea directă I2C cu senzorul de mișcare | ||
| + | - **Bleak** - Bibliotecă Python cross-platform pentru comunicarea Bluetooth Low Energy folosită în aplicația receptor | ||
| - | <note warning> | ||
| - | 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ă ;-). | ||
| - | 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**. | + | **Algoritmi și structuri implementate** |
| - | </note> | + | |
| - | ===== Jurnal ===== | + | **1. Structura modulară a firmware-ului** |
| - | <note tip> | + | Codul firmware-ului a fost organizat în module funcționale pentru o mai bună întreținere și scalabilitate: |
| - | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | + | |
| - | </note> | + | * **__main.cpp__** - Punct de intrare, inițializare și bucla principală |
| + | * **__config.h__** - Constante, definiri și configurație globală | ||
| + | * **__ble_manager__** - Gestionarea comunicației Bluetooth Low Energy | ||
| + | * **__i2c_interface__** - Implementarea protocolului I2C pentru comunicare cu senzori | ||
| + | * **__mpu6050__** - Comunicare și procesare date de la senzorul inerțial MPU6050 | ||
| + | * **__controller__** - Logica de control și mapare a gesturilor la acțiuni | ||
| + | |||
| + | **Inițializarea și configurarea ESP32** | ||
| + | <code> | ||
| + | void setup() { | ||
| + | Serial.begin(SERIAL_BAUD_RATE); | ||
| + | Serial.println("Wireless Glove Controller initializing..."); | ||
| + | |||
| + | // Setup I2C pins | ||
| + | pinMode(SDA_PIN, INPUT_PULLUP); | ||
| + | pinMode(SCL_PIN, INPUT_PULLUP); | ||
| + | |||
| + | // Configure button with interrupt | ||
| + | pinMode(MODE_BUTTON_PIN, INPUT_PULLUP); | ||
| + | attachInterrupt(digitalPinToInterrupt(MODE_BUTTON_PIN), buttonISR, FALLING); | ||
| + | |||
| + | // Initialize systems | ||
| + | i2c_init(); | ||
| + | mpu6050_init(); | ||
| + | initBLE(); | ||
| + | calibrate_sensors(); | ||
| + | |||
| + | // Configure timer for sensor sampling | ||
| + | sampleTimer = timerBegin(0, 80, true); | ||
| + | timerAttachInterrupt(sampleTimer, &onSampleTimer, true); | ||
| + | timerAlarmWrite(sampleTimer, SAMPLE_RATE_MS * 1000, true); | ||
| + | timerAlarmEnable(sampleTimer); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Handler de întrerupere pentru eșantionare** | ||
| + | <code> | ||
| + | void IRAM_ATTR onSampleTimer() { | ||
| + | portENTER_CRITICAL_ISR(&timerMux); | ||
| + | readSensorFlag = true; | ||
| + | portEXIT_CRITICAL_ISR(&timerMux); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Bucla principală** | ||
| + | |||
| + | <code> | ||
| + | void loop() { | ||
| + | // Process sensor data when ready | ||
| + | if (readSensorFlag) { | ||
| + | readSensorFlag = false; | ||
| + | |||
| + | if (deviceConnected) { | ||
| + | process_motion_data(); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Handle button press | ||
| + | if (buttonInterruptOccurred) { | ||
| + | buttonInterruptOccurred = false; | ||
| + | handle_button_interrupt(); | ||
| + | } | ||
| + | |||
| + | // Manage BLE reconnections | ||
| + | handleBLEEvents(); | ||
| + | |||
| + | delay(1); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Citirea datelor de la MPU6050** | ||
| + | <code> | ||
| + | void mpu6050_read_accel(int16_t *accelX, int16_t *accelY, int16_t *accelZ) { | ||
| + | uint8_t buffer[6]; | ||
| + | |||
| + | read_registers(MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, buffer, 6); | ||
| + | |||
| + | *accelX = (int16_t)((buffer[0] << 8) | buffer[1]); | ||
| + | *accelY = (int16_t)((buffer[2] << 8) | buffer[3]); | ||
| + | *accelZ = (int16_t)((buffer[4] << 8) | buffer[5]); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Procesare mișcare mouse** | ||
| + | <code> | ||
| + | if (currentMode == MOUSE_MODE) { | ||
| + | // Apply dead zone filter | ||
| + | if (abs(deltaGyroX) < GYRO_DEADZONE) deltaGyroX = 0; | ||
| + | if (abs(deltaGyroY) < GYRO_DEADZONE) deltaGyroY = 0; | ||
| + | |||
| + | // Non-linear scaling for better precision | ||
| + | float scaledX = (float)deltaGyroY / GYRO_SCALE_MAX; | ||
| + | float scaledY = (float)deltaGyroX / GYRO_SCALE_MAX; | ||
| + | |||
| + | int16_t mouseX = -scaledX * mouseAcceleration * MOUSE_SPEED_MAX; | ||
| + | int16_t mouseY = scaledY * mouseAcceleration * MOUSE_SPEED_MAX; | ||
| + | |||
| + | send_mouse_command(mouseX, mouseY); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Trimitere comandă BLE** | ||
| + | <code> | ||
| + | void send_mouse_command(int16_t x, int16_t y) { | ||
| + | if (!deviceConnected) return; | ||
| + | |||
| + | // Limită pentru valorile ±127 | ||
| + | x = constrain(x, -127, 127); | ||
| + | y = constrain(y, -127, 127); | ||
| + | |||
| + | // Construcție pachet | ||
| + | uint8_t buffer[4]; | ||
| + | buffer[0] = MOUSE_MOVE; | ||
| + | buffer[1] = (uint8_t)(x & 0xFF); | ||
| + | buffer[2] = (uint8_t)(y & 0xFF); | ||
| + | buffer[3] = 0; // Scroll | ||
| + | |||
| + | // Transmisie BLE | ||
| + | pTxCharacteristic->setValue(buffer, 4); | ||
| + | pTxCharacteristic->notify(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Calibrare senzori** | ||
| + | <code> | ||
| + | const int numSamples = 50; | ||
| + | for (int i = 0; i < numSamples; i++) { | ||
| + | mpu6050_read_accel(&accelX, &accelY, &accelZ); | ||
| + | mpu6050_read_gyro(&gyroX, &gyroY, &gyroZ); | ||
| + | |||
| + | sumAccelX += accelX; | ||
| + | sumAccelY += accelY; | ||
| + | sumAccelZ += accelZ; | ||
| + | |||
| + | delay(10); | ||
| + | } | ||
| + | |||
| + | // Calculare valori de bază | ||
| + | baseAccelX = sumAccelX / numSamples; | ||
| + | baseAccelY = sumAccelY / numSamples; | ||
| + | baseAccelZ = sumAccelZ / numSamples; | ||
| + | </code> | ||
| + | |||
| + | **2. Aplicație Python (Receptor)** | ||
| + | |||
| + | - Comunicare Bluetooth: | ||
| + | * **__notification_handler()__** - Procesarea notificărilor BLE primite | ||
| + | * **___connect()__** - Stabilirea conexiunii cu dispozitivul controller | ||
| + | - Procesare comenzi: | ||
| + | * **__process_mouse_move()__** - Interpretarea și aplicarea mișcărilor mouse-ului | ||
| + | * **__process_key_press()__** / **__process_key_release()__** - Gestionarea apăsărilor de taste | ||
| + | - Interfață utilizator | ||
| + | * **__create_gui()__** - Construirea interfeței grafice | ||
| + | * **__log()__** - Sistemul de înregistrare a evenimentelor pentru debugging | ||
| + | |||
| + | Handler notificări BLE (Python) | ||
| + | <code> | ||
| + | def notification_handler(self, sender, data): | ||
| + | # Adaugă datele la buffer | ||
| + | self.receive_buffer.extend(data) | ||
| + | |||
| + | # Extrage comanda | ||
| + | cmd = self.receive_buffer[0] | ||
| + | |||
| + | if cmd == MOUSE_MOVE and len(self.receive_buffer) >= 4: | ||
| + | x = struct.unpack('b', bytes([self.receive_buffer[1]]))[0] | ||
| + | y = struct.unpack('b', bytes([self.receive_buffer[2]]))[0] | ||
| + | self.process_mouse_move(x, y) | ||
| + | self.receive_buffer = self.receive_buffer[4:] | ||
| + | </code> | ||
| + | ===== Rezultate Obţinute ===== | ||
| + | |||
| + | {{:pm:prj2025:fstancu:produs_final2_safronii_veaceslav.jpg?200|}} {{:pm:prj2025:fstancu:produs_final1_safronii_veaceslav.jpg?250|}} | ||
| + | |||
| + | |||
| + | **Demo:** | ||
| + | |||
| + | <html> | ||
| + | <iframe width="560" height="315" | ||
| + | src="https://www.youtube.com/embed/A-uMmCEJwlk" | ||
| + | title="YouTube video player" | ||
| + | frameborder="0" | ||
| + | allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" | ||
| + | allowfullscreen> | ||
| + | </iframe> | ||
| + | </html> | ||
| + | |||
| + | ===== Download ===== | ||
| - | ===== Bibliografie/Resurse ===== | + | Codul sursa: |
| + | * src/ - Codul pentru ESP | ||
| + | * receptor/ - Programul in Python de receptie a comenzilor | ||
| - | <note> | + | {{:pm:prj2025:fstancu:wirelesscontroller.zip|}} |
| - | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | |
| - | </note> | + | |
| - | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||