CHAPTER 8

Arduino TFT LCD Display and Image Sensor Projects


THIS CHAPTER DISCUSSES the Arduino TFT LCD and image sensors. First, we introduce the thin-film-transistor (TFT) liquid-crystal display (LCD) with SD card reader/writer that is specifically designed for the Arduino. Then a hands-on example shows you how to use the TFT display and the attached SD card reader/writer. You will learn how to draw text and animated lines, circles, rectangles, and points to the TFT display. You also learn how to use the SD card to write and read data from an SD card. Then another hands-on example shows you how to use the TFT display and SD card reader/writer as part of a door alarm system that also tracks the number of times the door alarm has been tripped. Finally, we discuss cameras that can be used with the Arduino and cover the features of the ArduCAM OV2640 minicamera. The chapter concludes with a hands-on example using the AduCAM minicamera that shows you how to take a photo and then save it to an SD card by pressing a button.

Arduino TFT LCD Color Display Screen with SD Card Reader/Writer

The TFT display screen with SD card reader and writer is a standard device that is supported natively in the Arduino Integrated Development Environment (IDE) version 1.0.5 and above. The built-in Arduino library provides for the display of color text, images, and shapes such as rectangles, circles, lines, and points using native built-in functions. In addition, the TFT display device also contains an SD card reader and writer that can be used to read and write data from a small micro-SD card. The SD card slot is on the back on the display near the top and middle of the device (Figure 8-1).


Figure 8-1

TFT display with SD card reader/writer for Arduino.

The pin connections to the Arduino board depend on the specific model of the Arduino board you are using. The following pin connections are for the Arduino Uno. For example, the 5-V pin on the TFT display connects to the 5-V pin of the Arduino. The MISO pin on the TFT board connects to pin 12 of the Arduino board:

+5V

+5V

MISO

pin 12

SCK

pin 13

MOSI

pin 11

LCD CS

pin 10

SD CS

pin 4

D/C

pin 9

RESET

pin 8

BL

+5V

GND

GND

The recommended way to connect this board to the Arduino is to use a breadboard. The TFT display is inserted into the breadboard, and wires connect each of the pins on the TFT display to the pins on the Arduino. Figure 8-2 shows how to connect the TFT display to the Arduino Uno. The TFT display is facing up with the SD card on top and the pins that need to be connected to the Arduino on the right-hand side.


Figure 8-2

TFT display hookup information for the Arduino Uno.

Hands-on Example:
Arduino TFT Display and SD Card Reader/Writer Test

In this hands-on example project, you learn how to connect and use a standard TFT color LCD display with SD card reader/writer with an Arduino Uno. The TFT display connections described in this section are specific to the Arduino Uno. In this example project, you will learn how to display text, lines, rectangles, circles, and points on the TFT screen. In addition, you will learn how to read and write data using the SD card that is built into the back of the TFT LCD display device.

Parts List

To build this on example project, you will need

1 Arduino TFT LCD display with built-in SD card reader/writer

1 micro-SD card

1 breadboard (needed to hold the TFT LCD display)

1 Arduino Uno (Connection instructions in this example project are specifically designed for the Arduino Uno.)

Wires to connect the TFT LCD display to the Arduino

Setting Up the Hardware

To connect the hardware for this hands-on example project, you will need to:

Connect the 5-V pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the MISO pin on the TFT display to pin 12 of the Arduino Uno.

Connect the SCK pin on the TFT display to pin 13 of the Arduino Uno.

Connect the MOSI pin on the TFT display to pin 11 of the Arduino Uno.

Connect the LCD CS pin on the TFT display to pin 10 of the Arduino Uno.

Connect the SD CS pin on the TFT display to pin 4 of the Arduino Uno.

Connect the D/C pin on the TFT display to pin 9 of the Arduino Uno.

Connect the RESET pin on the TFT display to pin 8 of the Arduino Uno.

Connect the BL pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the GND pin on the TFT Display to the GND pin of the Arduino Uno (Figure 8-3).


Figure 8-3

Arduino TFT display and SD card reader/writer test.

Setting Up the Software

The software for this example project draws text and shapes and displays images from the SD card onto the TFT LCD display. It also reads and writes test data using the SD card. The program does this by:

1. Including the Serial Peripheral Interface (SPI ) library. This library is used to communicate with the TFT display and the SD card.

#include <SPI.h>

2. Including the SD library. The SD library is used to provide functions for the reading and writing of data to the SD card that is built into the TFT display.

#include <SD.h>

3. Including the TFT library. This is done so that functions that control the TFT display can be accessed.

#include <TFT.h>

4. Defining the chip select pin for the SD card as pin 4 of the Arduino. If the chip select pin is set to 0 or low voltage, the SD card communicates with the Arduino. If the chip select pin is set to 1 or high voltage, the SD card ignores the Arduino.

#define sd_cs 4

5. Defining the chip select pin for the TFT LCD screen as pin 10 of the Arduino:

#define lcd_cs 10

6. Defining the DC pin on the TFT display as connected to pin 9 of the Arduino:

#define dc 9

7. Defining the Reset pin on the TFT display as connected to pin 8 of the Arduino:

#define rst 8

8. Defining the variable TFTScreen, which is an object of type TFT that represents the TFT display screen:

TFT TFTScreen = TFT(lcd_cs, dc, rst);

9. Defining the BitmapImage variable, which holds the actual bitmap image that is loaded into and displayed on the TFT screen using PImage class. The PImage class is part of the standard TFT library.

PImage BitmapImage;

10. Using the TestFile variable to read and write data to a file employing the SD card reader/writer located on the back of the TFT display:

File TestFile;

11. Initializing the setup() function, which:

