Differences

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

Link to this comparison view

pm:prj2025:vstoica:aila.zeitouni [2025/05/25 23:17]
aila.zeitouni [Software Design]
pm:prj2025:vstoica:aila.zeitouni [2025/05/26 16:59] (current)
aila.zeitouni [Milestone 3 - Raport asupra implementării software]
Line 110: Line 110:
  
 <note tip> <note tip>
-#include <Arduino.h> +#include <avr/io.h> 
-#include <Servo.h> +#include <util/delay.h> 
-#include <Wire.h> +#include <stdint.h> 
-#include <LiquidCrystal_PCF8574.h> ​ // Installed manually in lib/+#include <stdbool.h> 
 +#include "​lcd_i2c.h"​ 
 +#include "​twi.h"​ 
 +// Pin defines matching your Arduino sketch 
 +#define TRIG_PIN PD6  // ​D6 
 +#define ECHO_PIN PD7  // D7 
 +#define SERVO_PIN PB1 // D9 (OC1A) 
 +#define BUZZER_PIN PB0 /D8
  
-// Pin Definitions +#define DISTANCE_OPEN_THRESHOLD 15 
-const int TRIG_PIN = 6; +#define DISTANCE_TRASH_THRESHOLD 8 
-const int ECHO_PIN = 7; +#define TRASH_DETECT_DELAY_MS 3000
-const int SERVO_PIN = 9; +
-const int BUZZER_PIN = 8;+
  
-// Constants +#​define ​SERVO_OPEN_ANGLE 0 
-const int DISTANCE_OPEN_THRESHOLD = 15;  // in cm +#​define ​SERVO_CLOSE_ANGLE ​180
-const int DISTANCE_TRASH_THRESHOLD = 8;  // for thanking +
-const int SERVO_OPEN_ANGLE ​0; +
-const int SERVO_CLOSE_ANGLE ​= 90; +
-const int TRASH_DETECT_DELAY = 3000;     // 3 seconds before next "thank you"+
  
-// Components +void setup_servo_pwm() { 
-Servo lidServo; +    DDRB |= (1 << SERVO_PIN); // PB1 as output 
-LiquidCrystal_PCF8574 lcd(0x27); +    ​TCCR1A |= (1 << COM1A1) | (1 << WGM11); 
-float distance_cm;​ +    ​TCCR1B |= (1 << WGM12(1 << WGM13(1 << CS11); // prescaler 8 
-unsigned long lastTrashDetectTime ​0; +    ICR1 = 19999// 20 ms PWM 
-float measureDistance(); +}
-void buzz(int times); +
-void setup() +
-  Serial.begin(9600)+
-  tone(8, 1000);  +
-  ​// Sensor setup +
-  ​pinMode(TRIG_PIN,​ OUTPUT)+
-  ​pinMode(ECHO_PIN,​ INPUT);+
  
-  // Buzzer +void set_servo_angle(uint8_t angle{ 
-  pinMode(BUZZER_PIN, OUTPUT); +    OCR1A = (ICR1 * (1000 + ((uint32_t)angle * 1000 / 180))) / 20000; 
-  ​digitalWrite(BUZZER_PIN, LOW);+}
  
-  ​// Servo setup +uint16_t measure_distance_cm() { 
-  ​lidServo.attach(SERVO_PIN); +    ​// Send trigger pulse 
-  ​lidServo.write(SERVO_CLOSE_ANGLE);+    PORTD &= ~(1 << TRIG_PIN);​ 
 +    _delay_us(2);​ 
 +    PORTD |= (1 << TRIG_PIN); 
 +    ​_delay_us(10); 
 +    PORTD &= ~(1 << TRIG_PIN);
  
-  ​// LCD setup +    ​// Wait for echo to go high 
-  ​lcd.begin(16,​ 2)+    ​uint16_t timeout = 30000
-  ​lcd.setBacklight(255); +    ​while ​(!(PIND & (1 << ECHO_PIN)) && timeout--) _delay_us(1); 
-  ​lcd.setCursor(0, 0); +    ​if ​(timeout == 0) return 0
-  ​lcd.print("​ Smart Stash Can ")+ 
-  ​lcd.setCursor(0, 1); +    // Measure how long echo is high 
-  ​lcd.print(" ​  ​Initializing ​  "​); +    uint32_t count = 0
-  ​delay(2000)+    while ((PIND & (1 << ECHO_PIN)) && count < 30000) { 
-  ​lcd.clear();+        ​_delay_us(1); 
 +        ​count++
 +    } 
 + 
 +    // Convert to cm 
 +    return ​(uint16_t)((count * 0.0343) / 2);
 } }
  
