This shows you the differences between two versions of the page.
pm:prj2024:iotelea:alexandra.craciun02 [2024/05/25 16:22] alexandra.craciun02 [Bibliografie] |
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 99: | Line 108: | ||
* LinkedList.h: pentru gestionarea listei de fișiere BMP. | * 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, a acțiunilor utilizatorului si a schimbarilor de luminozitate. | Î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 112: | 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 | ||
+ | |||
+ | // 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():** | * Gestionarea Întreruperilor: **buttonInterrupt() & ISR(PCINT2_vect) && senzorIntrerrupt():** | ||
Line 118: | Line 188: | ||
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. | ||
Updateaza filtru si apeleaza functia de draw cu noul filtru. | 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. | 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ă. | 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 131: | 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()** | ||
Încarcă și afișează imaginea BMP curentă de pe cardul SD. | Încarcă și afișează imaginea BMP curentă de pe cardul SD. | ||
+ | |||
+ | <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 ===== | ||