a. Initializes the Serial Monitor with a communication speed of 9,600 baud.

b. Printing a text message to the Serial Monitor indicating the start of the program.

c. Initializes the TFT screen device.

d. Setting the background color of the TFT screen to black by calling the TFTScreen.background(0, 0, 0) function with all zeros for all the color input values.

e. Setting the color of the text that will be placed on the TFT screen to white by calling the TFTScreen.stroke(255, 255, 255) function with all 255s, which is full intensity for all color input values.

f. Printing some text onto the TFT screen indicating that the program has started.

g. Delaying program execution for 3 seconds.

h. Initializing the SD card reader and writer.

i. Printing the status of the SD card reader/writer initialization to the Serial Monitor. See Listing 8-1.

The LoadImage() function:

1. Loads in a bitmap image called filename from the SD card that is attached to the TFT display. The filename is an input character array to the function.

2. Checks to see whether the bitmap image is valid.

3. If the bitmap image is not valid, prints a text error message to the Serial Monitor.

4. Displays the bitmap image on the TFT screen starting at the upper left-hand corner of the display. See Listing 8-2.

The LoadTestImage() function:

1. Clears the TFT background screen to black.

2. Loads and displays the bitmap on the SD card attached to the TFT display with the filename testbmp.bmp.

3. Suspends execution of the program for 3 seconds. See Listing 8-3.

The DrawLines() function animates a line on the TFT screen by:

1. Clearing the TFT screen and setting the background color to black.

2. Drawing a series of white lines across the TFT screen that move from left to right by:

a. Setting the line color to white.

b. Drawing a line starting at x position 0 and y position 10 on the TFT screen and ending at x position i and y position 60. The value of i ranges from 0 to the width of the TFT screen in pixels.

c. Setting the line color to black.

d. Drawing a line starting from x position 0 and y position 10 on the TFT screen and ending at x position i and y position 60. The range of the values for i is from 0 to the width of the TFT screen in pixels. By drawing a black line over the white line that was just drawn, you are erasing the white line and performing a simple form of animation.

3. Drawing a series of white lines across the TFT screen that move from right to left by:

a. Setting the color of the line to white.

b. Drawing a line starting at x position 0 and y position 10 on the TFT screen and ending at x position i and y position 60. The value of i ranges from the width of the TFT screen in pixels to 1.

c. Setting the color of the line to black.

d. Drawing a black line over the white line.

4. Suspending execution of the program for 3 seconds. See Listing 8-4.

The DrawRectangle() function moves a blue rectangle across the screen of the TFT by:

1. Clearing the background of the TFT and setting the background color to black.

2. Turning off the outline color of the shapes that are drawn.

3. Drawing a rectangle that moves from the left-hand side of the TFT screen to the right-hand side of the screen by:

a. Setting the rectangle color to blue.

b. Drawing the rectangle with the upper left-hand corner located at (i,10) with a width of 40 pixels and a height of 50 pixels. The i value will range from 0 to 40 pixels less than the width of the screen. By doing this, the entire rectangle will stay within the full view of the screen.

c. Setting the rectangle color to black.

d. Drawing the rectangle at the same location as in step b, which erases the rectangle from the TFT display.

4. Drawing a rectangle that moves from the right-hand side to the left-hand side of the TFT screen by:

a. Setting the rectangle color to blue.

b. Drawing the rectangle with a width of 40 pixels and a height of 50 pixels at an x position of i and a y position of 10. The value of i will range from 40 less than the width of the TFT screen to 1.

c. Setting the rectangle color to black.

d. Drawing the rectangle at the same position as in step b, which will have the effect of erasing that rectangle.

5. Setting the rectangle color to blue.

6. Drawing a rectangle of width 40 pixels and height of 50 pixels at location (0,10).

7. Delaying program execution for 3 seconds. See Listing 8-5.

The DrawCircle() function draws and animates a circle on the TFT screen by:

1. Clearing the background of the TFT screen and setting the background color to black.

2. Disabling the drawing of the outline color for the circle by calling the noStroke() function.

3. Drawing a series of circles on the TFT screen that will move the circle from the left-hand side of the screen to the right-hand side by:

a. Setting the color of the circle to green.

b. Drawing the circle at x and y position (i,20) with a radius of 20 pixels. The i value will range from 20 to 40 less than the width of the TFT screen.

c. Changing the color of the circle to black.

d. Drawing the circle at the same location as in step b, which has the effect of erasing the circle on the TFT display.

4. Drawing a series of circles on the TFT screen that will move the circle from the right-hand side of the screen to the left-hand side by:

a. Setting the color of the circle to green.

b. Drawing the circle at x and y position (i,20) with a radius of 20 pixels. The range of the i values will be from 40 less than the width of the LCD screen to 21. This moves the circle from the right-hand side of the screen to the left-hand side.

c. Setting the color of the circle to black.

d. Draw the circle at the same position as in step b, which has the effect of erasing the previously drawn circle.

5. Setting the color of the circle to green.

6. Drawing the circle at x,y location (20,20) with a radius of 20 pixels.

7. Suspending program execution for 3 seconds. See Listing 8-6.

The DrawPoint() function draws points to the TFT screen by:

1. Clearing the TFT screen and setting the background color to black.

2. Setting the color of the point to white by calling the stroke() function with 255 entered for the blue, green, and red parameters.

3. Drawing a line that moves from the left-hand side of the TFT screen to the right-hand side by repeatedly:

a. Changing the color of the point to white.

b. Drawing a point to the TFT screen at x,y position (i,20). The variable i will range from 0 to the width of the TFT screen.

c. Suspending program execution for 50 milliseconds.

