Autor: Socea Mihai Grupa 332CD

Introducere

Am realizat un sistem de deschidere / inchidere automata a unei usi prin calcularea distantei dintre obiect si senzor.

Daca distanta se modifica drastic ( persoana se apropie de usa, prin intermediul unui servomotor usa se va deschide.

Scopul proiectului este sa creez un design simplu si eficient pentru un lucru folosit de milioane de oameni.

Descriere generală

Flux operațional:

Proiectul realizează un mecanism de deschidere şi închidere automată a unei uşi folosind un senzor ultrasonic şi un servomotor SG90 controlate de un Arduino Nano. Uşa rămâne blocată (închisă) în mod normal; la detectarea unei variaţii bruște de distanţă faţă de senzor mai mare de 100 cm, sistemul o deblochează (deschide) automat. După 5 secunde fără nicio nouă variaţie majoră de distanţă, uşa se retrage în poziţia de “închis” automat pentru siguranţă.

Hardware Design

Componente folosite

</note>

Nr. crt. Componentă Tip de semnal / protocol Pini Arduino folosiți
1 Arduino Nano ATmega328P GPIO, PWM, I²C
2 Senzor ultrasonic HC-SR04 GPIO (Digital Input/Output) D8 (TRIG), D9 (ECHO)
3 Servomotor SG90 PWM D10
4 LED alb (închis) GPIO – ieșire digitală D3
5 LED alb (deschis) GPIO – ieșire digitală D4
6 Buzzer activ 5 V GPIO – ieșire digitală D6
7 Buton tactil (push-button 6×6×6) GPIO (INPUT_PULLUP) D7
8 Modul RTC DS3231 cu baterie tampon I²C A4 (SDA), A5 (SCL)
9 EEPROM AT24C256 I²C A4 (SDA), A5 (SCL)
10 Rezistor 220 Ω Limitare curent LED În serie cu LED-urile pe D3 & D4
11 Breadboard HQ + fire jumper

1000034412.jpg

Software Design

Componentă / Aspect Detalii
IDE Arduino IDE
Microcontroler Arduino Nano (ATmega328P + CH340)
Compilator AVR-GCC (prin Arduino Toolchain)
Limbaj C/C++ cu acces direct la registre
Biblioteci Fără librării externe (I2C, PWM, GPIO, Timere implementate manual)

Elemente software implementate

Funcționalitate
Control tastatură matricială 4×4 (scanare + debouncing)
Verificare PIN + contor de greșeli
Blocare automată după 10s de la deblocare (millis())
Servomotor SG90 acționat manual (fără Servo.h)
LED-uri pentru semnalizare (GPIO)
Buzzer pasiv cu secvențe sonore (tone() manual)
Afișare mesaje pe LCD 1602 (I2C low-level TWI)

Laboratoare folosite

Laborator Concept Aplicație în proiect
Lab 0 GPIO Configurarea pinilor TRIG (OUTPUT) și ECHO (INPUT) pentru senzorul ultrasonic, precum și controlul LED-urilor de stare (LED_OPEN_PIN, LED_CLOSED_PIN) și al butonului de reset.
Lab 2 Întreruperi Măsurarea precisă a duratei semnalului ECHO folosind Input Capture pe Timer1 (INT0/Input Capture) în loc de funcția blocking pulseIn(), pentru calcularea distanței.
Lab 3 Timere & PWM Generarea semnalului PWM pentru controlul servomotorului SG90 (Timer1 Fast PWM, 600 µs = 0°, 1500 µs = 90°) și crearea tonurilor pentru buzzer (Timer0 CTC pentru 262 Hz/175 Hz).
Lab 6 I2C (fără librării) Comunicare low-level cu modulul RTC DS3231 și cu EEPROM-ul extern AT24C256 prin TWI, pentru salvarea timestamp-urilor și a istoricului stării ușii (open/closed).

Implementarea logicii

initUltrasonic()

Configurează Timer1 în modul Input Capture și interrupt INT0 pentru măsurarea duratei semnalului ECHO. PIN-ul TRIG este setat ca OUTPUT, iar ECHO ca INPUT. La fiecare front de atac pe ECHO (ICES1 = 1), se capturează valoarea în ICR1; la frontul de coborâre (ICES1 = 0), se reia capturarea și se calculează distanța în centimetri folosind formula dist_cm = (ICR1_value * 0.666) / 58.

readDistance()

Trimite un impuls de 10 μs pe TRIG_PIN (bitul corespunzător este setat HIGH timp de delayMicroseconds(10), apoi LOW) și așteaptă completarea Input Capture (flag ICIF1). După ce ICR1 este citit, normalizează valoarea ținând cont de prescaler (8) și convertește în cm. Returnează distanța măsurată sau -1 dacă nu s-a recepționat semnal în timeout.

setDoorPosition(uint16_t pulse_us)

Configurează Timer1 în Fast PWM (WGM13:0 = 14, CS11 = 1) cu ICR1 = 19999 (periodă 20 ms). Pune OCR1A = (pulse_us * 2) (0.666 μs/tick la F_CPU = 16 MHz și prescaler = 8 → 1 tick ≈ 0.5 μs, ajustat experimental). Pentru deschis, apelează setDoorPosition(1500), iar pentru închis, setDoorPosition(600). Nu utilizează nicio librărie externă.

saveStateToEEPROM(bool state)

Inițializează interfața I2C (TWBR = 72, TWCR = (1«TWEN)), trimite START, adresa EEPROM-ului extern (0xA0), adresa internă de scriere (ADDR_IS_OPEN), apoi octetul state ? 1 : 0. După fiecare octet transmis (TWINT = 1), verifică codul de stare TWSR și, la final, trimite STOP. Astfel păstrează starea ușii (0 = închis, 1 = deschis) în memorie nevolatilă externă.

loadStateFromEEPROM()

Inițializează TWI, transmite START, adresa EEPROM (0xA0) și offsetul 0, apoi transmite REPEATED START, adresa pentru citire (0xA1), citește un octet (prin generarea NACK la final), și oprește TWI. Apoi, dacă valoarea citită este 1, apelează setDoorPosition(1500), aprinde LED_OPEN (PORTD |= (1«LED_OPEN_PIN)) și stinge LED_CLOSED; în caz contrar, setează setDoorPosition(600), aprinde LED_CLOSED și stinge LED_OPEN.

handleAutoClose()

Verifică în bucla principală dacă isOpen == true și (millis() - lastChangeTs) > CLOSE_DELAY_MS. Dacă da, apelează setDoorPosition(600) (închide), stinge LED_OPEN și aprinde LED_CLOSED, apelează playTone(175, 500), apelează saveStateToEEPROM(false), și actualizează isOpen = false și lastChangeTs = millis().

playTone(uint16_t freq, uint16_t duration_ms)

Configurează Timer0 în modul CTC (WGM01 = 1, prescaler = 64). Calculează OCR0A = (F_CPU / (2 * 64 * freq)) - 1. Activează OCIE0A pentru toggling în ISR(TIMER0_COMPA_vect): la fiecare comă, toggl-ează pinul buzzer (PORTB ^= (1«BUZZER_PIN)). După duration_ms (verificat cu millis()), dezactivează OCIE0A, oprește Timer0 (CS00..2 = 0) și resetează pinul buzzer pe LOW.

logEventToEEPROM(uint8_t eventCode)

Configurează interfața SPI (SPCR = (1«MSTR)|(1«SPE)|(1«SPR0), DDRB |= (1«PB3)|(1«PB5)|(1«PB7) pentru MOSI/SCK/CS). Trimite START pe CS (PB2 = 0), apoi trimite adresa paginii și offset-ul, apoi trimite eventCode și eventual timestamp primit din rtc_getTime(). Așteaptă SPIF după fiecare octet, apoi trimite STOP (PB2 = 1). Dacă adresa ajunge la limita paginii (64 B), incrementează la următoarea pagină (circular).

rtc_getTime()

Configurează TWI (TWBR = 72, TWCR = (1«TWEN)), transmite START, adresa DS3231 (0xD0), comanda de citire (0x00), apoi citește 7 octeți BCD (secunde, minute, ore, zi, dată, lună, an) cu ACK pentru fiecare, iar la ultimul octet cu NACK. Convertește fiecare octet de la BCD la decimal și returnează structura cu ora curentă.

Validarea funcțională a fost realizată fizic, cu testarea tuturor scenariilor:

Distanță > DELTA_THRESHOLD → readDistance() detectează delta semnificativă, setDoorPosition(1500) (deschis), LED_OPEN_PIN HIGH, LED_CLOSED_PIN LOW, saveStateToEEPROM(true), playTone(262, 200), logEventToEEPROM(0x01).

Inactivitate > CLOSE_DELAY_MS → handleAutoClose() închide ușa (setDoorPosition(600)), LED_CLOSED_PIN HIGH, LED_OPEN_PIN LOW, playTone(175, 500), saveStateToEEPROM(false), logEventToEEPROM(0x02).

Buton de reset (INT1) → ISR(INT1_vect) inițiază direct setDoorPosition(600), LED_CLOSED_PIN HIGH, LED_OPEN_PIN LOW, playTone(175, 300), openTs = millis(), saveStateToEEPROM(false), logEventToEEPROM(0x03).

Timeout ADC Low Battery → dacă ADC_read(A0) < THRESHOLD_ADC, se aprinde un LED roșu de avertizare, se trimite prin UART mesajul „LOW BATTERY”, playTone(300, 1000), logEventToEEPROM(0x04).

Parametri de calibrare

Componentă Metodă de calibrare Rezultat / Valoare finală
Servomotor SG90 Test empiric PWM manual 600 µs = 0° (închis), 1500 µs = 90° (deschis)
Tastatură 4×4 Ajustare debounce cu millis() Debounce = 50 ms
LCD 1602 I2C Ajustare timpi între comenzi și date Funcționare stabilă, fără caractere corupte
Buzzer piezoelectric Reglare durată şi frecvenţă tonuri Ton pozitiv: 262–330 Hz; eroare: 262–175 Hz

Rezultate obținute

• Sistemul de deschidere/închidere funcționează stabil și complet automatizat.

• Detectarea variației bruște de distanță (>100 cm) activează servo-motorul cu precizie.

• Ușa rămâne blocată până la detectarea unui delta >100 cm, apoi se deschide instantaneu.

• Închiderea automată după 5 s de inactivitate este realizată non-blocant (millis()).

• LED-urile albe indică clar starea: unul pentru „închis”, celălalt pentru „deschis”.

• Buzzer-ul emite un semnal scurt la deschidere și un semnal lung la închidere automată.

• Butonul de reset forțează imediat închiderea ușii și resetează timer-ul de auto-lock.

• Comunicația cu senzorul ultrasonic se face low-level, fără librării suplimentare.

• Toate componentele (ultrasonic, servo, LED, buzzer, buton) au fost testate fizic și redate în condiții reale.

Concluzii

Am realizat de la zero o ușă inteligentă cu Arduino, trecând prin planificarea logicii, achiziția componentelor și documentarea din surse online și tutoriale YouTube. Experiența practică a fost instructivă și motivantă și m-a ajutat să înțeleg întregul proces de dezvoltare embedded cap-coadă.

Jurnal

Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului.

Bibliografie/Resurse

pm/prj2025/fstancu/mihai_tudor.socea.txt · Last modified: 2025/05/31 23:07 by mihai_tudor.socea
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