-void loop() { +void buzz(uint8_t times) { 
-  ​distance_cm ​measureDistance();+    for (uint8_t i = 0; i < times; i++) { 
 +        PORTB |= (1 << BUZZER_PIN); 
 +        _delay_ms(300);​ 
 +        PORTB &= ~(1 << BUZZER_PIN);​ 
 +        _delay_ms(200);​ 
 +    } 
 +
 +#include "​lcd_i2c.h"​ 
 +#include "​twi.h"​
  
-  Serial.print("​Distance:​ "); +int main(void
-  ​Serial.print(distance_cm); +    // Setup TRIG as output, ECHO as input 
-  ​Serial.println(" cm");+    DDRD |= (1 << TRIG_PIN); 
 +    DDRD &= ~(1 << ECHO_PIN);
  
-  if (distance_cm > 0 && distance_cm < DISTANCE_OPEN_THRESHOLD) { +    ​// Setup buzzer 
-    ​// Open lid +    ​DDRB |= (1 << BUZZER_PIN); 
-    ​lcd.setCursor(0, 0); +    ​PORTB &= ~(1 << BUZZER_PIN);
-    ​lcd.print("​Opening lid     "​);​ +
-    lidServo.write(SERVO_OPEN_ANGLE);+
  
-    // 🔊 Buzzer beep on open +    // Init I2C and LCD 
-    ​buzz(1); +    ​twi_init(); 
-  } else { +    ​lcd_init();
-    ​// Close lid +
-    lcd.setCursor(0, 0); +
-    //​lcd.print("​Waiting... ​     "); +
-    lidServo.write(SERVO_CLOSE_ANGLE);​ +
-  }+
  
-  // Trash detection and second thank-you buzzer +    lcd_clear(); 
-  if (distance_cm > 0 && distance_cm < DISTANCE_TRASH_THRESHOLD{ +    ​lcd_set_cursor(0, 0); 
-    ​if (millis() - lastTrashDetectTime > TRASH_DETECT_DELAY) { +    ​lcd_print("Smart Stash Can"); 
-      lcd.setCursor(0, 1); +    ​lcd_set_cursor(0, 1); 
-      ​lcd.print(" ​ Thank you!     "); +    ​lcd_print(" ​  ​Initializing "); 
-      buzz(2);  // 2 short beeps +    ​_delay_ms(2000); 
-      ​lastTrashDetectTime = millis(); +    ​lcd_clear();
-    ​+
-  } else { +
-    lcd.setCursor(0, 1); +
-    ​lcd.print("​Scanning area   "​); +
-  }+
  
-  delay(300); +    // Init servo 
-+    setup_servo_pwm(); 
- +    ​set_servo_angle(SERVO_CLOSE_ANGLE);​
  
-float measureDistance() { +    uint32_t last_thank_time ​= 0;
-  digitalWrite(TRIG_PIN,​ LOW); +
-  delayMicroseconds(2);​ +
-  digitalWrite(TRIG_PIN,​ HIGH); +
-  delayMicroseconds(10);​ +
-  digitalWrite(TRIG_PIN,​ LOW); +
-  float duration ​pulseIn(ECHO_PIN,​ HIGH); +
-  return ​0.017 * duration; +
-}+
  
-void buzz(int times) { +    while (1) { 
-  ​for ​(int i = 0; i < timesi++) { +        uint16_t distance = measure_distance_cm();​ 
-    ​digitalWrite(BUZZER_PINHIGH); + 
-    ​delay(300);  // increase duration +        if (distance > 0 && distance < DISTANCE_OPEN_THRESHOLD) { 
-    ​digitalWrite(BUZZER_PINLOW); +            set_servo_angle(SERVO_OPEN_ANGLE);​ 
-    delay(200); +            lcd_set_cursor(0,​ 0); 
-  }+            lcd_print("​Opening lid     "​);​ 
 +            ​buzz(1)
 +        } else 
 +            ​set_servo_angle(SERVO_CLOSE_ANGLE);​ 
 +            lcd_set_cursor(0, 0); 
 +            lcd_print("​Lid closed ​     "); 
 +        } 
 + 
 +        if (distance > 0 && distance < DISTANCE_TRASH_THRESHOLD) { 
 +            if ((last_thank_time ​TRASH_DETECT_DELAY_MS) < 60000) { 
 +                ​lcd_set_cursor(01); 
 +                ​lcd_print(" ​ Thank you!    "); 
 +                buzz(2); 
 +                ​last_thank_time = 0; 
 +            } 
 +        } else { 
 +            lcd_set_cursor(01); 
 +            ​lcd_print("​Scanning area   "​); 
 +            ​last_thank_time += 300; 
 +        } 
 + 
 +        _delay_ms(300);​ 
 +    ​}
 } }
 +
    
  
 </​note>​ </​note>​
 +
 +
 +
 +====== Milestone 3 - Raport asupra implementării software ======
 +
 +=== Stadiul actual al implementării ===
 +
 +Software-ul pentru proiectul Smart Stash Can este funcțional și a fost testat cu succes pe hardware-ul final. Funcționalitățile implementate includ:
 +
 +  * Detectarea distanței utilizând senzorul ultrasonic HC-SR04 (TRIG pe PD6, ECHO pe PD7)
 +  * Controlul capacului prin servomotor acționat PWM (OC1A - PB1)
 +  * Feedback sonor cu ajutorul unui buzzer (PB0)
 +  * Afișaj LCD I2C (cu PCF8574, adresă 0x27) pentru interfața cu utilizatorul
 +  * Cod modular scris în C bare-metal cu acces direct la registrele perifericelor
 +  * Demonstrație completă validată experimental în laborator
 +
 +---
 +
 +=== Biblioteci și drivere utilizate ===
 +
 +^ Componentă ^ Bibliotecă / Driver ^ Justificare ^
 +| Afișaj LCD | lcd_i2c.c / lcd_i2c.h (scris de noi) | Implementare ușoară și eficientă pentru PCF8574, fără dependențe de Arduino |
 +| Magistrală I2C | twi.c / twi.h (din laborator) | Permite control complet asupra comunicației TWI |
 +| UART (debug) | usart.c / usart.h | Folosit pentru mesaje de test și jurnalizare serială |
 +| Control servomotor | PWM cu Timer1 | Precizie ridicată folosind OCR1A și ICR1 fără delay-uri software |
 +
 +Fiecare bibliotecă a fost selectată pentru simplitate, eficiență și integrare directă cu perifericele platformei ATmega328P.
 +
 +---
 +
 +=== Element de noutate al proiectului ===
 +
 +Acest proiect se diferențiază prin abordarea complet bare-metal, fără utilizarea bibliotecilor Arduino. Interacțiunea între senzor, servomotor, buzzer și afișaj este realizată exclusiv prin programare directă a registrelor. Se obține astfel un control total asupra funcționalității,​ temporizării și performanței sistemului, într-un format educativ și extensibil.
 +
 +---
 +
 +=== Justificarea utilizării funcționalităților din laborator ===
 +
 +^ Laborator ^ Funcționalitate utilizată ^ Aplicare în proiect ^
 +| Lab 0 | GPIO | TRIG și ECHO pentru senzor, ieșire pentru buzzer |
 +| Lab 1 | UART | Trimiterea mesajelor debug către terminal serial |
 +| Lab 3 | Timere și PWM | Control precis al servomotorului cu Timer1, canal OC1A |
 +| Lab 6 | I2C (TWI) | Comunicație cu afișajul LCD prin interfața I2C (PCF8574) |
 +
 +Fiecare funcționalitate din laborator a fost integrată într-un mod practic pentru a forma un sistem embedded complet funcțional.
 +
 +---
 +
 +=== Structura proiectului și validare ===
 +
 +**Fișiere principale:​**
 +
 +  * `main.c` – logica principală,​ secvența de control
 +  * `servo.c/h` – control PWM pentru servomotor
 +  * `twi.c/h` – comunicație I2C (TWI)
 +  * `lcd_i2c.c/​h` – afișare pe LCD prin PCF8574
 +  * `usart.c/h` – trimiterea mesajelor seriale
 +
 +**Validare:​**
 +  * Testare modulară: fiecare componentă a fost verificată individual
 +  * Testare integrată: comportamentul întregului sistem a fost observat în timp real
 +  * Compararea distanțelor măsurate cu o riglă fizică
 +  * Verificarea reacției servo în funcție de distanță
 +  * Confirmarea clarității mesajelor LCD și a actualizării cursorului
 +
 +---
 +
 +=== Calibrarea senzorului de distanță ===
 +
 +Senzorul ultrasonic HC-SR04 a fost calibrat folosind măsurători directe:
 +
 +  * Formula de conversie: `(durata în µs × 0.0343) / 2`
 +  * Pulsurile TRIG și ECHO au fost gestionate cu `_delay_us()` pentru precizie
 +  * Praguri stabilite experimental:​
 +    * Deschiderea capacului la < 15 cm
 +    * Mesaj de mulțumire la < 8 cm
 +  * Zgomotul de măsurare a fost redus prin cicluri scurte și perioade de eșantionare stabile (300 ms)
 +
 +---
 +
 +=== Optimizări realizate ===
 +
 +  * PWM hardware în loc de temporizări software pentru controlul servomotorului
 +  * I2C implementat low-level fără librării externe, pentru control precis
 +  * Suprimarea “ghosting”-ului pe LCD prin scriere completă a liniilor cu spații
 +  * Utilizarea exclusivă a variabilelor statice, fără alocare dinamică
 +  * Funcția de măsurare a distanței optimizată pentru precizie și timeout sigur
 +  * Structura buclei principale minimizează întârzierile și optimizează reacția sistemului
 +
 +---
 +
 +=== Video demonstrativ ===
 +
 +O demonstrație video a întregului proiect, cu explicații și comportament funcțional,​ poate fi vizualizată la:
 +
 +
 +
 +---
  
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
pm/prj2025/vstoica/aila.zeitouni.1748204278.txt.gz · Last modified: 2025/05/25 23:17 by aila.zeitouni
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