4. Erasing the line that was drawn in step 3 by repeatedly:

a. Changing the color of the point to black.

b. Drawing a point to the TFT screen at x,y location (i,20). The value of i will range from the width of the TFT screen to 1. This will have the effect of erasing the white line drawn in step 3 and making the line appear to move back to the left of the screen.

c. Suspending execution of the program for 50 milliseconds.

5. Suspending execution of the program for 3 seconds. See Listing 8-7.

The WriteFile() function tests the SD card attached to the back of the TFT screen by:

1. Clearing the TFT screen and setting the background color to black.

2. Setting the color of the text on the TFT screen to white.

3. Printing a message that a file is being written to the SD card on the TFT display and to the Serial Monitor.

4. Removing that file and printing the result to the TFT screen and to the Serial Monitor if the file to be written already exits.

5. Opening the file for writing.

6. If the file has been opened successfully for writing, then:

a. Writing text and data to the opened file.

b. Closing the file.

c. Printing a text message indicating that the file was written to the TFT screen and to the Serial Monitor.

7. If the file was not opened successfully, then printing out a text message to the TFT and Serial Monitor indicating that there was an error when opening the file for writing.

8. Suspending program execution for 3 seconds. See Listing 8-8.

The ReadFile() function reads the data from the file written by the WriteFile() function and displays these data on the TFT screen and the Serial Monitor by:

1. Clearing the TFT screen and setting the background color to black.

2. Setting the text color to white.

3. Printing text to the TFT screen and the Serial Monitor indicating the test file is about to be read from the SD card.

4. Opening the file on the SD card for reading.

5. If the opening was successful, then while there is more data in the file:

a. Reading in a byte from the file.

b. Writing the byte to the Serial Monitor.

c. Writing the byte to the TFT screen.

6. Closing the file.

7. Printing text error messages to the TFT screen and the Serial Monitor if the file fails to open for reading.

8. Suspending execution of the program for 6 seconds. See Listing 8-9.

The DisplayEndScreen() function displays the program end screen by:

1. Clearing the TFT screen and setting the background to black.

2. Setting the text color to white.

3. Printing the text The End on the TFT screen and the Serial Monitor. See Listing 8-10.

The loop() function contains the main demo code and:

1. Loads the test bitmap image from the SD card and displays the image on the TFT screen by calling the LoadTestImage() function.

2. Draws a series of lines across the TFT screen by calling the DrawLines() function.

3. Draws a moving rectangle across the TFT screen by calling the DrawRectangle() function.

4. Draws a moving circle across the TFT screen by calling the DrawCircle() function.

5. Draws a moving line across the TFT screen by calling the DrawPoint() function.

6. Writes a file to the SD card called TestF.txt by calling the WriteFile("TestF.txt") function.

7. Reads and displays the content of the file TestF.txt that was written in step 6 by calling the ReadFile("TestF.txt") function.

8. Displays the end-of-program message on the TFT by calling the DisplayEndScreen() function.

9. Enters an infinite loop that permanently suspends the program. See Listing 8-11.

Running the Program

Before starting the program, you will need to select or create a bitmap or bmp image file and save it to a micro-SD card with the filename testbmp.bmp. Put this micro-SD card in the SD card reader/writer on the back of the TFT display. Upload the program to the Arduino, and start the Serial Monitor.

The first screen on the TFT display should be a text message indicating that the program has started (Figure 8-4). Next, the program loads a bitmap image from the SD card and displays it on the TFT screen (Figure 8-5). Then a series of lines is drawn to the TFT screen (Figure 8-6). Next, the program draws a blue or red rectangle to the TFT screen.


Figure 8-4

The start screen.


Figure 8-5

Loading and displaying a bitmap image from the SD card.


Figure 8-6

Drawing lines to the TFT screen.

On some TFT screens, such as the one I have, the red and blue colors are reversed. For example, the color of the rectangle is set by the fill() function, which the official documentation says has the parameters of fill(red, green, blue), with the parameter values ranging from 0 to 255. However, on my version of the TFT screen, the first parameter sets the blue color. This is most likely due to a mistake by the hardware manufacturer. There are many different manufacturers of hardware for the Arduino, so this is not surprising. Thus the following function call sets the rectangle to the color blue on my TFT display, but it is supposed to set the color to red (Figure 8-7):


Figure 8-7

Drawing a moving rectangle to the TFT screen.

TFTScreen.fill(255,0,0);

Now, a green circle is drawn on the TFT screen. The green circle starts off on the left-hand side of the screen and then moves to the right-hand side and then back again (Figure 8-8). Then a series of points is drawn to the screen, and they form a line starting on the left-hand side of the TFT screen and moving to the right-hand side and then moving back (Figure 8-9). Now the screen should indicate that a file is being written to the SD card using the SD card reader/writer attached to the back of the TFT display (Figure 8-10). Then the program will read and display the contents of the file from the SD card that was just written on the TFT screen (Figure 8-11). Finally, the program ends and displays a text message that the program has ended (Figure 8-12).


Figure 8-8

Drawing a moving circle to the TFT screen.


Figure 8-9

Drawing points to form a line.


Figure 8-10

Writing a test file to the SD card.


Figure 8-11

Reading the test file from the SD card.


Figure 8-12

The End.

Hands-on Example:
Arduino TFT Display Door Entry Alarm with SD Card Logging

This hands-on example project can be easily modified into a full door entry alarm system that detects the opening of a door, logs the number of entries to an SD card, and then displays the status of the alarm on a TFT LCD display. The alarm has a “waiting” state where the alarm cannot be triggered and is designed for a user to be able to set the alarm and then leave the home without the alarm going off. The “waiting” state is followed by the “active” state, where the alarm will detect the presence of a magnet. If a magnet is detected, the alarm state changes to “tripped.” The alarm can be reset to the “waiting” state by pressing a button.

