Making TFT thermometer
Just for fun I bought some arduino boards ( uno, nano, mini-pro in 8 and 16 MHz variations ) and some TFT displays ( in different sizes with different physical interface and different driver chips ) on ebay some month ago.
So far I soldered some funny things and little more serious things, like sensors with radio connecting to arduinos to openhab running on RPI, and sensors and radios to transmit data from car to another car, movement sensor with specific filtering algorithm, and IR receiver for make possible to enter PIN number for specific car alarm system, hardware of which praises my colleagues work. ( on picture 2 )
But now I only wanted to make a funny and good looking somthing. So you can see the result, and the steps for reaching it.
First of all, earlier I got some experience with adafruit libraries and arduino uno and displays with intel 8080 interface. That interface could be fast, but it needs you to use 8 + 5 pins for control the display that is too much. You hardly remain any pins to do anything apart from drawing on screen.
Display driver library hack
So, I have to try the SPI interface display. My SPI interfaced display equipped with ILI9341 driver which driver chip is cool and it has adafruit library. You can easily download from here:
https://github.com/adafruit/Adafruit_ILI9341
So okay, I soldering for some hours ( this part wasn't the coolest part of this job. ) This type of driver chip don't like 5V on its pins, so I had to solder level shifters. You can find some good example how to do this on the Net but some of them no so bright, my suggestion, you shouldn't use level shifter on MISO pin, and it isn't necessary to use on slave select pin too, and should use resistor 10-20 KOhm, less value isn't the correct way, because it waste huge amount of power (2-3 mA on every pins.... :D ).
And voálá the adafruit graphic test worked.
But, but and but..... the performance, it made me had a little bit headache. The maximum SPI bus frequency is half of the AVR CPU frequency, on a 16 MHz board it means 8 MHz which isn't so slow, but the result wasn't fast enough.
That is why, I started to modify the adafruit ILI 9341 driver class. Yeah I have to mention the adafriut libraries sometimes could be messy, but their principle is absolutely okay. The base class is the adafruit gfx class, which include the high level function, e.g. fill rectangle, draw line, draw circle and other base drawing algorithm, and they include some pure virtual method and some virtual method overriding them you can make your hardware specific library or you can override other method to make it faster or to meet your other requirement.
The key of the performance is the draw point and the draw line methods, most of the higher level drawing methods using them. For first glance in the draw pixel method, there are a lot of method calls ( which could be costly ) and there are some not so many important "if" conditions. So make methods inline ( yeah, it eats your program memory) and get rid of unnecessary "if"-s ( yeah, the more performance means the less safety ). So the first step of optimizing program was successful, I got about 40-50% performance advance.
From that point I spent several hours to optimize the code, and the result was enough. The results comparing than the original adafruit library.
|
Original library |
Modified library |
Rate of acceleration |
|
time (microsecond) |
time (microsecond) |
|
Screen fill |
1329592 |
2126428 |
1,60 |
Lines |
490184 |
2343420 |
4,78 |
Horiz/Vert Lines |
107596 |
179228 |
1,67 |
Rectangles |
69700 |
118828 |
1,70 |
Rectangles (filled) |
2761156 |
4416460 |
1,60 |
Circles (filled) |
449440 |
906852 |
2,02 |
Circles (outline) |
374788 |
1023996 |
2,73 |
Triangles (outline) |
126904 |
743428 |
5,86 |
Triangles (filled) |
1008036 |
1830952 |
1,82 |
Rounded rects (outline) |
150924 |
386084 |
2,56 |
Rounded rects (filled) |
3009676 |
4896456 |
1,63 |
There are several "fast" driver libs on the Net. I examined some of them, but I didn't find faster library than mine, but I am sure it exists somewhere. There is still some opportunities to get faster on the code. But of course they have their own cost.
If you use original adafruit library take care, the ILI9341 "driver" class has two constructors, the library uses hardware or software SPI mode depend on which constructor used to instantiate the class. Of course the software SPI is much slower.
So Finaly I have hardware and a good driver for it. I soldered a DTH11 sensor too. And wrote some code, it was easiest part of this little project. I drew a color arch to symbolize the temperature somehow, and a little chart bellow it.
In the chart, I can display the 24 hours data including 2 temperature and 1 humidity values in each point. The data is stored in eeprom, so the power break doesn't matter. I used a simple clever index algorithm which help to find the last stored data after power break. ( Consider that, this little circuit don't have real clock.) And of course I use circular buffer when use eeprom, so every address is written very rarely for lengthen its lifetime.
I will upload my modified library to GITHUB ASAP.
For test I fed it a simple sin. Yeah it's not a big deal, but consider it's only 8 bit RISC microcontroller runing on 16 MHz with 2 KByte RAM.