This shows you the differences between two versions of the page.
pm:prj2024:iotelea:alexandra.craciun02 [2024/05/25 03:19] alexandra.craciun02 [Concluzii] |
pm:prj2024:iotelea:alexandra.craciun02 [2024/05/26 19:03] (current) alexandra.craciun02 [Hardware Design] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Flashback photo frame ====== | ====== Flashback photo frame ====== | ||
- | Nume: Craciun Alexandra-Georgiana | + | <note>Nume: Craciun Alexandra-Georgiana |
- | Grupa: 331CB | + | Grupa: 331CB</note> |
Line 28: | Line 28: | ||
===== Hardware Design ===== | ===== Hardware Design ===== | ||
- | Lista de piese: | + | **Lista de piese:** |
<note tip> | <note tip> | ||
- placa Arduino | - placa Arduino | ||
Line 40: | Line 40: | ||
</note> | </note> | ||
- | {{ :pm:prj2024:iotelea:eagle_bun.png?nolink&700 |}} | + | {{ :pm:prj2024:iotelea:eagle_bun.png?nolink&800 |}} |
- | Conectare piese: | + | **Conectare piese:** |
* Ecran LCD - Arduino: | * Ecran LCD - Arduino: | ||
Line 86: | Line 86: | ||
- | Asamblare hardware: | + | **Asamblare hardware:** |
+ | |||
+ | Inainte de cod | ||
+ | |||
+ | {{ :pm:prj2024:iotelea:hardware.jpg?nolink&500 |}} | ||
+ | |||
+ | Varianta intermediara | ||
{{ :pm:prj2024:iotelea:hard_final.jpeg?nolink&400 |}} | {{ :pm:prj2024:iotelea:hard_final.jpeg?nolink&400 |}} | ||
+ | Varianta finala | ||
+ | |||
+ | {{ :pm:prj2024:iotelea:final2.jpeg?nolink&500 |}} | ||
===== Software Design ===== | ===== Software Design ===== | ||
Line 97: | Line 106: | ||
* SD.h: pentru accesul și citirea fișierelor BMP de pe cardul SD. | * SD.h: pentru accesul și citirea fișierelor BMP de pe cardul SD. | ||
* TFT.h: pentru interacțiunea și desenarea pe ecranul TFT. | * TFT.h: pentru interacțiunea și desenarea pe ecranul TFT. | ||
- | * LinkedList.h: pentru gestionarea listei de fișiere BMP în modul stack. | + | * LinkedList.h: pentru gestionarea listei de fișiere BMP. |
- | Functionalitate: | + | **Functionalitate** |
- | + | ||
- | În codul dat, inițializarea sistemului începe prin configurarea piniilor și inițializarea componentelor hardware, precum ecranul TFT și cardul SD. Gestionarea întreruperilor permite detectarea rapidă a apăsării butoanelor și a acțiunilor utilizatorului. După inițializarea cardului SD și crearea unei liste cu imagini disponibile, sistemul monitorizează constant starea senzorului de lumină și starea butoanelor pentru a răspunde la acțiunile utilizatorului. Am ales aceasta metoda pentru ca schimbarile sa fie in timp real, in loc sa fie aplicate urmatorului fisier. | + | |
+ | În codul dat, inițializarea sistemului începe prin configurarea piniilor și inițializarea componentelor hardware, precum ecranul TFT și cardul SD. Gestionarea întreruperilor permite detectarea rapidă a apăsării butoanelor, a acțiunilor utilizatorului si a schimbarilor de luminozitate. | ||
Principala funcție de execuție, loop(), coordonează afișarea imaginilor BMP pe ecranul TFT, încărcând și afișând fiecare imagine în conformitate cu interacțiunile utilizatorului. Funcția bmpDraw() este responsabilă de deschiderea și afișarea fiecărei imagini BMP, inclusiv aplicarea unui filtru alb-negru opțional. | Principala funcție de execuție, loop(), coordonează afișarea imaginilor BMP pe ecranul TFT, încărcând și afișând fiecare imagine în conformitate cu interacțiunile utilizatorului. Funcția bmpDraw() este responsabilă de deschiderea și afișarea fiecărei imagini BMP, inclusiv aplicarea unui filtru alb-negru opțional. | ||
+ | **Variabile globale** | ||
- | Descriere Funcții | + | <code c> |
+ | #define PIN_SD_CS 4 | ||
+ | #define PIN_TFT_CS 10 | ||
+ | #define PIN_DC 9 | ||
+ | #define PIN_RST 8 | ||
+ | #define BUTTON_PIN 2 | ||
+ | #define BACKLIGHT_PIN 5 | ||
+ | #define SENSOR_PIN 3 | ||
+ | #define BUTTON_PIN_NEXT 6 | ||
+ | #define BUTTON_PIN_BACK 7 | ||
+ | |||
+ | #define DELAY_IMAGE_SWAP 5000 // each image is shown for 5 seconds | ||
+ | #define BUFFPIXEL 20 // Number of pixels to buffer | ||
+ | |||
+ | int filtru = 0; | ||
+ | String currentFile; | ||
+ | unsigned long lastDebounceTime = 0; // Last pressed time | ||
+ | unsigned long debounceDelay = 50; // press interval | ||
+ | |||
+ | TFT TFTscreen = TFT(PIN_TFT_CS, PIN_DC, PIN_RST); //init screen | ||
+ | |||
+ | LinkedList<String> bmpFiles; // List to store all BMP files | ||
+ | int currentFileIndex = -1; // Index of the current file being displayed | ||
+ | |||
+ | </code> | ||
+ | |||
+ | **Descriere Funcții** | ||
* Setup Inițial: **setup():** | * Setup Inițial: **setup():** | ||
Line 113: | Line 148: | ||
Inițializează ecranul TFT, cardul SD și setează întreruperi pentru butoanele de control. | Inițializează ecranul TFT, cardul SD și setează întreruperi pentru butoanele de control. | ||
+ | <code c> void setup() { | ||
+ | // initialize default serial connection to send debug information | ||
+ | Serial.begin(9600); | ||
+ | while (!Serial) { | ||
+ | // wait until default serial connection is fully set up | ||
+ | } | ||
+ | // Initialize button filter pin | ||
+ | pinMode(BUTTON_PIN, INPUT_PULLUP); | ||
+ | attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonInterrupt, FALLING); // Attach interrupt to the button pin | ||
+ | // Initialize backlight pin and sensor pin | ||
+ | pinMode(BACKLIGHT_PIN, OUTPUT); | ||
+ | pinMode(SENSOR_PIN, INPUT); | ||
+ | attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), senzorIntrerrupt, CHANGE); // Attach interrupt to the button pin | ||
- | * Gestionarea Întreruperilor: **buttonInterrupt() & ISR(PCINT2_vect):** | + | // Initialize next and back pin |
+ | pinMode(BUTTON_PIN_NEXT, INPUT_PULLUP); | ||
+ | pinMode(BUTTON_PIN_BACK, INPUT_PULLUP); | ||
+ | |||
+ | PCICR |= (1 << PCIE2); // Enable Pin Change Interrupts for D0 to D7 (PCINT16 to PCINT23) | ||
+ | PCMSK2 |= (1 << PCINT22); // Enable pin change interrupt on pin 6 (PCINT22) | ||
+ | PCMSK2 |= (1 << PCINT23); // Enable pin change interrupt on pin 7 (PCINT23) | ||
+ | |||
+ | sei(); // Enable global interrupts | ||
+ | |||
+ | // The following two lines replace "TFTscreen.begin();" => avoids that red and blue (?) are swapped/interchanged | ||
+ | TFTscreen.initR(INITR_BLACKTAB); | ||
+ | TFTscreen.setRotation(1); | ||
+ | |||
+ | TFTscreen.background(255, 255, 255); // prints black screen to TFT display | ||
+ | analogWrite(BACKLIGHT_PIN, 250); | ||
+ | |||
+ | init_SD(); // function call that initializes SD card | ||
+ | |||
+ | } </code> | ||
+ | |||
+ | * Gestionarea Întreruperilor: **buttonInterrupt() & ISR(PCINT2_vect) && senzorIntrerrupt():** | ||
1. Această funcție este apelată la apăsarea butonului pentru aplicarea filtrului alb-negru. | 1. Această funcție este apelată la apăsarea butonului pentru aplicarea filtrului alb-negru. | ||
Folosește o verificare anti-debounce pentru a evita multiple declanșări dintr-o singură apăsare. | Folosește o verificare anti-debounce pentru a evita multiple declanșări dintr-o singură apăsare. | ||
- | Incrementează un contor pentru a urmări starea butonului (activat/dezactivat). | + | Updateaza filtru si apeleaza functia de draw cu noul filtru. |
+ | |||
+ | <code c> void buttonInterrupt() { | ||
+ | unsigned long currentMillis = millis(); | ||
+ | if (currentMillis - lastDebounceTime > debounceDelay) { | ||
+ | if (digitalRead(BUTTON_PIN) == LOW) { | ||
+ | filtru = (filtru + 1) % 2; | ||
+ | bmpDraw((char*)currentFile.c_str(), 0, 0, filtru); // Redraw with filter | ||
+ | } | ||
+ | lastDebounceTime = currentMillis; // Update last | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
2. Gestionează întreruperile pentru butoanele de next și back. | 2. Gestionează întreruperile pentru butoanele de next și back. | ||
Verifică starea butoanelor și updateaza indexul fișierului afisat în funcție de apăsările detectate. | Verifică starea butoanelor și updateaza indexul fișierului afisat în funcție de apăsările detectate. | ||
+ | Apeleaza functia de draw cu noua imagine. | ||
+ | |||
+ | <code c> ISR(PCINT2_vect) { | ||
+ | unsigned long currentMillis = millis(); | ||
+ | if (currentMillis - lastDebounceTime > debounceDelay) { | ||
+ | bool nextPressed = digitalRead(BUTTON_PIN_NEXT) == HIGH; | ||
+ | bool backPressed = digitalRead(BUTTON_PIN_BACK) == HIGH; | ||
+ | |||
+ | if (nextPressed && !backPressed) { | ||
+ | currentFileIndex = (currentFileIndex + 1) % bmpFiles.size(); | ||
+ | } | ||
+ | if (backPressed && !nextPressed) { | ||
+ | if (currentFileIndex == 0) { | ||
+ | currentFileIndex = bmpFiles.size() - 1; // Wrap to last image | ||
+ | } else { | ||
+ | currentFileIndex--; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | currentFile = bmpFiles.get(currentFileIndex); | ||
+ | // Draw the current image | ||
+ | bmpDraw((char*)currentFile.c_str(), 0, 0, filtru); | ||
+ | lastDebounceTime = millis(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | 3. Gestionează întreruperile de la senzorul de lumină. La detectarea unei schimbări în starea senzorului, aceasta ajustează luminozitatea ecranului TFT, astfel incat la intuneric luminozitatea va fi redusă, iar la lumină, ridicată. | ||
+ | |||
+ | <code c>void senzorIntrerrupt() { | ||
+ | |||
+ | int senzor = digitalRead(SENSOR_PIN); | ||
+ | if (!senzor) | ||
+ | analogWrite(BACKLIGHT_PIN, 250); | ||
+ | else | ||
+ | analogWrite(BACKLIGHT_PIN, 100); | ||
+ | } | ||
+ | </code> | ||
Line 129: | Line 250: | ||
Parcurge directorul rădăcină al cardului SD și adaugă toate fișierele BMP găsite în lista bmpFiles. | Parcurge directorul rădăcină al cardului SD și adaugă toate fișierele BMP găsite în lista bmpFiles. | ||
+ | <code c> void init_SD() { | ||
+ | // try to init SD card | ||
+ | Serial.print(F("SD card init...")); | ||
+ | if (!SD.begin(PIN_SD_CS)) { | ||
+ | Serial.println(F("ERROR")); // failed | ||
+ | return; | ||
+ | } | ||
+ | Serial.println(F("SUCCESS")); // ok | ||
+ | |||
+ | // Store all BMP files in the bmpFiles list | ||
+ | File dir = SD.open("/"); | ||
+ | File entry; | ||
+ | while ((entry = dir.openNextFile())) { | ||
+ | if (!entry.isDirectory() && String(entry.name()).endsWith(".BMP")) { | ||
+ | bmpFiles.add(String(entry.name())); | ||
+ | } | ||
+ | entry.close(); | ||
+ | } | ||
+ | dir.close(); | ||
+ | |||
+ | if (bmpFiles.size() > 0) { | ||
+ | currentFileIndex = 0; // Start with the first file | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
* Funcția Principală de Executare: **loop()** | * Funcția Principală de Executare: **loop()** | ||
- | Verifică starea senzorului de lumină și ajustează luminozitatea ecranului în funcție de aceasta. | ||
Încarcă și afișează imaginea BMP curentă de pe cardul SD. | Încarcă și afișează imaginea BMP curentă de pe cardul SD. | ||
- | Monitorizează dacă a fost apăsat butonul pentru aplicarea filtrului alb-negru și reafișează imaginea cu filtrul aplicat. | + | |
+ | <code c> void loop() { | ||
+ | currentFile = bmpFiles.get(currentFileIndex); | ||
+ | // Draw the current image | ||
+ | bmpDraw((char*)currentFile.c_str(), 0, 0, filtru); | ||
+ | delay(DELAY_IMAGE_SWAP); | ||
+ | currentFileIndex= (currentFileIndex + 1) % bmpFiles.size(); //go default to new image | ||
+ | } | ||
+ | </code> | ||
Line 150: | Line 303: | ||
{{:pm:prj2024:iotelea:pm_photo_frame.rar|}} | {{:pm:prj2024:iotelea:pm_photo_frame.rar|}} | ||
- | |||
===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
- | TODO | + | Rezultatul a fost unul satisfacator, intrucat toate functionalitatile dorite au fost implementate :-) |
+ | <note tip> | ||
+ | Link catre demo pe Youtube: https://youtu.be/lRo6TX4jXq0?si=5vUYiCinLNkvlKRF | ||
+ | |||
+ | </note> | ||
===== Concluzii ===== | ===== Concluzii ===== | ||
Pe parcursul acestui proiect, am intampinat diverse dificulatati, cum ar fi fire ce nu faceau bine contact, folosirea gresita a butoanelor sau a intreruperilor, formatul gresit al pozelor de pe card. Consider ca cea mai grea parte a fost software, nu hardware, intrucat am avut destul de putine piese care insa faceau multe instructiuni ce trebuiau sincronizate :-D Au fost necesare documentatie extra, incercari destul de multe, emotii cand dadea black screen sau cand nu mai citea USB -ul. Iar tot procesul a fost usor diferit de ceea ce eram obisnuita, implicand acum si parte hardware si rezultat real-time, dar si frica ca poti sa arzi lucruri si nu mai ai timp sa ti vina alta comanda de piese m( | Pe parcursul acestui proiect, am intampinat diverse dificulatati, cum ar fi fire ce nu faceau bine contact, folosirea gresita a butoanelor sau a intreruperilor, formatul gresit al pozelor de pe card. Consider ca cea mai grea parte a fost software, nu hardware, intrucat am avut destul de putine piese care insa faceau multe instructiuni ce trebuiau sincronizate :-D Au fost necesare documentatie extra, incercari destul de multe, emotii cand dadea black screen sau cand nu mai citea USB -ul. Iar tot procesul a fost usor diferit de ceea ce eram obisnuita, implicand acum si parte hardware si rezultat real-time, dar si frica ca poti sa arzi lucruri si nu mai ai timp sa ti vina alta comanda de piese m( | ||
- | Totusi, a fost o experienta interesanta, iar satisfactia rezultatului final a fost uriasa. Pe masura ce mai reuseam sa fac o functionalitate, prindeam si mai mult drag de proiect, pe care il voi pastra, cu siguranta, ca amintire. | + | Totusi, a fost o experienta interesanta, iar satisfactia rezultatului final a fost uriasa. Pe masura ce mai reuseam sa fac o functionalitate, prindeam si mai mult drag de proiectul pe care il voi pastra, cu siguranta, ca amintire. |
Line 169: | Line 325: | ||
* 16.05.2024: Verificarea pieselor si asamblarea lor | * 16.05.2024: Verificarea pieselor si asamblarea lor | ||
* 17.05.2024: Adaugare scheme hardware | * 17.05.2024: Adaugare scheme hardware | ||
- | * 19.05.2024: Scriere cod pentru ecran si buton | + | * 19.05.2024: Scriere cod pentru ecran si buton + citire card SD |
- | * 20.05.2024: Citire card SD | + | * 20.05.2024: Adaugarea senzorului si a filtrului alb-negru fara intreruperi, ci cu iterare prin for |
- | * 21.05.2024: Adaugarea senzorului si a filtrului alb-negru | + | * 21.05.2024: Adaugare intreruperi |
* 22.05.2024: Fixed a bug cu intreruperi; am crezut ca am ars ceva LOL | * 22.05.2024: Fixed a bug cu intreruperi; am crezut ca am ars ceva LOL | ||
- | * 23.05.2024: Adaugare butoane next/prev | + | * 23.05.2024: Adaugare butoane next/prev + mutat tot pe breadboard mai mare |
===== Bibliografie ===== | ===== Bibliografie ===== | ||
Line 186: | Line 342: | ||
* https://www.electronics-lab.com/project/arduino-diy-photo-frame/ | * https://www.electronics-lab.com/project/arduino-diy-photo-frame/ | ||
* https://www.arduino.cc/reference/en/libraries/tft/ | * https://www.arduino.cc/reference/en/libraries/tft/ | ||
+ | * https://github.com/sparkfun/SparkFun-Eagle-Libraries | ||
<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> | ||