Parts List

To build this hands-on example project, you will need

1 Arduino TFT LCD display with SD card reader/writer

1 micro-SD card

1 reed switch

1 push button

1 10-kΩ resistor

1 breadboard (needed to hold the TFT LCD display)

1 Arduino Uno (Connection instructions for this hands-on example project are specifically designed for the Arduino Uno.)

Wires to connect the components to the Arduino

Setting Up the Hardware

To build the hardware for this hands-on example project, you will need to:

Connect the 5-V pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the MISO pin on the TFT display to pin 12 of the Arduino Uno.

Connect the SCK pin on the TFT display to pin 13 of the Arduino Uno.

Connect the MOSI pin on the TFT display to pin 11 of the Arduino Uno.

Connect the LCD CS pin on the TFT display to pin 10 of the Arduino Uno.

Connect the SD CS pin on the TFT display to pin 4 of the Arduino Uno.

Connect the D/C pin on the TFT display to pin 9 of the Arduino Uno.

Connect the RESET pin on the TFT display to pin 8 of the Arduino Uno.

Connect the BL pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the GND pin on the TFT display to the GND pin of the Arduino Uno.

Connect the VCC pin on the reed switch to the 5-V pin of the Arduino.

Connect the GND pin on the reed switch to a GND pin of the Arduino.

Connect the DO pin on the reed switch to pin 7 of the Arduino.

Connect one terminal on the push button to a node that contains the 10-kΩ resistor and a wire to pin 6 of the Arduino. Connect the other end of the resistor to GND.

Connect the other terminal on the push button to the 5-V pin of the Arduino (Figure 8-13).


Figure 8-13

Arduino TFT door alarm.

Setting Up the Software

The program for this hands-on example project implements the alarm system by:

1. Including the SPI library so that the TFT display and SD card can be used:

#include <SPI.h>

2. Including the SD card library so that functions needed to read and write data to the SD card can be accessed:

#include <SD.h>

3. Including the TFT library so that functions related to drawing text on the TFT can be used:

#include <TFT.h>

4. Assigning the SD card reader/writer chip select pin to pin 4 of the Arduino:

#define sd_cs 4

5. Assigning the TFT LCD screen chip select pin to pin 10 of the Arduino:

#define lcd_cs 10

6. Assigning the DC pin on the TFT LCD screen to pin 9 of the Arduino:

#define dc 9

7. Assigning the Reset pin on the TFT LCD screen to pin 8 of the Arduino:

#define rst 8

8. Initializing the TFTScreen variable, which is a class object and represents the TFT screen, using the TFT constructor:

TFT TFTScreen = TFT(lcd_cs, dc, rst);

9. Initializing the LogFile variable, which is used to read and write the number of alarm trips to the SD card:

File LogFile;

10. Initializing the NumberTrips variable, which holds the total number of times the alarm has been tripped, including past alarm trips from previous power-ups:

int NumberTrips = 0;

11. Assigning the reed sensor output pin to pin 7 of the Arduino:

int SensorPin = 7;

12. Initializing the RawValue variable, which holds the input read from devices attached to the Arduino:

int RawValue = 0;

13. Initializing the AlarmState enumeration, which holds the different states that the alarm can be in:

enum AlarmState
{
Waiting,
Active,
Tripped
};

14. Initializes the CurrentAlarmState variable, which holds the current state of the alarm system and is initialized to the Waiting state:

AlarmState CurrentAlarmState = 
  Waiting;

15. Initializing the WaitStateTime, which holds the time in milliseconds that the alarm system stays in the Waiting state before it moves to the Active state. The default value is 5 seconds.

int WaitStateTime = 5000;

16. Assigning the ButtonPin variable, which is used to read in the status of the alarm’s reset button, to pin 6 of the Arduino:

int ButtonPin = 6;

The setup() function initializes the program by:

1. Setting the SensorPin pin of the Arduino (which is connected to the reed switch output) to be an input pin so that data can be read from the reed switch.

2. Setting the ButtonPin pin of the Arduino (which is connected to the push button) to be an input pin so that the status of the button can be read. If the voltage is high or 1, the button is being pressed. If the voltage is low or 0, the button is not being pressed.

3. Initializing the Serial Monitor and setting the communication speed to 9,600 baud.

4. Printing a text message indicating that the program has begun to the Serial Monitor.

5. Initializing the TFT LCD display.

6. Clearing the TFT screen and setting the background color to black.

7. Setting the TFT text color to white.

8. Printing a text message to the TFT screen indicating that the program is starting.

9. Suspending execution of the program for 3,000 milliseconds, or 3 seconds.

10. Printing a text message to the Serial Monitor indicating that the SD card reader/writer is being initialized.

11. Initializing the SD card reader/writer.

12. Printing a text message to the Serial Monitor indicating that the SD was not initialized if the SD card was not initialized successfully and then exiting the function.

13. Printing a text message to the Serial Monitor indicating that the SD card reader/writer was initialized successfully.

14. Read the total number of times the alarm has been tripped by calling the ReadLogFile("Log.txt") function, which reads the value from a file on the SD card named Log.txt.

15. Printing to the TFT screen the value read from step 14.

16. Printing to the Serial Monitor the value read from step 14.

17. Suspending execution of the program for 6 seconds. See Listing 8-12.

The WriteLogFile() function writes the total number of times that the alarm has been tripped to a file by:

1. Printing a text message to the Serial Monitor that the log file is about to be written to the SD card.

2. Deleting the log file from the SD card if a file already exists. Printing out the result of the attempt to remove the existing file from the Serial Monitor.

