Jump to content

LCD cockpit displays


Recommended Posts

Having dabbled with arduinos and displays, I decided to have a go at making a cockpit display for when I get my mig144 up and flying.

Heres my first (successful) attempt on a 1” X 1” screen (not a mig display but just an exercise). Bear in mind that the colours look much better than a photo shows!unknown.jpg

It half crossed my mind to sell these displays pre programmed but decided lifes too short. If I share the info and other make them perhaps they would share their programmes too thus saving me time in the future????

Firstly you need to get a suitable display to connect to an arduino. One of the best you can get (correct me if im wrong) is a 1” by 1” 240 X 240 pixel resolution colour TFT such as:-

1.3" ST7789 240x240 SPI Colour IPS TFT LCD Screen Display STM32 Arduino UK STOCK

£5 off ebay. Very bright and clear display and good from all angles (some displays grey out at slight viewing angles)!

Obviously the size of the display has to be about right for the size of the plane. You can scale down the size whilst still using the same display and hide some of the border. Similarly you can go up in size too! There are loads of different size displays but many have differing connection, software requirements and performance!!

During development im using an arduino Uno but an arduino nano would be light enough to be part of the finished display for use in a plane!

Connections are simple

Display - Arduino

#01 GND -> GND

#02 VCC -> VCC (5V)

#03 SCL -> D13/SCK

#04 SDA -> D11/MOSI

#05 RES -> D8

#06 DC -> D7

#07 BLK -> Not connected

Link to comment
Share on other sites

20201119_214428[1].jpg

Software drivers are required and im using “Arduino_ST7789_Fast.h” for this display.

Normally, to display an image, the easiest way is to save the image as a .BMP and write this to the display from the code. Unfortunately this needs more memory than arduinos have and is slow. Even the large ATmega chips don’t have enough for a 240x240 colour display.

After many attempts including using sd cards as the memory I decided on doing it the hard but far superior way. Each display is drawn by software, built up of a series of blocks, lines, curves, text etc. A circle can be half covered up to make a semi circle etc. A circle can go off the side of the screen to make a semi circle! The advantage here is the screen can be painted black (one line of code) then bits added one or a few lines for each! You don’t need to waste a ton of memory that says for each pixel, black, black, black, black .......etc.

The other main advantage is speed. The above attitude/horizon display fires up in a fraction of a second. A bitmap being drawn takes many seconds. Another disadvantage of a bitmap is small details can be blurred between pixels as it most likely will not map accurately to the 240 x240 grid.

Drawing the display with code maps the elements directly to pixels giving a sharp image, particularly with small text. Limits however are that text sizes are set but as seen above, certainly not a major problem. Some artistic licence is needed re text size however!

Most of the above should make more sense as I build up the weather radar and explain what each line of code is doing! I wont claim that the software is super optimised but its simple to follow!

bnavk.jpg

I will emulate the above random picture off the web (not being a pilot I don’t know what display this is off but its a good exercise!!)

Link to comment
Share on other sites

I shall first draw the plane in yellow at the bottom of the screen with the below code

#define TFT_DC 7

#define TFT_RST 8

#define SCR_WD 240

#define SCR_HT 240

#include <SPI.h>

#include <Arduino_ST7789_Fast.h>

Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);

unsigned long res[16]; // initialisationrequired for the display

void setup(void) {

tft.init(SCR_WD, SCR_HT);

tft.fillScreen(BLACK); // fills screen black

tft.fillRoundRect(110, 210, 22, 2, 0, YELLOW); // draw yellow plane

tft.fillRoundRect(120, 205, 2, 22, 0, YELLOW);

tft.fillRoundRect(115, 222, 12, 2, 0, YELLOW); }

void loop() {

} // loop around endlessly having drawn screen

20201119_214317[1].jpg

Normally the main code is within the “loop” but I am doing it to run once in the “setup” section. Loop simply goes around in circles once the screens drawn!

With a numbering system that has 0,0 as top left to 240,240 as bottom right, the wings are drawn using a rectangle tft.fillRoundRect(110, 210, 22, 2, 0, YELLOW); from 110 across, 210 down, 22 long (l to r) and 2 wide (downwards). 0 is the radius of the corners of the rectangle but 0 just gives sharp corners!

Playing with the numbers will show the effect

The fus and tail are similarly done. It takes a while to tweak the values to get the lines where you want them!! The display printed out on a 240x240 paper grid helps here!

