This shows you the differences between two versions of the page.
|
pm:prj2026:alexandru.jipa2803:eduard.ghelbereu [2026/05/23 02:41] eduard.ghelbereu |
pm:prj2026:alexandru.jipa2803:eduard.ghelbereu [2026/05/24 03:32] (current) eduard.ghelbereu |
||
|---|---|---|---|
| Line 121: | Line 121: | ||
| Aceste functionalitati sunt legate direct de continutul laboratoarelor: GPIO si lucrul cu registrele sunt introduse in laboratorul 0, timerele si intreruperile in laboratorul 2, PWM-ul in laboratorul 3, SPI-ul in laboratorul 5, iar I2C-ul in laboratorul 6. | Aceste functionalitati sunt legate direct de continutul laboratoarelor: GPIO si lucrul cu registrele sunt introduse in laboratorul 0, timerele si intreruperile in laboratorul 2, PWM-ul in laboratorul 3, SPI-ul in laboratorul 5, iar I2C-ul in laboratorul 6. | ||
| + | |||
| + | ==== Fragmente relevante de cod ==== | ||
| + | |||
| + | === Configurarea comunicatiei I2C pentru LCD === | ||
| + | |||
| + | Display-ul LCD foloseste magistrala I2C/TWI. Comunicatia este initializata prin configurarea registrelor TWSR, TWBR si TWCR. | ||
| + | |||
| + | <code c> | ||
| + | void twi_init() { | ||
| + | TWSR = 0x00; | ||
| + | TWBR = 72; | ||
| + | TWCR = (1 << TWEN); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Registrul TWBR stabileste viteza magistralei I2C, iar bitul TWEN activeaza perifericul TWI al microcontrollerului. Aceasta functionalitate este folosita pentru transmiterea comenzilor si caracterelor catre display. | ||
| + | |||
| + | === Trimiterea datelor catre cele doua registre 74HC595 === | ||
| + | |||
| + | Pentru controlul celor 16 LED-uri am folosit doua registre 74HC595. Astfel, toate LED-urile pot fi controlate folosind doar 3 pini ai microcontrollerului. | ||
| + | |||
| + | <code c> | ||
| + | void shift595_send(uint16_t value) { | ||
| + | PORTB &= ~(1 << LATCH_PIN); | ||
| + | |||
| + | for (int i = 15; i >= 0; i--) { | ||
| + | if (value & (1 << i)) PORTD |= (1 << DATA_PIN); | ||
| + | else PORTD &= ~(1 << DATA_PIN); | ||
| + | |||
| + | PORTD |= (1 << CLOCK_PIN); | ||
| + | _delay_us(2); | ||
| + | PORTD &= ~(1 << CLOCK_PIN); | ||
| + | } | ||
| + | |||
| + | PORTB |= (1 << LATCH_PIN); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Functia trimite pe rand cei 16 biti catre registre. Primii 8 biti controleaza LED-urile rosii, iar ceilalti 8 biti controleaza LED-urile verzi. La final, semnalul latch actualizeaza iesirile registrelor. | ||
| + | |||
| + | === Calcularea locurilor libere si actualizarea LED-urilor === | ||
| + | |||
| + | Senzorii IR sunt cititi periodic. In functie de starea fiecarui senzor, se aprinde LED-ul verde pentru loc liber sau LED-ul rosu pentru loc ocupat. | ||
| + | |||
| + | <code c> | ||
| + | for (uint8_t i = 0; i < 8; i++) { | ||
| + | if (senzori_liber[i]) { | ||
| + | locuri++; | ||
| + | leduri |= (1 << i); | ||
| + | } else { | ||
| + | leduri |= (1 << (i + 8)); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | shift595_send(leduri); | ||
| + | </code> | ||
| + | |||
| + | Variabila leduri contine starea tuturor celor 16 LED-uri. Bitii 0-7 sunt folositi pentru LED-urile verzi, iar bitii 8-15 pentru LED-urile rosii. | ||
| + | |||
| + | === Configurarea PWM pentru servo motor === | ||
| + | |||
| + | Servo motorul este controlat cu Timer1, folosind iesirea OC1A de pe pinul PB1 / D9. | ||
| + | |||
| + | <code c> | ||
| + | void servo_init() { | ||
| + | DDRB |= (1 << PB1); | ||
| + | |||
| + | TCCR1A = (1 << COM1A1) | (1 << WGM11); | ||
| + | TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); | ||
| + | |||
| + | ICR1 = 39999; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Timer1 este configurat in mod Fast PWM, cu perioada de aproximativ 20 ms, potrivita pentru controlul unui servo motor. Pozitia barierei este setata prin modificarea registrului OCR1A. | ||
| + | |||
| + | <code c> | ||
| + | void servo_write(uint8_t angle) { | ||
| + | if (angle == 0) { | ||
| + | OCR1A = 2000; | ||
| + | } else { | ||
| + | OCR1A = 4000; | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Valoarea OCR1A determina durata impulsului PWM. Pentru proiect, valorile au fost calibrate astfel incat bariera sa aiba doua pozitii clare: coborata si ridicata. | ||
| + | |||
| + | === Initializarea comunicatiei SPI pentru RFID === | ||
| + | |||
| + | Modulul RC522 comunica prin SPI. Pinii MOSI, SCK si SS sunt configurati ca iesiri, iar MISO ca intrare. | ||
| + | |||
| + | <code c> | ||
| + | void spi_init() { | ||
| + | DDRB |= (1 << PB2) | (1 << PB3) | (1 << PB5); | ||
| + | DDRB &= ~(1 << PB4); | ||
| + | |||
| + | PORTB |= (1 << RFID_SS); | ||
| + | |||
| + | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Bitul SPE activeaza perifericul SPI, iar MSTR configureaza microcontrollerul ca master. RC522 functioneaza ca dispozitiv slave. | ||
| + | |||
| + | === Citirea UID-ului cardului RFID === | ||
| + | |||
| + | Pentru detectarea cardului RFID se trimite o comanda REQA, apoi se foloseste comanda anticollision pentru citirea UID-ului. | ||
| + | |||
| + | <code c> | ||
| + | bool rfid_read_uid(uint8_t *uid) { | ||
| + | rfid_write(0x09, 0x26); | ||
| + | rfid_write(0x01, 0x0C); | ||
| + | rfid_setBit(0x0D, 0x80); | ||
| + | |||
| + | _delay_ms(10); | ||
| + | |||
| + | if (!(rfid_read(0x04) & 0x30)) return false; | ||
| + | |||
| + | rfid_write(0x09, 0x93); | ||
| + | rfid_write(0x09, 0x20); | ||
| + | |||
| + | _delay_ms(10); | ||
| + | |||
| + | for (uint8_t i = 0; i < 5; i++) { | ||
| + | uid[i] = rfid_read(0x09); | ||
| + | } | ||
| + | |||
| + | return true; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Daca nu este detectat niciun card, functia intoarce false. Daca un card este prezent, UID-ul este salvat intr-un vector si ulterior afisat pe LCD. | ||
| + | |||
| + | === Logica principala a proiectului === | ||
| + | |||
| + | Bucla principala actualizeaza permanent starea parcarii si verifica daca a fost citit un card RFID. | ||
| + | |||
| + | <code c> | ||
| + | while (1) { | ||
| + | int locuri = actualizeaza_parcarea(); | ||
| + | |||
| + | if (rfid_read_uid(uid)) { | ||
| + | afiseaza_uid(uid); | ||
| + | |||
| + | if (locuri == 0) { | ||
| + | lcd_print("Acces refuzat"); | ||
| + | } else { | ||
| + | deschide_bariera(); | ||
| + | } | ||
| + | |||
| + | rfid_halt(); | ||
| + | _delay_ms(500); | ||
| + | rfid_init(); | ||
| + | } | ||
| + | |||
| + | _delay_ms(150); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Aceasta este partea care leaga toate modulele intre ele: senzorii determina disponibilitatea locurilor, RFID-ul declanseaza cererea de acces, iar servo motorul actioneaza bariera daca exista locuri libere. | ||
| + | |||
| + | === Actionarea barierei si feedback-ul sonor === | ||
| + | |||
| + | La acces permis, bariera este ridicata, buzzerul este activat, apoi dupa o pauza bariera este coborata automat. | ||
| + | |||
| + | <code c> | ||
| + | void deschide_bariera() { | ||
| + | lcd_clear(); | ||
| + | lcd_print("Acces permis"); | ||
| + | |||
| + | servo_write(90); | ||
| + | buzzer_on_2s(); | ||
| + | |||
| + | _delay_ms(2000); | ||
| + | |||
| + | lcd_clear(); | ||
| + | lcd_print("Bariera jos"); | ||
| + | |||
| + | servo_write(0); | ||
| + | buzzer_on_2s(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Buzzerul functioneaza pe durata miscarii barierei, oferind feedback sonor utilizatorului. | ||
| ==== Structura software ==== | ==== Structura software ==== | ||
| Line 190: | Line 375: | ||
| - cazul in care parcarea este plina si accesul este refuzat. | - cazul in care parcarea este plina si accesul este refuzat. | ||
| - | Link demo video: TODO | + | Link demo video: https://youtube.com/shorts/kGitde-WedE?is=PO4sWVbsrNmVk2R9 |
| + | |||
| + | ==== Github ==== | ||
| + | |||
| + | https://github.com/EduardG05/ProiectPM | ||
| + | |||
| + | ==== Bibliografie ==== | ||
| + | |||
| + | https://www.pcbasic.com/ro/blog/ir_sensors.html | ||
| + | |||
| + | https://ocw.cs.pub.ro/courses/pm/proiect/xplainedmini | ||
| + | |||
| + | https://components101.com/sites/default/files/component_datasheet/SG90%20Servo%20Motor%20Datasheet.pdf | ||
| + | |||
| + | https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf | ||
| <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> | ||