3. Opening the file for writing.

4. If the file was successfully opened for writing, then:

a. Converting the total number of alarm trips from an integer to a string type and then writing the value to the SD card.

b. Closing the file.

c. Printing a text message to the Serial Monitor that the writing of the file has been completed.

5. Printing a text message to the Serial Monitor indicating that opening the file failed if the file was not successfully opened for writing. See Listing 8-13.

The ReadLogFile() function reads the number of total times the alarm has been tripped by:

1. Opening the log file on the SD card for reading.

a. If the log file was successfully opened for reading, while there are more data to read from the file, reading one byte of data and storing it in the character array called Data indexed by the variable i.

b. Incrementing the array index variable i by 1.

2. Closing the log file.

3. Converting the characters in the character array called Data into an integer by calling the atoi() function and storing the result in the variable NumberTrips. The atoi() function is a standard C library conversion function.

4. Printing a text error message to the Serial Monitor if the log file was not successfully opened for reading. See Listing 8-14.

The ProcessWaitingState() function processes the Waiting state of the alarm by:

1. Clearing the TFT screen and setting the background color of the standard TFT display to red = 0, green = 255, and blue = 255. However, for some TFT screens, the red and blue inputs are switched, which is most likely due to manufacturer error.

2. Setting the color of the text to black.

3. Displaying text to the TFT screen indicating that the alarm is in the Waiting state.

4. Suspending execution of the program for WaitStateTime milliseconds.

5. Reading the total number of alarm trips from the log file by calling the ReadLogFile("Log.txt") function with the log file name Log.txt.

6. Clearing the TFT screen and setting the background to green.

7. Printing text to the TFT screen indicating that the alarm is now active and printing the total number of times the alarm has been tripped (which was read in from the log file in step 5). See Listing 8-15.

The loop() function implements the alarm system by repeatedly (in an infinite loop):

1. Reading the status of the alarm reset button.

2. Changing the alarm status to Waiting and printing a text message to the Serial Monitor that the alarm is now in the Waiting state if the alarm reset button is being pressed.

3. If the current alarm state is Waiting, then processing this state by calling the ProcessWaitingState() function. After this function completes, setting the current alarm state to Active.

4. If the current alarm state is Active, then:

a. Reading the state of the reed switch sensor.

b. If the reed switch sensor detects a magnet, the alarm has been tripped, so increasing the total number of alarm trips by 1.

c. Setting the current state of the alarm to Tripped.

d. Printing the status of the alarm to the Serial Monitor.

e. Clearing the background of the TFT screen and setting it to red (on my TFT).

f. Setting the TFT text color to white.

g. Writing a text message to the TFT screen indicating that the alarm has been tripped.

h. Writing out a log file that updates the total number of times that the alarm has been tripped by calling the WriteLogFile("Log.txt") function. The Log.txt is the file to write to. See Listing 8-16.

Running the Program

The first thing to note is that on some TFT screens such as mine, the red and blue colors are switched so that when I set the color for blue on my TFT screen, it actually shows up as red. This is most likely a problem with the hardware. Upload the program to your Arduino. You should see the text screen come up on the TFT indicating the program is starting. Next, the alarm should go into the Waiting state (Figure 8-14).


Figure 8-14

The Waiting alarm state shown on the TFT LCD display.

Next, the alarm moves into the Active state, and the total number of alarm trips is displayed. As you trip and reset the alarm, the number of alarm trips should increase. In Figure 8-15, the alarm is in the Active state and has been tripped a total of 22 times.


Figure 8-15

The Active alarm state shown on the TFT LCD display.

Now bring a magnet close enough to the reed switch that the alarm can be activated. When the alarm is activated, the TFT screen should display the alarm-tripped message (Figure 8-16).


Figure 8-16

The Tripped alarm state shown on the TFT LCD display.

To change this hands-on example project into a working door entry alarm, you would change the alarm to detect the absence of a magnet instead of the presence of a magnet. What you would do is place the reed switch sensor on the door and the magnet on the door frame so that when the door is closed, the magnet would be detected. When the door is open, the magnet would not be detected by the reed switch, which will trigger the alarm.

Arduino Cameras

The two best cameras for the Arduino are the Omnivision OV7670 FIFO camera and the ArduCAM OV2640 minicamera. The OV7670 comes in two main versions, one with first in, first out (FIFO) frame buffer memory and one without any memory. If you are using the camera with the Arduino, then you will need the version with the FIFO memory. The OV7670 is complex to operate and requires an Arduino Mega to use in order to take a picture and save it on an SD card. The benefit over the ArduCAM mini is that it costs around $9 to $10 dollars, which is less than half the cost of the ArduCAM mini, which is around $25 as of this writing. You can learn more about how to use this camera in a book I wrote called Beginning Arduino OV7670 Camera Development, which covers the most popular version, the FIFO version, of the OV7670. The ArduCAM OV2640 costs more than the OV7670 but is much easier to use and only requires an Arduino Uno to take a picture and save it on a SD card. The maximum resolution of the ArduCAM mini is also higher than that of the OV7670. The projects in this book use the ArduCAM OV2640 minicamera.

ArduCAM OV2640 Minicamera

The ArduCAM OV2640 minicamera includes

2MP image sensor

I2C interface for sensor configuration

SPI interface for camera commands and data stream

5-V/3.3-V-tolerant input-output (I/O) ports

Support for JPEG compression mode, single- and multiple-shoot mode, one-time capture multiple-read operation, burst read operation, low-power mode

Good mating with standard Arduino boards

An open source code library for Arduino, STM32, Chipkit, Raspberry Pi, and BeagleBone Black