Next instalment when I get round to it ie when its too cold in the garage!

Link to comment
Share on other sites

To add the distance arcs, you draw circles centred on the yellow plane at 120, 215

// draw distance arcs

tft.drawCircle(120, 215, 45, WHITE);
tft.drawCircle(120, 215, 90, WHITE);
tft.drawCircle(120, 215, 135, tft.color565(255, 255, 255));
tft.drawCircle(120, 215, 180, tft.color565(255, 255, 255));

Note the two different ways to specify a colour. you can use the 16 std colours or custom by varying the rgb values. The three 255 values are red green blue values. When all three are 255 (max) this adds up to white. 0,0,0 is black with 16million options between!

20201121_185237[1].jpg

To truncate the inner two circles ive added triangles (shown blue for clarity)

20201121_185747[1].jpg

When two are drawn as a mirror of each other:-

//trim circles with black triangle
tft.fillTriangle(0, 170, 0, 240, 150, 240, BLACK );
tft.fillTriangle(240, 170, 240, 240, 90, 240, BLACK );

You get

20201121_193348[1].jpg

Next to make the arcs dashed

 

Edited By dave windymiller on 21/11/2020 19:47:18

Link to comment
Share on other sites

Me Too!

Dave, I was under the impression that all sketches started of with everything you wanted to happen once contained within the

void setup () { }

Now your sketch doesn't do that and I note that if I try to include the

#include "Arduino_ST7789_Fast.h"

inside the

void setup() { }

then it errors.......so - this errors

void setup() {

#define TFT_DC 7
#define TFT_RST 8
#define SCR_WD 240
#define SCR_HT 240
#include "Arduino_ST7789_Fast.h"
#include "SPI.h"
Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);
unsigned long res[16]; // initialisationrequired for the display

tft.init(SCR_WD, SCR_HT);
tft.fillScreen(BLACK); // fills screen black
tft.fillRoundRect(110, 210, 22, 2, 0, YELLOW); 
tft.fillRoundRect(120, 205, 2, 22, 0, YELLOW); 
tft.fillRoundRect(115, 222, 12, 2, 0, YELLOW); 


tft.drawCircle(120, 215, 45, WHITE); // draw distance arcs
tft.drawCircle(120, 215, 90, WHITE);
tft.drawCircle(120, 215, 135, WHITE);
tft.drawCircle(120, 215, 180, WHITE);
//tft.drawCircle(120, 215, 135, tft.color565(255, 255, 255));
//tft.drawCircle(120, 215, 180, tft.color565(255, 255, 255));

tft.fillTriangle(0, 170, 0, 240, 150, 240, BLACK ); //trim circles with black triangle
tft.fillTriangle(240, 170, 240, 240, 90, 240, BLACK );
}

void loop() {

}

But this compiles ok

#include  "Arduino_ST7789_Fast.h"


void setup() {

#define TFT_DC 7
#define TFT_RST 8
#define SCR_WD 240
#define SCR_HT 240
#include "SPI.h"

Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);
unsigned long res[16]; // initialisationrequired for the display

tft.init(SCR_WD, SCR_HT);
tft.fillScreen(BLACK); // fills screen black
tft.fillRoundRect(110, 210, 22, 2, 0, YELLOW);
tft.fillRoundRect(120, 205, 2, 22, 0, YELLOW);
tft.fillRoundRect(115, 222, 12, 2, 0, YELLOW); 


tft.drawCircle(120, 215, 45, WHITE); // draw distance arcs
tft.drawCircle(120, 215, 90, WHITE);
tft.drawCircle(120, 215, 135, WHITE);
tft.drawCircle(120, 215, 180, WHITE);
//tft.drawCircle(120, 215, 135, tft.color565(255, 255, 255)); 
//tft.drawCircle(120, 215, 180, tft.color565(255, 255, 255));

tft.fillTriangle(0, 170, 0, 240, 150, 240, BLACK ); //trim circles with black triangle
tft.fillTriangle(240, 170, 240, 240, 90, 240, BLACK );
}

void loop() {

}

Do you know why that is?

