This shows you the differences between two versions of the page.
pm:prj2025:vstoica:aila.zeitouni [2025/05/18 23:22] aila.zeitouni [Hardware 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> | ||
- | Descrierea codului aplicaţiei (firmware): | + | #include <avr/io.h> |
- | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | + | #include <util/delay.h> |
- | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | + | #include <stdint.h> |
- | * algoritmi şi structuri pe care plănuiţi să le implementaţi | + | #include <stdbool.h> |
- | * (etapa 3) surse şi funcţii implementate | + | #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 | ||
+ | |||
+ | #define DISTANCE_OPEN_THRESHOLD 15 | ||
+ | #define DISTANCE_TRASH_THRESHOLD 8 | ||
+ | #define TRASH_DETECT_DELAY_MS 3000 | ||
+ | |||
+ | #define SERVO_OPEN_ANGLE 0 | ||
+ | #define SERVO_CLOSE_ANGLE 180 | ||
+ | |||
+ | void setup_servo_pwm() { | ||
+ | DDRB |= (1 << SERVO_PIN); // PB1 as output | ||
+ | TCCR1A |= (1 << COM1A1) | (1 << WGM11); | ||
+ | TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS11); // prescaler 8 | ||
+ | ICR1 = 19999; // 20 ms PWM | ||
+ | } | ||
+ | |||
+ | void set_servo_angle(uint8_t angle) { | ||
+ | OCR1A = (ICR1 * (1000 + ((uint32_t)angle * 1000 / 180))) / 20000; | ||
+ | } | ||
+ | |||
+ | uint16_t measure_distance_cm() { | ||
+ | // Send trigger pulse | ||
+ | PORTD &= ~(1 << TRIG_PIN); | ||
+ | _delay_us(2); | ||
+ | PORTD |= (1 << TRIG_PIN); | ||
+ | _delay_us(10); | ||
+ | PORTD &= ~(1 << TRIG_PIN); | ||
+ | |||
+ | // Wait for echo to go high | ||
+ | uint16_t timeout = 30000; | ||
+ | while (!(PIND & (1 << ECHO_PIN)) && timeout--) _delay_us(1); | ||
+ | if (timeout == 0) return 0; | ||
+ | |||
+ | // Measure how long echo is high | ||
+ | uint32_t count = 0; | ||
+ | while ((PIND & (1 << ECHO_PIN)) && count < 30000) { | ||
+ | _delay_us(1); | ||
+ | count++; | ||
+ | } | ||
+ | |||
+ | // Convert to cm | ||
+ | return (uint16_t)((count * 0.0343) / 2); | ||
+ | } | ||
+ | |||
+ | void buzz(uint8_t times) { | ||
+ | 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" | ||
+ | |||
+ | int main(void) { | ||
+ | // Setup TRIG as output, ECHO as input | ||
+ | DDRD |= (1 << TRIG_PIN); | ||
+ | DDRD &= ~(1 << ECHO_PIN); | ||
+ | |||
+ | // Setup buzzer | ||
+ | DDRB |= (1 << BUZZER_PIN); | ||
+ | PORTB &= ~(1 << BUZZER_PIN); | ||
+ | |||
+ | // Init I2C and LCD | ||
+ | twi_init(); | ||
+ | lcd_init(); | ||
+ | |||
+ | lcd_clear(); | ||
+ | lcd_set_cursor(0, 0); | ||
+ | lcd_print("Smart Stash Can"); | ||
+ | lcd_set_cursor(0, 1); | ||
+ | lcd_print(" Initializing "); | ||
+ | _delay_ms(2000); | ||
+ | lcd_clear(); | ||
+ | |||
+ | // Init servo | ||
+ | setup_servo_pwm(); | ||
+ | set_servo_angle(SERVO_CLOSE_ANGLE); | ||
+ | |||
+ | uint32_t last_thank_time = 0; | ||
+ | |||
+ | while (1) { | ||
+ | uint16_t distance = measure_distance_cm(); | ||
+ | |||
+ | if (distance > 0 && distance < DISTANCE_OPEN_THRESHOLD) { | ||
+ | set_servo_angle(SERVO_OPEN_ANGLE); | ||
+ | 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(0, 1); | ||
+ | lcd_print(" Thank you! "); | ||
+ | buzz(2); | ||
+ | last_thank_time = 0; | ||
+ | } | ||
+ | } else { | ||
+ | lcd_set_cursor(0, 1); | ||
+ | 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 ===== |