Small form factor

Power supply at 5 V, 70 mA

Low power mode at 5 V, 20 mA

Frame buffer of 384 kB

Resolution support for UXGA, SVGA, VGA, QVGA, CIF, and QCIF

Image format support for RAW, YUV, RGB, and JPEG (Figure 8-17).


Figure 8-17

ArduCAM OV2640 minicamera.

ArduCAM Minicamera Library Software Installation

To use the ArduCAM minicamera with your Arduino, you will need to download and install the ArduCAM libraries from the ArduCAM website: www.arducam.com. Once you have downloaded the zip file, you will need to uncompress it using a program such as 7-Zip and install the two directories ArduCAM and UTFT4ArduCAM_SPI under the libraries directory for Arduino. For example, on my Windows XP system, I have installed the ArduCAM libraries in my Program Files/Arduino/libraries directory by copying the two directories to this libraries directory. After doing this, you should be able to compile source code that includes the ArduCAM library. For the example projects in this book, I used version 3.4.7 of the ArduCAM library, which was released on August 8, 2015.

The Memory Saver Include File

Change the memorysaver.h include file located in the ArduCAM library directory so that the following line is uncommented:

#define OV2640_CAM

This includes the camera register information needed for the ArduCAM OV2640 mini camera.

Hands-on Example:
Arduino ArduCAM OV2640 Mini Portable Programmable Digital Camera System

In this hands-on example project, you will learn how to build a portable programmable camera system using an ArduCAM OV2640 minicamera. You will be able to take a picture by pressing a button that will automatically save the captured image to an SD card. The status of the camera system will be displayed on the TFT screen. This example can serve as a basis for your own custom projects in areas such as security, surveillance, wildlife photography, time-lapse photography, and Internet of things.

Parts List

To build this hands-on example project, you will need

1 Arduino TFT LCD display with SD card reader/writer

1 micro-SD card

1 Arduino Uno

1 or more breadboards for the TFT display, Arduino camera, etc.

1 push button

1 10-kΩ resistor

1 ArduCAM OV2640 minicamera

Setting Up the Hardware

To connect the hardware for this hands-on example project, you will need to:

Connect the 5-V pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the MISO pin on the TFT display to pin 12 of the Arduino Uno.

Connect the SCK pin on the TFT display to pin 13 of the Arduino Uno.

Connect the MOSI pin on the TFT display to pin 11 of the Arduino Uno.

Connect the LCD CS pin on the TFT display to pin 10 of the Arduino Uno.

Connect the SD CS pin on the TFT display to pin 4 of the Arduino Uno.

Connect the D/C pin on the TFT display to pin 9 of the Arduino Uno.

Connect the Reset pin on the TFT display to pin 8 of the Arduino Uno.

Connect the BL pin on the TFT display to the 5-V pin of the Arduino Uno.

Connect the GND pin on the TFT display to the GND pin of the Arduino Uno.

Connect the CS pin on the ArduCAM to pin 7 of the Arduino Uno.

Connect the MOSI pin on the ArduCAM to the node on the breadboard that contains the MOSI pin from the TFT LCD.

Connect the MISO pin on the ArduCAM to the node on the breadboard that contains the MISO pin from the TFT LCD.

Connect the SCK pin on the ArduCAM to the node on the breadboard that contains the SCK pin from the TFT LCD.

Connect the GND pin on the ArduCAM to the GND node or GND pin of the Arduino Uno.

Connect the VCC pin on the ArduCAM to the 5-V node or 5-V pin of the Arduino Uno.

Connect the SDA pin on the ArduCAM to analog pin 4 of the Arduino Uno.

Connect the SCL pin on the ArduCAM to analog pin 5 of the Arduino Uno.

Connect one terminal on the push button to a node that consists of a 10-kΩ resistor and a wire that connects the node to pin 6 of the Arduino. Connect the other end of the resistor to GND of the Arduino Uno.

Connect the other terminal on the push button to the 5-V pin of the Arduino Uno (Figure 8-18).


Figure 8-18

Arduino TFT ArduCAM OV2640 minicamera system.

Setting Up the Software

The digital camera system presented in this hands-on example project is controlled by the software discussed in this section. An ArduCAM related library is included:

#include <UTFT_SPI.h>

The library relating to using the SD card reader/writer is included so that the SD card can be accessed:

#include <SD.h>

The Wire library is needed for the ArduCAM camera for the I2C interface portion of the camera:

#include <Wire.h>

The ArduCAM library is included so that the OV2640 minicamera can be used:

#include <ArduCAM.h>

The SPI library includes code relating to the Serial Peripheral Interface, which is needed for the TFT display, the SD card, and the ArduCAM camera:

#include <SPI.h>

The camera’s register settings are defined in the memorysaver.h file:

#include "memorysaver.h"

The TFT library is included so that the TFT display can be initialized and accessed:

#include <TFT.h>

Set pin 7 of the Arduino as the chip select pin for the ArduCAM minicamera. This pin on the Arduino is connected to the chip select input pin on the camera:

const int SPI_CS = 7;

Define the ArduCAM minicamera as myCAM, which is of camera type OV2640:

ArduCAM myCAM(OV2640, SPI_CS);

The ResolutionType enumeration holds the available camera image resolutions. The MAX enumeration means that the camera’s resolution is set to 1,280 by 1,024 pixels:

enum ResolutionType
{
 MAX,
 VGA,
 QVGA,
 QQVGA
};

The Resolution variable holds the current camera resolution. The default is set to VGA resolution. An image that is taken with the camera will be by default in VGA resolution:

ResolutionType Resolution = VGA;

The chip select pin on the SD card reader/writer is assigned to pin 4 of the Arduino Uno:

#define sd_cs 4

The chip select pin on the TFT display is assigned to pin 10 of the Arduino Uno:

#define lcd_cs 10

The dc pin on the TFT display is assigned to pin 9 of the Arduino Uno:

#define dc 9

The Reset pin on the TFT display is assigned to pin 8 of the Arduino Uno:

#define rst 8

The TFTScreen variable represents the TFT display and will display the status of the camera system:

TFT TFTScreen = TFT(lcd_cs, dc, rst);

The DataFile variable is used to write the image that is captured from the ArduCAM to the SD card:

File DataFile;

The ButtonPin variable is used to get the status of the button and is assigned to pin 6 of the Arduino Uno:

int ButtonPin = 6;

The status of the button is stored in the RawValue variable:

int RawValue = 0;

The ImageCount variable holds the number of images taken since the camera system was powered up and is set to the default value of 0:

int ImageCount = 0;

The ImageFileName is used to create the image filename based on the ImageCount variable:

String ImageFileName = "";

The FileName variable is a character array that holds the final image filename that will be saved to the SD card:

char FileName[10];

The OpenFileForWriting() function opens the image file that is to be written to the SD card by:

1. Setting the TFT screen background to black.

2. Setting the text color to white.

3. Printing text to the TFT screen stating that writing the image file to the SD card has started.

4. Printing text to the Serial Monitor stating that writing the image file to the SD card has started.

5. Removing the file and printing a notification text message to the TFT display and Serial Monitor if the file to be written already exists.

6. Printing an error message to the TFT screen and the Serial Monitor if an error occurs when trying to remove the file.

7. Opening the file for writing.

8. Printing a notification message to the TFT display and to the Serial Monitor if the file was opened successfully.

9. Printing an error message to the TFT display and to the Serial Monitor if the file was not opened successfully. See Listing 8-17.

The InitializeCamera() function initializes the ArduCAM OV2640 minicamera for operation by:

1. Initializing the I2C interface by calling the Wire.begin() function if __AVR__ is defined or by calling the Wire1.begin() function if __arm__ is defined.

2. Printing a text message to the Serial Monitor indicating that the ArduCAM camera is initializing.

3. Setting the SPI_CS pin on the Arduino to be an output pin. This pin is connected to the chip select input pin on the ArduCAM mini and is used to determine whether the camera will ignore or process the data coming from the SPI bus.

4. Initializing the Serial Peripheral Interface by calling the SPI.begin() function.

5. Checking whether the connection between the ArduCAM camera and the Arduino Uno is working correctly by writing 0x55 to the ARDUCHIP_TEST1 register on the ArduCAM minicamera, reading the register, and verifying that the returned value is 0x55.

6. If the values do not match, the SPI interface is not working, so printing an error message to the Serial Monitor and suspending execution of the program by entering an infinite loop.

7. Detecting the presence of the OV2640 camera specifically and printing the result to the Serial Monitor.

8. Setting the format of the images to be captured by the camera to JPEG format by calling the myCAM.set_format(JPEG) function with JPEG as the input parameter.

9. Initializing the ArduCAM OV2640 by calling the myCAM.InitCAM() function. See Listing 8-18.

The setup() function initializes the program by:

1. Initializing the Serial Monitor and setting the communication speed to 9,600 baud.

2. Printing a text message to the Serial Monitor indicating that the program has started.

3. Initializing the TFT display.

4. Setting the background color to black.

5. Setting the text color to white.

6. Printing a text message to the TFT display indicating that the program has started.

7. Initializing the camera by calling the InitializeCamera() function.

8. Setting the ButtonPin pin on the Arduino Uno as an input pin so that the status of the button can be read.

9. Printing a text message to the Serial Monitor indicating that the SD card is being initialized.

10. Printing an error message to the Serial Monitor if the SD card reader/writer did not initialize successfully and then exiting the function.

11. Printing a text message to the Serial Monitor indicating that the SD card reader/writer initialized successfully.

12. Printing text messages to the TFT display and the Serial Monitor that the camera system is ready to take photos. See Listing 8-19.

The CaptureImage() function captures an image to the ArduCAM minicamera’s frame buffer memory by:

1. Printing a text message to the Serial Monitor indicating that an image is being captured by the camera.

2. Resetting the FIFO frame buffer read pointer to 0 by calling the myCAM.flush_fifo() function. The frame buffer holds the captured image.

3. Clearing the flag that is automatically set after an image is captured by calling the myCAM.clear_fifo_flag() function.

4. Capturing an image by calling the myCAM.start_capture() function. This function will wait until the start of a new frame and then capture that frame to the FIFO frame buffer memory on the camera.

5. Printing a text message to the Serial Monitor indicating that the camera has started to capture an image.

6. Polling the camera continuously until the capture done flag has been set, indicating that the entire image has just finished being captured by the camera.

7. Printing a text message to the Serial Monitor indicating that the image has just finished being captured by the camera. See Listing 8-20.

The ReadFifoBurstWriteSDCard() function reads the image from the camera’s FIFO memory frame buffer and saves the image to a SD card using the SD card reader/writer attached to the back of the TFT display by:

1. Getting the length of the captured image in bytes by calling the myCAM.read_fifo_length() function.

2. Exiting the function if the length of the captured image is greater than or equal to the size of the FIFO frame buffer, which is 384 kB. This means that an error occurred while capturing the image, and the image was not found.

3. Printing the length of the captured image to the Serial Monitor.

4. Getting the current system time since power-up in milliseconds by calling the millis() function.

5. Setting the camera to recognize data from the Serial Peripherals Interface by calling the myCAM.CS_LOW() function. This function sets the voltage on the chip select pin on the camera to 0 or LOW.