(I have changed the greater than and less than symbols to " because they don't display included text properly on this forum)

Edited By FlyinFlynn on 24/11/2020 11:36:11

Edited By FlyinFlynn on 24/11/2020 11:39:20

Link to comment
Share on other sites

Quick test to see if this forum supports code insertion

 

`

tft.drawCircle(120, 215, 90, WHITE);
tft.drawCircle(120, 215, 135, WHITE);
tft.drawCircle(120, 215, 180, WHITE);

`

It appears to not support it    which is a problem because any line with the 'greater than' and 'less than' symbols trunkate ....

Edited By FlyinFlynn on 24/11/2020 11:29:46

Edited By FlyinFlynn on 24/11/2020 11:32:53

Edited By FlyinFlynn on 24/11/2020 11:37:46

Link to comment
Share on other sites

The #include is not an executable instruction but a compiler directive. What it does is place the content of the included file in the code at the place of the #include statement prior to compilation.

The fact that one compiles and one does not is going to be due to the actual content of the file being included.

included files are going to be complete library functions and/or definitions and should never be inside your own functions. The fact that one compiles is not indicative that it will work.

Put all your includes outside and before the executable functions (void & setup) and all should be well.

Link to comment
Share on other sites

Re 3.3 or 5V

My original display was from here which stated 5V but further down the listing says "3.3-5V, (3.3V recommended)"!. Having since seen other identical displays stated as 3.3V i have found that running mine on 3.3V, it fails to start up reliably but is fine on 5V (powered by the usb lead).

This being said all the data lines would be at 5V but powered from the 3.3V pin of the arduino which may confuse it?. Maybe it would be better (from a longivety point of view?) on a 3.3V arduino but I have been playing with my display over a year and still it works!  I have seen postings that use resistors networks to drop the data lines from 5 to 3.3 but that didnt seem necessary in my case having already used 5V?

I read somewhere that the display has a voltage regulator on the back (u2 i presume). but cant say i delved any deeper.  Any info from others re this would be useful!

I had no intentions of posting on the arduino forum, with it being very model plane orientated!

 

Edited By dave windymiller on 24/11/2020 20:33:02

Link to comment
Share on other sites

Dave, not all +5v USB power supplies were created equal! I have what I would expect to be a quite typical setup with a 1.5M USB2 extension lead going between my PC, which is on the floor, and my workbench. If I meter out the USB supply I see 4.77v at the 5v pin on a nano connected via the extn lead. The 3v3 output however is always 3.3v. Perhaps others could meter their usb's out and comment?

I looked up the specs on the ST 7789 and it has an absolute operation range of Supply Voltage VDD - 0.3 ~ +4.6 V. Which I take to mean +4.3v to +4.6v. with the added note of - Note: If one of the above items is exceeded its maximum limitation momentarily, the quality of the product may be degraded. Absolute maximum limitation, therefore, specify the values exceeding which the product may be physically damaged. Be sure to use the product within the recommend range.

The chip specs also state the i/o voltage should be between 1.65v and 3.3v and be at or below the supply voltage so level shifting really should be employed

Half the offerings I looked at for these 240x240 IPS displays state 3v3 supply, the other half state 5v. So where does that leave us?....I suspect, as your experience suggests, providing your +5v is not too 'aggressive' it will work, at least for a while, it would appear however, to be out of spec.

I would liken it to people running single channel relay module directly off an arduino output pin... the specs say 40mA max but these relays consume ~46 - 55mA...and then when the arduino fails they complain about the unreliability of these cheap chinese arduinos.

I think I will be checking whether 3v3 will power my displays when they arrive and make a decision accordingly. I do have a supply of the quad level shifters available so if 3v3 doesn't drive the display ok I will be using my dodgy usb 5v and incorporating a level shifter for the logic..

Looking at the pictures it looks to me like the U2 is connected to the backlight pin via R2 so will be part of the backlighting level adjustment and nothing to do with the chip supply.

 

 

 

 

Edited By FlyinFlynn on 25/11/2020 10:24:40

Link to comment
Share on other sites

Thanks flyinfynn. Like you say some say 3.3V some say 5V.

I experimented today by powering an ardiuno nano (CH340 version) & display from a new 4.8v receiver pack and dropping the voltage using a couple of diodes. With one diode, 4.4V measured, the display and arduino fired up no problems and there was no noticeable brightness difference. With 2 diodes again it ran every time (3.7V measured) but you could see a slight dimming of the display. I think one diode would be a reasonable compromise and a simple thing to try if anyone is concerned about 5V!

You could alternatively use the volts from one cell of a lipo via the balance lead?

pb254251.jpg

Anyhoo

As you can see above the display has a bit more detail now added. To get the dashes i simply added black filled circles 3 pixel radius and manually moved them to get the right position by eyeball (initally coloured red to see them!). Start with the center one and work in one direction. Once one half is done, simply use 240 - (the first value) to get a matching spot on the opposite side!

// 2nd ring LHS
tft.fillCircle(38, 179, 3, BLACK);
tft.fillCircle(44, 168, 3, BLACK);
tft.fillCircle(52, 158, 3, BLACK);
tft.fillCircle(60, 149, 3, BLACK);
tft.fillCircle(70, 141, 3, BLACK);
tft.fillCircle(81, 134, 3, BLACK);
tft.fillCircle(93, 129, 3, BLACK);
tft.fillCircle(105, 127, 3, BLACK);

// middle
tft.fillCircle(120, 125, 3, BLACK);

// RH side same but values (for example)240-38 = 202
tft.fillCircle(202, 179, 3, BLACK);
tft.fillCircle(196, 168, 3, BLACK);
tft.fillCircle(188, 158, 3, BLACK);
tft.fillCircle(180, 149, 3, BLACK);
tft.fillCircle(170, 141, 3, BLACK);
tft.fillCircle(159, 134, 3, BLACK);
tft.fillCircle(147, 129, 3, BLACK);
tft.fillCircle(135, 127, 3, BLACK);

This is clearly non optimised/ crude programming (before anyone says!) but easy to do!

Ideally you would use trig to calculate where these spots go and have a routine to do it. If i was making many of these i would invest the time to make a routine to create dashed lines more elegantly. It took me ~90mins to do all three lines! Im sure someone with more programming skill can do it "correctly" in less time?

Thinking ahead, the weather will be drawn first (inserted prior to the code for the dashed lines) so the spots may show up on non black backgrounds so these can be changed to match the background as req!

The tick marks on the outer ring are done similarly (trial and error for one half!).

The text is manually placed eg

// White text
tft.setTextColor(WHITE); tft.setTextSize(1);

tft.setCursor(5,0);
tft.println("BS" ) ;

tft.setCursor(60,0);
tft.println("TAS" ) ;

tft.setCursor(180,0);
tft.println("BENIP" ) ;

tft.setCursor(35,15) ;
tft.println("/" ) ;

 

Notice how the text is horizontal not rotated as per original. Again it could be done with elegant software but not by me! Artistic license! Note the difference between size 1 and size 2 text!!

pb244246.jpg

Next is the weather. Not sure how best to do that yet with all those fuzzy edges!

ps i will gladly share the full code via email on request! (not put it on here, too long.

Dave

 

Edited By dave windymiller on 25/11/2020 21:20:46

Edited By dave windymiller on 25/11/2020 21:25:49

  • Like 1
Link to comment
Share on other sites

Hiya Nick. The displays use spi bus so it may possible to have multiple displays. Obviously the two display programs would have to fit into the arduino memory. Similarly, one display could display two images one after the other or switched memory permitting? For two displays I would have one arduino each and these could be connected by i2c bus to talk to each other if req. Lot of effort? Yes but interesting.

Link to comment
Share on other sites

Nick, the answer regarding multiple displays is probably.

The display does not use the i2c bus which would allow each display to have different address but uses SPI serial interface. Some st7789 devices have a chip select (CS) pin, with these devices you can connect multiple devices but only communicate with one at a time by setting the CS pin low on the target and high on the other(s).

At least that is the theory. I’ve never done this but understand the theory. Googling around there is a short video demonstration of an arduino controlling 2 displays, but no explanation of how. I also found an unanswered forum question where somebody had set up 2 displays but could not get them to work other than individually. Each worked on its own but neither worked when the other was plugged in. My immediate thought on this problem is that the arduino may not provide enough power from its VCC pin to control the additional display, but that is pure speculation.

Personally I think it should be perfectly possible but will need an understanding of how the library controls the CS pin, and may need to be powered other than by the arduino.

with regard to to processing capacity of the arduino, in the example of this thread the arduino is basically doing nothing most of the time. With static displays like this the arduino is drawing the display(s) then folding its arms. Even making the displays dynamic, the arduino will not be very busy and re-drawing is not time critical. This is basically a trivial loading for the arduino. As has already been said the only real limit is the programming space within the arduino. This is in practice quite significant, however it’s usage is affected very much by programming technique.

My advice would be get a few fly leads, and maybe a bread board so you can experiment with the wiring, and play. The help of somebody who understands C++ coding to use as a mentor would be very useful.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...