This shows you the differences between two versions of the page.
|
pm:prj2026:alexandru.jipa2803:costin.spataru [2026/05/05 10:23] costin.spataru |
pm:prj2026:alexandru.jipa2803:costin.spataru [2026/05/23 22:47] (current) costin.spataru |
||
|---|---|---|---|
| Line 2: | Line 2: | ||
| ===== Introducere ===== | ===== Introducere ===== | ||
| - | <note tip> | + | Proiectul constă într-o cutie inteligentă cu închidere mecanică, destinată depozitării telefonului sau a altor obiecte în timpul unei sesiuni de lucru. Utilizatorul selectează o |
| - | Prezentarea pe scurt a proiectului vostru: | + | durată de blocare, iar dispozitivul blochează capacul folosind un servomotor. Deblocarea se poate face doar după expirarea timpului setat sau prin introducerea unei combinații |
| - | * ce face | + | rotative. |
| - | * care este scopul lui | + | |
| - | * care a fost ideea de la care aţi pornit | + | |
| - | * de ce credeţi că este util pentru alţii şi pentru voi | + | |
| - | </note> | + | |
| - | Proiectul constă într-o cutie inteligentă cu închidere mecanică, destinată depozitării telefonului sau a altor obiecte în timpul unei sesiuni de lucru. Utilizatorul selectează o durată de blocare și poate debloca dispozitivul doar după expirarea timpului sau prin introducerea unei combinații rotative. Sistemul detectează tentativele de forțare și semnalizează acustic și vizual evenimentele. | + | Proiectul este gândit ca un sistem fizic de limitare a accesului la obiecte care pot distrage atenția, în special telefonul. Spre deosebire de o aplicație software de productivitate, |
| + | TimeLock Box obligă utilizatorul să își respecte intervalul de lucru printr-o blocare mecanică reală. Sistemul afișează starea curentă pe un LCD și semnalizează vizual sau acustic | ||
| + | evenimentele importante. | ||
| ===== Descriere generală ===== | ===== Descriere generală ===== | ||
| - | <note tip> | + | Componentele principale ale proiectului sunt vizibile în schema bloc de mai jos. Placa **ATmega328P Xplained Mini** este blocul central al sistemului: citește intrările utilizatorului, actualizează afișajul și comandă mecanismul de blocare. |
| - | O schemă bloc cu toate modulele proiectului vostru, atât software cât şi hardware însoţită de o descriere a acestora precum şi a modului în care interacţionează. | + | |
| - | Exemplu de schemă bloc: http://www.robs-projects.com/mp3proj/newplayer.html | + | {{ timelock-box_block_diagram.png }} |
| - | </note> | + | |
| - | {{timelock_box_schema_bloc.png|}} | + | Encoderul de timp este folosit pentru alegerea duratei de blocare, iar encoderul de cod este folosit pentru introducerea combinației de deblocare. LCD-ul comunică prin I2C și afișează starea sistemului. Servomotorul SG90 este comandat prin PWM și acționează zăvorul mecanic. Microswitch-ul detectează ridicarea capacului, iar buzzerul și LED-urile oferă feedback acustic și vizual. Servo-ul este alimentat separat la 5V, cu masă comună cu restul sistemului. |
| ===== Hardware Design ===== | ===== Hardware Design ===== | ||
| - | <note tip> | + | Schema electrică a proiectului este realizată în KiCad și este atașată mai jos. Pentru lizibilitate, conexiunile sunt grupate prin etichete de semnal, iar alimentarea servo-ului este separată de alimentarea logică. |
| - | Aici puneţi tot ce ţine de hardware design: | + | |
| - | * listă de piese | + | {{url>https://ocw.cs.pub.ro/courses/_media/pm:prj2026:alexandru.jipa2803:timelock-box.pdf 98%,400px}} |
| - | * scheme electrice (se pot lua şi de pe Internet şi din datasheet-uri, e.g. http://www.captain.at/electronic-atmega16-mmc-schematic.png) | + | ==== Listă de componente ==== |
| - | * diagrame de semnal | + | |
| - | * rezultatele simulării | + | ^ Componentă ^ Cantitate ^ Rol în proiect ^ |
| - | </note> | + | | ATmega328P Xplained Mini | 1 | control principal | |
| + | | Encoder rotativ KY-040 pentru timp | 1 | setare durată | | ||
| + | | Encoder rotativ KY-040 pentru cod | 1 | introducere cod | | ||
| + | | LCD 1602 cu interfață I2C | 1 | afișare status | | ||
| + | | Servomotor SG90 | 1 | acționare zăvor | | ||
| + | | Buzzer pasiv 5V | 1 | alarmă acustică | | ||
| + | | Microswitch cu levier (Panasonic) | 1 | detecție capac | | ||
| + | | LED roșu | 1 | indicator alarmă / blocat | | ||
| + | | LED verde | 1 | indicator OK / deschis | | ||
| + | | Rezistențe 330Ω | 2 | limitare curent LED | | ||
| + | | Condensator electrolitic 470uF / 16V | 1 | stabilizare servo | | ||
| + | | Breadboard 830 puncte | 1 | prototipare | | ||
| + | | Fire jumper tată-tată și mamă-tată | mai multe | conexiuni | | ||
| + | | Sursă externă 5V pentru servo | 1 | alimentare servo | | ||
| + | |||
| + | ==== Conexiuni și justificarea pinilor ==== | ||
| + | |||
| + | ^ Modul ^ Conexiuni ^ Motiv ^ | ||
| + | | Encoder cod KY-040 | CLK - PD2; DT - PD3; SW - PD4; VCC -> +5V; GND -> GND | Interfață dedicată pentru setarea și introducerea codului. | | ||
| + | | Encoder timp KY-040 | CLK - PD5; DT - PD6; SW - PD7; VCC -> +5V; GND -> GND | Interfață dedicată pentru alegerea duratei de blocare. | | ||
| + | | LCD 1602 I2C | SDA - PC4; SCL - PC5; VCC -> +5V; GND -> GND | Afișează meniul, codul și timpul rămas. | | ||
| + | | Servomotor SG90 | Semnal - PB1; VCC -> +5V servo; GND -> GND comun | Acționează zăvorul mecanic. | | ||
| + | | Buzzer pasiv | + -> PB0; - -> GND | Feedback sonor și alarmă. | | ||
| + | | Microswitch capac | NO - PB2; C - GND | Detectează deschiderea capacului. | | ||
| + | | LED roșu | anod - PC0; catod -> rezistență 330Ω -> GND | Indică seif blocat / alarmă. | | ||
| + | | LED verde | anod - PC1; catod -> rezistență 330Ω -> GND | Indică seif deschis / OK. | | ||
| + | |||
| + | ==== Alimentare ==== | ||
| + | |||
| + | ^ Linie alimentare ^ Componente alimentate ^ Observații ^ | ||
| + | | +5V logică | ATmega328P Xplained Mini, LCD 1602 I2C, encodere KY-040 | Pentru componente cu consum redus. | | ||
| + | | +5V servo | Servomotor SG90 | Alimentare separată pentru vârfurile de curent. | | ||
| + | | GND comun | Toate modulele | Leagă sursa servo de masa plăcii. | | ||
| + | | Condensator 470uF / 16V | Între +5V servo și GND | Stabilizează alimentarea servo-ului. | | ||
| + | |||
| + | ==== Sumar pini ==== | ||
| + | |||
| + | ^ Pin ATmega328P ^ Funcție în proiect ^ | ||
| + | | PD2 | CLK encoder cod | | ||
| + | | PD3 | DT encoder cod | | ||
| + | | PD4 | SW encoder cod (Buton) | | ||
| + | | PD5 | CLK encoder timp | | ||
| + | | PD6 | DT encoder timp | | ||
| + | | PD7 | SW encoder timp (Buton) | | ||
| + | | PB0 | Buzzer pasiv (Alarmă/Confirmare) | | ||
| + | | PB1 | Semnal servomotor SG90 (Zăvor) | | ||
| + | | PB2 | Intrare senzor ușă (Microswitch Panasonic) | | ||
| + | | PC0 | Ieșire LED roșu | | ||
| + | | PC1 | Ieșire LED verde | | ||
| + | | PC4 | Date I2C pentru ecran LCD | | ||
| + | | PC5 | Ceas I2C pentru ecran LCD | | ||
| + | | PD0, PD1 | UART pentru debug, lăsați liberi | | ||
| + | |||
| + | ==== Dovezi de funcționare ==== | ||
| + | |||
| + | În această secțiune voi încărca video-ul realizat în laborator: | ||
| + | * montajul general pe breadboard; | ||
| + | * testul pentru buzzer și LED roșu; | ||
| + | * testul pentru LCD și LED-ul verde. | ||
| - | * 1 x ATmega328P Xplained Mini | + | {{url>https://www.youtube.com/embed/FYHVN1Hon-A 100%,400px}} |
| - | * 2 x encodere rotative KY-040 | + | |
| - | * 1 x display LCD 1602 cu interfaţă I2C | + | |
| - | * 1 x servomotor SG90 standard | + | |
| - | * 1 x buzzer pasiv 5V | + | |
| - | * 1 x microswitch cu levier | + | |
| - | * 1 x LED roşu | + | |
| - | * 1 x LED verde | + | |
| - | * 2 x rezistenţe 330 Ohm pentru LED-uri | + | |
| - | * 1 x condensator electrolitic 470 uF / 16V | + | |
| - | * 1 x breadboard 830 puncte | + | |
| - | * fire de conexiune tată-tată şi mamă-tată | + | |
| - | * 1 x sursă externă de 5V pentru servomotor | + | |
| ===== Software Design ===== | ===== Software Design ===== | ||
| + | ==== Mediu de dezvoltare ==== | ||
| - | <note tip> | + | Firmware-ul este dezvoltat în **PlatformIO**, folosind framework-ul **Arduino** pentru microcontrollerul **ATmega328P Xplained Mini**. Configurația proiectului folosește platforma atmelavr, placa custom atmega328p_xplained_mini și frecvența de lucru de 16 MHz. |
| - | Descrierea codului aplicaţiei (firmware): | + | |
| - | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | + | ==== Biblioteci folosite ==== |
| - | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | + | |
| - | * algoritmi şi structuri pe care plănuiţi să le implementaţi | + | * Arduino.h - funcționalități de bază Arduino: setup(), loop(), millis(), digitalRead(), pinMode(), tone(). |
| - | * (etapa 3) surse şi funcţii implementate | + | * Wire.h - comunicația I2C/TWI folosită de LCD. |
| - | </note> | + | * LiquidCrystal_I2C.h - afișarea meniurilor, codului și timpului rămas pe LCD 1602. |
| + | * Servo.h - generarea semnalului PWM pentru servomotorul SG90 care acționează zăvorul. | ||
| + | * avr/io.h - acces direct la registre AVR pentru LED-uri, prin DDRC și PORTC. | ||
| + | |||
| + | ==== Element de noutate ==== | ||
| + | |||
| + | Proiectul implementează un **TimeLock Box** cu două encodere rotative separate: unul pentru alegerea timpului de blocare și unul pentru setarea/introducerea codului. Codul de deblocare este setat direct din hardware la începutul sesiunii, fără a fi recompilat firmware-ul și fără cod de deblocare hardcodat în firmware. În plus, cutia are un sistem de alarmă folosind microswitch-ul, care detectează deschiderea capacului cât timp seiful este blocat. | ||
| + | |||
| + | ==== Funcționalități din laboratoare ==== | ||
| + | |||
| + | * **GPIO** - citire butoane encoder, microswitch capac, comandă LED-uri. | ||
| + | * **Întreruperi externe** - citirea encoderului pentru cod folosind pinii PD2 și PD3. | ||
| + | * **Timere / PWM** - semnalul pentru servomotor și semnalele sonore pentru buzzer. | ||
| + | * **I2C / TWI** - comunicația cu LCD-ul 1602 prin adaptorul I2C. | ||
| + | * **USART** - serialul este folosit pentru debug în timpul testării. | ||
| + | |||
| + | ==== Structura aplicației ==== | ||
| + | |||
| + | Logica este organizată ca o mașină de stări: | ||
| + | |||
| + | <code cpp> | ||
| + | enum SafeState { | ||
| + | SET_CODE, | ||
| + | SET_TIME, | ||
| + | LOCKED, | ||
| + | ENTER_CODE, | ||
| + | ALARM | ||
| + | }; | ||
| + | </code> | ||
| + | |||
| + | Stările principale sunt: | ||
| + | |||
| + | * SET_CODE - utilizatorul alege codul de sesiune folosind encoderul de cod; | ||
| + | * SET_TIME - utilizatorul alege durata de blocare folosind encoderul de timp; | ||
| + | * LOCKED - servo-ul ține zăvorul închis, LED-ul roșu este aprins și cronometrul scade; | ||
| + | * ENTER_CODE - utilizatorul introduce codul pentru deblocare sau pentru oprirea alarmei; | ||
| + | * ALARM - microswitch-ul a detectat capacul ridicat cât timp seiful era blocat. | ||
| + | |||
| + | Pe lângă aceste stări există variabile de control pentru starea fizică a seifului: | ||
| + | |||
| + | <code cpp> | ||
| + | bool safe_locked = false; | ||
| + | bool alarm_active = false; | ||
| + | long remaining_seconds = 0; | ||
| + | int session_code[3] = {0, 0, 0}; | ||
| + | </code> | ||
| + | |||
| + | ==== Algoritm ==== | ||
| + | |||
| + | În funcția setup() se inițializează LCD-ul, encoderele, microswitch-ul, buzzerul, LED-urile, servomotorul și comunicația serială. LED-ul verde este aprins la pornire, iar servo-ul este poziționat în starea de zăvor deschis. | ||
| + | |||
| + | În funcția loop() se execută următorii pași: | ||
| + | |||
| + | * se verifică microswitch-ul; dacă seiful este blocat și capacul este ridicat, se activează alarma; | ||
| + | * în starea de alarmă, codul poate fi introdus doar după ce capacul revine închis; | ||
| + | * dacă seiful este blocat, cronometrul este actualizat cu millis(), fără delay() pentru scurgerea timpului; | ||
| + | * timpul continuă să scadă inclusiv în starea ENTER_CODE; | ||
| + | * encoderul de timp modifică durata în trepte de 5 minute; | ||
| + | * encoderul de cod modifică cifra curentă între 0 și 9; | ||
| + | * apăsarea butonului encoderului de cod confirmă cifra curentă; | ||
| + | * la introducerea celor 3 cifre, codul este comparat cu session_code; | ||
| + | * dacă acest cod este corect, servo-ul retrage zăvorul, LED-ul verde se aprinde și sesiunea se resetează; | ||
| + | * dacă timpul expiră natural, seiful se deblochează automat și revine la setarea unui cod nou. | ||
| + | |||
| + | Pentru a reduce problemele de bouncing și citirile greșite ale encoderelor, afișajul LCD nu este redesenat continuu. Se folosește un flag de refresh, astfel încât LCD-ul este actualizat doar când se schimbă o valoare sau o stare: | ||
| + | |||
| + | <code cpp> | ||
| + | bool screen_dirty = true; | ||
| + | |||
| + | // exemplu: după rotirea encoderului | ||
| + | current_digit++; | ||
| + | screen_dirty = true; | ||
| + | </code> | ||
| + | |||
| + | ==== Repartizare pini în firmware ==== | ||
| + | |||
| + | <code cpp> | ||
| + | #define CODE_CLK_PIN 2 // PD2 | ||
| + | #define CODE_DT_PIN 3 // PD3 | ||
| + | #define CODE_SW_PIN 4 // PD4 | ||
| + | |||
| + | #define TIME_CLK_PIN 5 // PD5 | ||
| + | #define TIME_DT_PIN 6 // PD6 | ||
| + | #define TIME_SW_PIN 7 // PD7 | ||
| + | |||
| + | #define BUZZER_PIN 8 // PB0 | ||
| + | #define SERVO_PIN 9 // PB1 | ||
| + | #define DOOR_SWITCH_PIN 10 // PB2 | ||
| + | </code> | ||
| + | |||
| + | LED-urile sunt controlate direct prin registre: | ||
| + | |||
| + | <code cpp> | ||
| + | DDRC |= (1 << PC0) | (1 << PC1); // PC0 roșu, PC1 verde | ||
| + | |||
| + | void stareDeschis_LED() { | ||
| + | PORTC |= (1 << PC1); | ||
| + | PORTC &= ~(1 << PC0); | ||
| + | } | ||
| + | |||
| + | void stareInchis_LED() { | ||
| + | PORTC |= (1 << PC0); | ||
| + | PORTC &= ~(1 << PC1); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | ==== GPIO și întreruperi ==== | ||
| + | |||
| + | Microswitch-ul și butoanele encoderelor sunt configurate cu rezistențele interne de pull-up. Astfel, apăsarea butonului sau închiderea microswitch-ului produce nivel logic LOW. | ||
| + | |||
| + | <code cpp> | ||
| + | pinMode(DOOR_SWITCH_PIN, INPUT_PULLUP); | ||
| + | pinMode(CODE_SW_PIN, INPUT_PULLUP); | ||
| + | pinMode(TIME_SW_PIN, INPUT_PULLUP); | ||
| + | </code> | ||
| + | |||
| + | Encoderul pentru cod este citit prin întreruperi externe pe ambele linii (CLK și DT). Tranzițiile sunt decodate cu un tabel de cuadratură, ceea ce reduce citirile inverse produse de bouncing. | ||
| + | |||
| + | <code cpp> | ||
| + | attachInterrupt(digitalPinToInterrupt(CODE_CLK_PIN), code_encoder_interrupt, CHANGE); | ||
| + | attachInterrupt(digitalPinToInterrupt(CODE_DT_PIN), code_encoder_interrupt, CHANGE); | ||
| + | </code> | ||
| + | |||
| + | ==== PWM, servo și buzzer ==== | ||
| + | |||
| + | Servomotorul SG90 este controlat prin biblioteca Servo.h. În implementarea curentă, unghiul 0 reprezintă zăvorul retras, iar unghiul 90 reprezintă zăvorul coborât. | ||
| + | |||
| + | <code cpp> | ||
| + | Servo lockServo; | ||
| + | |||
| + | lockServo.attach(SERVO_PIN); | ||
| + | lockServo.write(0); // zăvor deschis | ||
| + | lockServo.write(90); // zăvor închis | ||
| + | </code> | ||
| + | |||
| + | Buzzerul este folosit pentru confirmări scurte, erori și alarmă: | ||
| + | |||
| + | <code cpp> | ||
| + | void sunaBuzzer(int durata_ms) { | ||
| + | tone(BUZZER_PIN, 1000); | ||
| + | delay(durata_ms); | ||
| + | noTone(BUZZER_PIN); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | ==== I2C ==== | ||
| + | |||
| + | LCD-ul 1602 este inițializat la adresa 0x27 și este folosit pentru afișarea meniului, codului și timpului rămas. | ||
| + | |||
| + | <code cpp> | ||
| + | LiquidCrystal_I2C lcd(0x27, 16, 2); | ||
| + | |||
| + | lcd.init(); | ||
| + | lcd.backlight(); | ||
| + | lcd.clear(); | ||
| + | </code> | ||
| + | |||
| + | Timpul rămas este afișat în format HHh:MMm:SSs, pentru a putea reprezenta inclusiv sesiuni mai lungi de o oră. | ||
| + | |||
| + | ==== USART ==== | ||
| + | |||
| + | Serialul este folosit pentru debug în timpul dezvoltării și testării: | ||
| + | |||
| + | <code cpp> | ||
| + | Serial.begin(115200); | ||
| + | </code> | ||
| + | |||
| + | ==== Calibrări ==== | ||
| + | |||
| + | * Encoderele KY-040 sunt citite pe front descendent și au debounce software scurt, bazat pe millis(). | ||
| + | * LCD-ul este actualizat doar la schimbări de stare sau valoare, pentru a evita lag-ul care poate produce citiri greșite ale encoderelor. | ||
| + | * Pentru encoderul de timp, fiecare pas modifică durata cu 5 minute. | ||
| + | * Butoanele encoderelor au un mic delay de confirmare pentru a evita apăsările multiple. | ||
| + | * Unghiurile servo-ului (0 și 90) pot fi ajustate în funcție de zăvorul mecanic real. | ||
| + | * Servo-ul este alimentat separat la 5V, iar GND-ul sursei servo este comun cu GND-ul plăcii. | ||
| + | * Dacă bouncing-ul mecanic persistă, se pot adăuga condensatori de 100nF între CLK și GND, respectiv între DT și GND pentru fiecare encoder. | ||
| ===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
| - | <note tip> | + | Am obținut o cutie care se blochează pe un timp ales din encoder și se deschide doar cu codul setat sau după ce expiră timpul. Pe LCD se afișează timpul rămas, iar dacă ușa este forțată pornește alarma. |
| - | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | |
| - | </note> | + | {{url>https://www.youtube.com/embed/Un5VciYyRXg 100%,400px}} |
| ===== Concluzii ===== | ===== Concluzii ===== | ||
| + | |||
| + | Proiectul funcționează cum mi-am propus. Partea cea mai dificilă a fost legarea și calibrarea componentelor, mai ales encoderele și microswitch-ul. | ||
| ===== Download ===== | ===== Download ===== | ||
| - | <note warning> | + | <html> |
| - | 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ă ;-). | + | <style> |
| - | + | a.timelock-github-link { text-decoration: none; } | |
| - | 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**. | + | a.timelock-github-link:hover { text-decoration: underline; } |
| - | </note> | + | </style> |
| + | <a class="timelock-github-link" href="https://github.com/Costin10/TimeLock-Box" target="_blank" rel="noopener"> | ||
| + | <svg width="18" height="18" viewBox="0 0 16 16" aria-hidden="true" style="vertical-align:-3px;margin-right:6px" fill="currentColor"> | ||
| + | <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82A7.64 7.64 0 0 1 8 3.87c.68 0 1.36.09 2 .26 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"></path> | ||
| + | </svg> | ||
| + | GitHub | ||
| + | </a> | ||
| + | </html> | ||
| ===== Jurnal ===== | ===== Jurnal ===== | ||
| Line 86: | Line 313: | ||
| <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||
| - | |||
| - | |||