Intro: Arduino TFT Color Clock
You may be familiar with a website in the UK called Colour Clock (http://thecolourclock.co.uk/) which converts the time into a hex value and then uses that value to update the background color. It's very hypnotic and once you get used to how it works you can actually tell where you are in the day just by glancing at the screen from across the room.
I had an Arduino Uno R3 and an Adafruit 1.8" Color TFT Shield w/microSD and Joystick that I was trying to use for another project that kept stalling out. One night just for fun I decided to see if I could recreate the Colour Clock and it only took a couple hours. If you're familiar with Arduino you could easily swap parts out for a simple TFT breakout board and something tiny like a Beetle and make a very compact unit. You could even wear it as a badge.
I made use of the Adafruit GFX Library which made getting things set up a breeze. I already had mine working and understood how to use the library a little so your results may vary depending on your experience. At first I would just type the current time into the code and sync, but with the addition of a real time clock the project will remember what time it is and spring to life every time you power it up.
- Arduino UNO R3 (or clone, or something similar if you're crafty)
- Adafruit 1.8" Color TFT Shield w/microSD (or compatible, the larger the better!)
- DS3231 RTC (Real Time Clock) module (more accurate than DS1307
- Jumper wire (or jumpers with Dupont connectors)
- Soldering Iron
Step 1: The Hardware
The TFT shield comes with some assembly required. You need to attach the header pins which I usually do by first inserting them in the corresponding holes on the Arduino, then setting the shield in place and flowing with solder. Use a fine tip soldering iron and fine filament solder for best results. Apply just a little heat to the top of the pin and gently touch the solder to the pin (not the iron) until it starts to flow. Very quickly you'll have a tiny pool of solder around the pin. Lift the solder and iron and let it cool. Repeat until all the pins are done.
With that out of the way your shield is already installed on your UNO. Click through to attach the RTC and add a jumper to be able to adjust brightness.
Step 2: The Peripherals
This isn't so much a peripheral as an option. If you solder a little jumper between pin 5 and the BC pin. That lets you AnalogWrite to pin 5 to set the screen brightness from 0 to 255. More on that later.
To attach the RTC module I happened to have some jumper cables with Dupont connectors, female on one end and male on the other. These are great for connecting to peripherals or breadboards. I just slid the female ends on the appropriate four pins on the RTC and then soldered the other ends to the TFT shield. Each pin has a hole next to it that it's tied to so you don't have to solder right to the pin. I'm not going to put mine in a case. It'll probably get pulled apart in a month to become something else. For now I'm going to rest it in a business card holder on my desk at work so I came off the front. You could just as easily go to the back of the UNO or even add some screw terminals for easy changes.
Pins used are:
- SCL - Clock Line - to Arduino Pin A5
- SDA - Data Line - to Arduino Pin A4
- VCC - 5 Volts - to Arduino 5v Pin
- GND - Ground - to Arduino Gnd Pin
Because the clock is the only device using the I2C bus in this project, pull up resistors aren't needed. While the UNO R3 has pins over by the ARef pin for I2C, they really just connect to A4 and A5 so it doesn't matter that the shield doesn't bring them up to the top level, we'll just go straight to the source.
Now that it's all built it's just a matter of loading the code and we're off to the races.
Step 3: The Code
Some of the code comes directly from the example sketches that came with the shield and RTC module. The rest was cooked up by yours truly and heavily commented for your ease of use. The one thing you will need to watch out for is the different ways you can set up for the TFT screen. It's also available as a simple breakout board (without the joystick or SD card reader) and the pinout is different for that. There are also multiple versions of the shield which are indicated by the color of the tab on the screen protector. Mine came with a green tab but only worked with the black tab code line enabled. You'll just have to try a few things out to get yours working. Refer to the example sketches for help.
You'll need to include the following libraries:
Make sure you have those downloaded and installed in the IDE before you get going. The first three have to be in that exact order or you'll get compile errors. I was stumped for quite a while before I found that little tidbit in a forum somewhere.
I'll explain the code a little. To pick a color to use on the screen you have to use a 16 bit hex value but it's in a weird configuration that's a little hard to understand at first. It's called 565 color and that's because the green value is treated differently. There's five bits for red and blue but because your eye is more sensitive to green it uses 6 bits for that. So you have 16 values for red and blue, and 32 values for green. But that's not all. The lowest value is actually zero so the highest value is actually 15 or 31.
While you can get out a hex chart and do some converting it's sort of cumbersome to be constantly typing in color values in hex like 0xFFFF for white (you can declare some color values, see the top of the sketch) the GFX library provides a nice little function to take care of things for you using values from 0 to 255.
What the time portion of the sketch does is take the hour value and use the map function to convert 24 hours, 60 minutes, and 60 seconds to values ranging from 0 to 255. Then it plugs those variables into the tft.Color565 function and it takes care of coming up with the hex value. Hours give the red value, minutes the green, and seconds the blue.
redValue =map(hour(t), 0, 23, 0, 255);
grnValue = map(minute(t), 0, 59, 0, 255);
bluValue = map(second(t), 0, 59, 0, 255);
tft.fillRect(0, 0, 160, 50, (tft.Color565(redValue, grnValue, bluValue)));
That's what the sketch uses to set the text and field colors. I messed around with eliminating the black bar and instead having the time appear in black with a clear text background but it was a little flickery. That's why the bar exists and it draws two rectangles of color instead of just filling the screen with color.
As for the colors you can get to know about where you are in the day or hour with just a quick glance.
Just after midnight it's very dark because the red value (hours) is zero and so are the blue and green (minutes and seconds). As the seconds tick off things get bluer and bluer until the minute ticks over and a tiny bit of green is added and the blue value resets to zero. When it's almost one AM things will be very green with the seconds taking things into teal as they creep up.
By lunch time there's a fair amount of red in play so things start to get a little more purple.
And by the end of the day, especially just before midnight things are very bright because all the values are very high at this point.
If you also have the shield with the joystick it's very easy to add some code to set the brightness. If you've gone the simple route you can just add two buttons to any two pins that can do a digitalRead. Use one to call the brightness function and then the other two for up and down. Hit select again to exit.
If you want to do away with buttons entirely you could either program the brightness depending on time of day, or use a photo sensor and control it with ambient light levels.
Here's the code:
Step 4: The Frills
I have a hard time leaving any project alone. I went ahead and added a little preferences menu that you access with the joystick. A press gets you into the menu and there you can select screen brightness by clicking left or right and 12 or 24 hour time by clicking up or down. Click again and your settings are saved to EEPROM so they're still there the next time you power up.
Here's The Code: [Edit] Corrected issue with first hour after midnight and leading zero in 12 hour mode.