This shows you the differences between two versions of the page.
pm:prj2024:iotelea:alexandra.craciun02 [2024/05/25 15:46] alexandra.craciun02 |
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, 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 | ||
- | * Gestionarea Întreruperilor: **buttonInterrupt() & ISR(PCINT2_vect) && senzorIntrerrupt:** | + | // 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. | ||
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 ===== | ||
Line 173: | 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 + mutat tot pe breadboard mai mare | * 23.05.2024: Adaugare butoane next/prev + mutat tot pe breadboard mai mare | ||
Line 190: | 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> | ||