BMP Image File Album and Digital Clock With Arduino
by jandb86 in Circuits > Arduino
1395 Views, 0 Favorites, 0 Comments
BMP Image File Album and Digital Clock With Arduino
This is photo album and digital clock made with Arduino Uno and 1.8 inch TFT display.
It’s a common Arduino project utilizing DS3231 RTC (Real Time Clock) and small graphic display.
Firstly, I planned to make simple digital clock just showing character based time and several graphic icons on the relatively wide TFT display than 0.91” or 1.4”.
But suddenly some different idea struck me and original project is changed to make small digital photograph album with 1.8 inch display.
Although display size is not big, still 1.8 inch is adequate enough for showing small photo like images with 160x128 resolutions.
When converting your photograph files taken by digital camera into bitmap file format and resolution can be displayed on the 1.8 inch display, newly made clock above also can be utilized as digital photo album.
To be useful in real life, time is also shown at the bottom side of the display together with photo image.
For me, it’s become a good chance for revisiting and enjoying old photographs taken quite long time ago and forgotten.
Personally I didn’t travel any place during the year 2020 due to the COVID-19 and have no plan yet to leave on a trip anywhere in this year too.
Anyway, this small photo album reminds me of many good memories with the photos taken during the previous travels before the COVID-19.
Let’s look more detail of the Arduino photo album with digital clock project.
Step 1. Schematics
Like other common digital clock projects, typical components are used such as DS3231 RTC and display module.
But the 1.8 inch TFT display module is a little bit special as it includes SD card board together with display.
As two devices (TFT display and SD card board) are connected with Uno, overall wiring pattern is a little bit complex.
Also for me, TFT display wiring method with Uno is very confusing (Please see description in Part 2 for more detail)
Meanwhile, connecting DS3231 RTC is relatively simple and quite straight-forward.
As two components are using different communication methods, SPI and I2C peripheral communication interfaces should be are utilized at the same time.
Activating both peripheral interfaces makes C-sketch program bigger and it can cause some problem. (I’ll explain later when describing program)
Anyway, let’s move on to the next step.
Step 2. Parts
As digital clock is not an exotic and difficult project, common and typical components are used as listed below.
***
- Arduino Uno board
- 1.8 inch TFT (with ST7735 graphic driver chip) display with 160x128 pixel resolution
- DS3231 Real Time Clock break-out board
- 1~4GB Micro SD card (Big size more than 32GB cannot be recognized by Uno)
- Smart phone charger for 5V power supply to Uno
- Acrylic board (10cm x 7cm size) x 2EA
- Metal supporter 3cm x 4EA
- Bolts and nuts (M3 size)
***
For me, this is the first time using relatively big size (1.8 inch TFT) of display.
While making the clock, pin-layout of TFT display module is especially confusing.
As shown in the picture above, two different brands of TFT modules are having different pin-layouts.
Also flash memory card socket type is also different such as one support SD/SDHC type and the other support only micro SD card.
Actually, there are many different sizes (e.g. 0.91”, 1.4”, 1.8”, 2”) of TFT module products are available and all are supposedly using a little bit different pin-layouts among them.
I’ll compare pin layout of two different TFT modules shown in the picture above.
***
---------------------------------------------------------------------------
(1) Micro SD version (2) SD version Arduino Uno pin connection
---------------------------------------------------------------------------
LED X (Not available) 3.3V
SCK CLK D13
SDA SDA D11
A0 RS D9
RESET RST D8
CS CS D10
GND GND (two!!!) GND
VCC Vcc (1) 5V / (2) 3.3V
***
As you can see, pin naming convention is different and confusing between products.
Some module need 5V(Vcc)/3.3V(LED) power supplies while other need only 3.3V..
I can’t tell you exact pin naming convention rule of any TFT display module. (It’s really diverse!!)
But generally they are following SPI peripheral device interface pin configuration convention.
Therefore, you will need (or can’t avoid) several times of trial and errors before to find correct pin-layout.
But luckily connecting SD card board to Uno is very straight-forward because it strictly following standard SPI interface specification.
Except CS (Control Select), all other signal lines (MOSI, MISO, SCK) can be share among peripheral devices connected together to the single SPI bus.
Therefore, several Arduino Uno pins (D11, D12, D13) are shared by TFT display and SD card board.
But control line (CS) of each device is uniquely assigned such as TFT display using D10 and SD card board using D4..
***
SD_CS (TFT) -> D4 (Arduino)
SD_MOSI -> D11 (Arduino)
SD_MISO -> D12 (Arduino)
SD_SCK -> D13 (Arduino)
***
When looking wiring pattern in the Schematics shown in the Step 1, you can see the inter-connection scheme between TFT display and SD card board.
Maybe, your wiring scheme will be different when you are using different brand of 1.8” TFT display module.
Therefore, use above wiring scheme as just your reference.
Step 3. Wiring DS3231
Wiring DS3231 with Uno is relatively simpler than TFT display module.
As DS3231 RTC is utilizing I2C communication interface, two lines (SCL and SDA) are necessary to be connected with Uno.
The Uno clone board I used has dedicated SCL and SDA pins for plugging Dupon jumper wires directly.
When all components are wired together as explained so far, hardware side assembling is completed
But conclusively preparing software is more important for this project.
Actually I faced some unexpected obstacles while coding program which showing images continually along with time information on the same TFT screen.
Let’s look more detail on the software side from next step.
Step 4. C-sketch Program Coding
In conclusion, two programs are combined for supporting photograph album and digital clock functions.
One of the most advantageous aspects of Arduino is that it support many ready-made and fully functional example codes in IDE (Integrated Development Environment) and various referential programs are available at many web-sites.
Actually the program continually showing BMP image files on TFT screen is example code of Adafruit imageReader library.
When you install imageReader with Arduino IDE library manager, “Breakout ST7735-160x128” example code is installed along with the library.
You can refer the following web-page information for the detail about library installation and utilizing imageReader example code.
***
https://learn.adafruit.com/1-8-tft-display?view=all
***
Likewise, I used referential DS3231 interfacing program which is posted on the one of Korean web-site below.
***
https://deneb21.tistory.com/327
***
But be aware and caution for utilizing two programs mentioned above.
When you simply combine two source codes and compiling together, produced executable size will be bigger than the available internal memory of Arduino Uno.
Because compiled imageReader program takes already about 85% of Uno memory and additional DS3231 interfacing source code requires 22% more usable memory.
Therefore, you can’t load compiled executable to the Arduino Uno.
To avoid the problem, you need to strip down unnecessary code segments from two programs and several optimizations is required for reducing overall program size.
I’ll explain details about program optimization method in the next Steps.
Actually the control logic of combined, optimized and finalized main program is very simple.
It continually reading BMP file one by one from SD card storage and displaying it on the TFT screen.
Meanwhile, main program also read time data from DS3231 and display together at the bottom side of TFT display along with BMP file image.
Let’s look more detail about how the main program is made.
Step 5. Modifying ImageReader Program
Conclusively the Adafruit imageReader library is a little bit complex if you want to know the all details about it.
When you look at the number of header files included in the example source code, you will understand that this library dependent on many other system libraries as listed below..
***
#include // Core graphics library
#include // Hardware-specific library
#include // SD card & FAT filesystem library
#include // SPI / QSPI flash library
#include // Image-reading functions
***
If you want to understand all relevant operational mechanisms of BMP file displaying on the TFT screen, you will necessary to study Adafruit graphic library, ST7735 video controller technical specification/interfacing method, handling flash memory storage file-system details, connection of external storage media with SPI communication interface, and finally all functions included in the imageReader library.
Frankly speaking, I have not so much patience and energy for studying all these necessary technical subjects and many related information.
Therefore, I tried to find a short cut to produce just workable code without investing so many time and efforts.
As a quick solution, I started to delete code segment which seems unnecessary from example code and checked still the BMP image file can be displayed on TFT screen.
After many trial and errors, the final code is produced like below.
***
void loop() {
// --
String file_name = ""; // storing BMP image file name
String tm_stmp = ""; // Time data string which is read from DS3231
int randNumber = 0; // Randomly chosen file name to be displayed on TFT screen
// --
randNumber = random(0, 400); // Select one BMP file among stored 400 image files
if (randNumber < 10) { // if chosen file name is 0~9, add two more “0” to the file name
file_name = "/00"+(String) randNumber+".bmp";
} // if chosen file name is 10 ~ 99, add one more “0” to the file name
else if (randNumber >= 10 && randNumber < 100) {
file_name = "/0"+(String) randNumber+".bmp";
} // if chosen file is 100~399, simply add “/” to the head of file name
else {
file_name = "/"+(String) randNumber+".bmp";
} // Calling Adafruit imageReader function to read BMP file and loading it on TFT screen
stat = reader.drawBMP(&file_name[0], tft, 0, 0);
reader.printStatus(stat); // Check BMP image file is successfully displayed
// --
for (int j=0;j<20;j++) {
tft.setCursor(21, 114);
tft.setTextColor(BLACK, WHITE);
tft.setTextSize(2);
tm_stmp = Get_time_stamp();
tft.print(tm_stmp);
delay(500);
} // Displaying time data string at the bottom side of TFT screen (I’ll explain detail later)
}
***
To my surprise, only single line of code (RED colored line in the code above) is enough for reading BMP image file from SD card, transmit image file data to ST7735 display device driver, and finally image showing on the TFT screen.
Yes! Really single line “stat = reader.drawBMP(&file_name[0], tft, 0, 0)” is all needed..
It’s really very simple…. huh?
The actual name of BMP file shall be displayed is stored in file_name variable and it’s memory address (&file_name[0], C language pointer variable) is sent to reader.drawBMP function.
Then magically BMP image file is loaded and displayed on the TFT screen…..that’s it….really… that’s all necessary…WOW
Step 6. Preparing BMP Image Files
What make this project so special is the BMP files which are shown on the TFT display.
If you are displaying family photographs on screen, it really becomes digital album.
Or you can store all memories which are captured as image files including your friends, pets or happy moments during previous travels.
In the time of COVID-19 pandemic, such images will give you some consolation.
Then, how such image file can be produced?
Answer is simple and just use Windows paint application as shown in the picture above.
For proper loading and displaying by “reader.drawBMP” function, file should be BMP with 24bit color format and resolution should be 160x128 pixels.
If file format is not BMP (with 24bit color depth), “reader.drawBMP” function will complain and raising error.
Also if image is bigger than 160x128 pixels, only portion of image shall be seen on the display.
Therefore, creating necessary image files by following the procedure like below.
***
- Preparing 1GB ~ 4GB size of micro SD card (Higher capacity like 32GB can’t be recognized by SD card board or Arduino SD library)
- Formatting SD card by PC with Windows menu as FAT 32bit file system type (It’s default SD card format option)
- Opening Windows paint application and load your JPEG photograph file from hard-disk (Only one file at a time)
- Open Resize menu of paint application and select resize option as pixel base
- Enter horizontal pixel length as 160 (“Maintain aspect ratio” check-box should be checked -> With this option, vertical pixel length automatically resized without entering number manually)
- Save re-sized file image to SD card as BMP with 24 color file format
- When you storing files to SD card, naming each file like “000.bmp”, “001.bmp”, “002.bmp” and so on (I stored 400 files like 000.bmp ~ 399.bmp)
- When all photographs are stored to SD card, plugging it to the socket of TFT display module
***
Although I don’t know any convenient graphic tool which can convert multiple JPEG files at once to BMP, my photograph album is made by above method. (Total number of files is 400)
Making file name as 3 digit number sequence (e.g. 000.bmp, 001.bmp, 002.bmp ~ 399.bmp) is very important because the naming scheme is intentionally planned.
When you look at the source code shown in the Step 5, you can see “randNumber = random(0, 400)” line.
The “random” function is producing any integer number from 0 to 400 (except 400).
Therefore, you can show randomly chosen file image on the TFT display continually like below.
***
if (randNumber < 10) { // if chosen file name is 0~9, add two more “0” to the file name
file_name = "/00"+(String) randNumber+".bmp";
}
***
Randomly produced integer number is changed into file name string to be loaded from SD card.
By the above BMP file loading scheme, TFT display continually showing randomly chosen image among 400 photographs.
Step 7. Modifying DS3231 Program
Reading time data from DS3231 is very typical and well known application.
Why I’m using program posted in the specific Korean web-site is that the size of source code is relatively compact and easy to modify.
When compiled and finally loaded to Uno, only 25% of usable memory is occupied by the program.
As the size is still bigger and more functionality optimization was necessary, the following of modified source code is made.
***
String Get_time_stamp()
{
String time_stamp = ""; // storing “ HH:MM:SS “ data and used by tft.print(tm_stmp) function
String hrs = ""; // Variable storing hour data
String mins = ""; // Storing minute data
String secs = ""; // Storing second data
// --
watchConsole(); // Setting time to DS3231 when time string like “T2102220636002” is entered
// T21 = year 2021, 0226 = February day 26, 063600 is 6 a.m., 36 minutes and 00 second, 2-> Monday
// --
get3231Date(); // Major sub-routine getting time stamp data from DS3231
// --
if (hours < 10) { // make single digit to two digits hour string such as change “6” to “06”
hrs = "0"+(String) hours;
}
else { // Convert two digits hour data into string such as 11 (integer) -> 11 (string).
hrs = (String) hours;
}
if (minutes < 10) { // make two digits minute string such as change “6” into “06”
mins = "0"+(String) minutes;
}
else {
mins = (String) minutes;
}
if (seconds < 10) { // make two digits second string such as change “1” into “01”
secs = "0"+(String) seconds;
}
else {
secs = (String) seconds;
}
time_stamp = " "+hrs+":"+mins+":"+secs+" "; // Merge time data as “HH:MM:SS” format
return (time_stamp); // return time stamp data to main loop
}
***
Conclusively, size of time data producing program is reduced to 21% of Uno’s usable memory.
When “HH:MM:SS” format of time data is returned to main loop, the following code segment display time data at the bottom of TFT display.
***
tft.setCursor(21, 114); // Locating time string at the bottom side of TFT display
tft.setTextColor(BLACK, WHITE); // Set color of time string as black and background as white
tft.setTextSize(2); // Setting size of time string character as 16x16 pixel
tm_stmp = Get_time_stamp(); // “HH:MM:SS” data returned from DS3231 sub-routine
tft.print(tm_stmp); // Show time on the bottom side of TFT display
***
When merging two programs for compilation and loading optimized final application code, total 86% of Uno memory is occupied.
Finally everything is ready for operating photo album and digital clock.
Step 8. Final Sketch Program and Video
For me this is the first time experiencing full graphic supporting Arduino project.
You can download final sketch code at the link below.
***
https://drive.google.com/file/d/1xHElATk3llSGvKKvumhrsb-AsfChbxCJ/view?usp=sharing
***
As mentioned above, use the source code above just as referential example.
Maybe, other ways will be possible for making more optimized sketch code.
Anyway, handling image file stored in SD card and displaying it on the TFT screen is a little bit challenge for me.
You can see image album and clock operating in the video at the link below.
***
https://drive.google.com/file/d/15AnybaIaGwHzm4Uh-B9AgpZJC9ZvEryW/view?usp=sharing
***
If you are making personally valuable and memorable photo album, the device made will give you more special meaning and pleasure during this harsh COVID-19 period.
Thanks for reading...