6. Setting the FIFO memory to be read in burst mode by calling the myCAM.set_fifo_burst() function.

7. Reading in the dummy byte from the camera’s FIFO buffer to the Arduino Uno by calling the SPI.transfer(0x00) function.

8. Decreasing the counter that keeps track of the number of bytes needed to be read from the frame buffer by 1.

9. While there are still more bytes to read from the camera’s buffer, then:

a. Reading a byte from the FIFO frame buffer on the camera by calling the SPI.transfer(0x00) function and storing the result in the variable temp.

b. Disabling the camera from SPI operations by calling the myCAM.CS_HIGH() function, which sets the chip select pin on the camera to 1 or HIGH voltage.

c. Writing the byte to the SD card by calling the DataFile.write(temp) function with temp as the input parameter. Remember that temp holds the data that were just read from the camera.

d. Enabling the camera to use the SPI by calling the myCAM.CS_LOW() function. This sets the chip select pin on the camera to 0 or LOW voltage.

e. Setting the camera’s memory into FIFO burst mode by calling the myCAM.set_fifo_burst() function.

f. Increasing the bytecount variable by 1. This variable keeps track of the total number of bytes read from the camera’s memory.

g. Suspending execution of the program by 10 microseconds by calling the delayMicroseconds(10) function with input parameter 10.

10. Disabling the camera from using the SPI by calling the myCAM.CS_HIGH() function, which sets the chip select pin on the camera to 1 or HIGH voltage.

11. Closing the image file that was just written by calling the DataFile.close() function.

12. Printing the total number of bytes written to the file to the Serial Monitor.

13. Printing the total time in milliseconds that it took to write the image file to the SD card. See Listing 8-21.

The SetCameraResolution() function sets the camera resolution based on the Resolution variable by:

1. Changing the camera resolution to 160 by 120 pixels if Resolution is set to QQVGA.

2. Changing the camera resolution to 320 by 240 pixels if Resolution is set to QVGA.

3. Changing the camera resolution to 640 by 480 pixels if Resolution is set to VGA.

4. Changing the camera resolution to 1,280 by 1,024 pixels if Resolution is set to MAX.

5. Printing an error message to the Serial Monitor if Resolution is none of the preceding values. See Listing 8-22.

The loop() function contains the main program code for this camera system and in a continuous loop:

1. Reads the status of the push button.

2. If the button is pressed, then:

a. Prints a text message to the Serial Monitor indicating that the camera is now taking a photo.

b. Sets the background color of the TFT screen to red on my TFT or blue on a standard TFT display.

c. Sets the text color to white.

d. Displays text on the TFT screen indicating that the camera is now taking a photo.

e. Sets the camera resolution to VGA by setting the Resolution variable to VGA and then calling the SetCameraResolution() function.

f. Captures an image using the camera by calling the CaptureImage() function.

g. Increases the number of photos taken by 1.

h. Creates the filename for the photo by concatenating the number of photos taken and the .jpg file extension.

i. Creates and opens a file with the filename from step h for saving the image by calling the OpenFileForWriting(FileName) function.

j. Reads the image data from the camera’s FIFO frame buffer and saves this image data to the file that was opened in step i by calling the ReadFifoBurstWriteSDCard() function.

k. Prints text to the TFT screen indicating that the image file has been saved to the SD card. See Listing 8-23.

Running the Program

Upload the program to your Arduino, and start the Serial Monitor. The startup message indicating that the program has begun should be printed to the Serial Monitor:

TFT ArduCAM Test ...

The ArduCAM should be initializing, and the OV2640 mini camera should be detected:

ArduCAM Starting ..........
OV2640 detected ...........

Next, the SD card is initialized, and a message should be printed to the Serial Monitor indicating that the SD has been initialized successfully:

Initializing SD card...SD Card Initialization OK ...

In addition, a message should be displayed on the Serial Monitor and the TFT screen indicating that the camera system is ready to take a photo and save it to the SD card:

Ready To Take Photo...

To take a photo, press the button. You should see messages on the Serial Monitor indicating that a photo is being taken by the camera:

Taking Photo ...
... Starting Image Capture ...
Start Capture

When the capture is completed, the following message should appear:

Capture Done!

Now the image is written to the SD card. If a file with the same filename already exists, then that file is deleted and a new image file is written. The length of the image file in the FIFO memory, the final size of the file that is written, and the total time to write the file are also displayed on the Serial Monitor:

Writing File...
Removing file ...
File Opened... 1.jpg
READ_FIFO_LENGTH() = 9216
ByteCount = 9215
Total time used:615 milliseconds ...

This file should now be saved on the SD card. Turn off the Arduino, and remove the SD card. Read and display the image file on the SD card using your computer. An example image from the camera I took is shown in Figure 8-19. Another image I took using the camera system is shown in Figure 8-20.


Figure 8-19

Image taken with the ArduCAM OV2640 camera system.


Figure 8-20

Image taken with the ArduCAM OV2640 camera system.

Summary

This chapter has covered the TFT display with SD card reader/writer and the ArduCAM OV2640 minicamera. First, we discussed the TFT display, and then we provided a hands-on example project demonstrating the features of the TFT display and the attached SD card reader/writer that is located on the back of the display. You learned how to display text and display and animate lines, rectangles, circles, and points using the display. You also learned how to read and write files using the SD card reader/writer. Next, a hands-on example project used the TFT display, the SD card, and a reed switch to create a door entry alarm system. Then we discussed the ArduCAM OV2640 minicamera. This was followed by a hands-on example where this camera was used as part of a larger camera system by which you could take a picture and save it to an SD card by pressing a button.