Note: all files and sketches on M0IFA.me
What a struggle! These TFT displays are awkward to use. Especially when you want to display a clock face and hands that move round, or for that matter to write text/numbers on the display and update them. To move a hand you must delete the previous line you have drawn and draw a new one. BUT, you cannot let the second hand, as it moves round, delete the minute or hour hand as it passes by...
Same for the time. When the hours, minutes or seconds change you have to write a black box over the original number and then the new time. Fortunately the simple Adafruit font does this by allowing you to define both the font colour and the background colour. The negative side of using the simple font is that it is very blocky and only small sizes can be used.
MY CLOCK
This is my display. This TFT has 5V operation and I am running it quite happily on the Arduino Mega at 5V.
The TFT has an ILI9341 controller chip. This is supported by the Adafruit_GFX.h library with the driver Adafruit_ILI9341.h. This graphic library is not very extensive, but does have to simple things I needed, filled rectangles, circles, horizontal and vertical lines, sloping lines, print of numbers and text.
The interesting code for the clock hands is this:
- x, y = centre of hands
- r = radius of clock
- ch, h etc are the colours and hour, min, sec values
Typical usage may be
dispHands(110, 110, 100, WHITE, hrs, WHITE, mns, RED, sec);
This is the function:
// HANDS
// display hands x, y, r, ch, h, cm, m, cs, s
void dispHands(int16_t x, int16_t y, int16_t r, uint16_t ch, uint8_t h, uint16_t cm, uint8_t m, uint16_t cs, uint8_t s) {
uint16_t rh, rm, rs; // hand lengths
static uint8_t xh, xm, xs; // prev hms data
// hand lengths, % of radius
rh = r * 60/100;
rm = r * 80/100;
rs = r * 90/100;
// proportional move of hour hand
h = h * 5 + m / 12.0; // 60 min / 12 hours, plus minutes / 12
// if hms change erase old hand
if (h != xh) {
tft.drawLine(x, y, x + rh * sin((6.282 * xh / 60.0)), y - rh * cos((6.282 * xh /60.0)), BLACK);}
if (m != xm) {
tft.drawLine(x, y, x + rm * sin((6.282 * xm / 60.0)), y - rm * cos((6.282 * xm / 60.0)), BLACK);}
if (s != xs) {
tft.drawLine(x, y, x + rs * sin((6.282 * xs / 60.0)), y - rs * cos((6.282 * xs / 60.0)), BLACK);}
// then draw current times
tft.drawLine(x, y, x + rh * sin((6.282 * h / 60.0)), y - rh * cos((6.282 * h / 60.0)), ch);
tft.drawLine(x, y, x + rm * sin((6.282 * m / 60.0)), y - rm * cos((6.282 * m / 60.0)), cm);
tft.drawLine(x, y, x + rs * sin((6.282 * s / 60.0)), y - rs * cos((6.282 * s / 60.0)), cs);
// remember current time
xh = h;
xm = m;
xs = s;
}
Just to run though it
1 comment:
Hello
I used your code for running my analog clock using a 2.8" ili9341 tft display. It works great and I thank you for the code. However, I found the precision for calculating the hour hand can be improved.
Your code:
h = h * 5 + m / 12.0;
tft.drawLine(x, y, x + rh * sin((6.282 * h / 60.0)), y - rh * cos((6.282 * h / 60.0)), ch);
My code:
H = h * 60 + m; (H is a uint16_t)
tft.drawLine(x, y, x + rh * sin((6.282 * H / 720.0)), y - rh * cos((6.282 * H / 720.0)), ch);
Explanation:
Dividing m(a uint8_t) by 12 results in a quantized value for the hour hand position for all minute times non-divisible by 12.
Post a Comment