Teensy 4.0 with Newhaven display

Status
Not open for further replies.

zogster

Active member
Hi,

I'm working on a project for my car that will show boost pressure, tyre data and oil temperature (also battery voltage) on a single touch screen display in the centre console.

I have a prototype almost complete, using a Nextion display and Teensy 4.0, which works pretty well but has a relatively narrow viewing angle, so I'm thinking of doing a new version with one of these daylight viewable Newhaven displays:

https://www.newhavendisplay.com/nhd43480272ftcsxnt-p-9568.html?number_of_uploads=0&action=send

Does anyone have experience of using these displays with a Teensy 4.0? Can I use the supplied Arduino libraries without complicaton?

I'm not very good at coding, btw, and tend to copy and adapt code rather than writing from scratch,

Pic attached of current project… I'd plan on doing the same thing as here, with a series of bitmaps to animate the boost gauge and LED bar graph for oil temp (not illuminated here), and text/number fields for the other data
 

Attachments

  • IMG_3515.jpg
    IMG_3515.jpg
    83 KB · Views: 549
Excellent displays. The capacitive versions (FT813) are more resistant: 3.5 ", 4.3" or 5 ". With options to be able to use them in sunlight conditions. I have recently been working on a modification of the library for gameduino, which works very well with the teensy 3.6, teensy 4 and teensy 4.1; taking advantage of the SDIO reader for multimedia management

GD23ZUTX

 
Looks good! You're making me wonder whether I should maybe just use a single background image, and animate a needle/pointer over the top of that. Might be easier than using a series of bitmaps of the whole gauge, which was the best way to put a good-looking gauge on the Nextion.

But I just need to first get a sense of how hard it will be to deal with the coding for any approach
 
If you use a series of bitmaps with the gauge at every angle (which I assume you mean), then you have to generate them, which means you already have to do a crap-ton of work. If you decide to add or change some feature, it's back to the drawing-board, so this is really not a very modular approach. In software, you want to make things as easy to change as possible, because there is virtually guaranteed to be a reason to do so sooner or later. If you decide the needle should look slightly different, you have to do it all over again.

I think you will spend less time figuring out how to draw the needle pointing in whatever direction you want, than sitting there in Photoshop or Gimp or whatever, creating an extremely long series of images with it pointing in all sorts of directions. Just think about how tedious that would be.

What you are really doing is figuring out how to draw and fill the needle once, and then filling it. In simple terms, you need three points to define a very narrow triangle, and then rotating those three points about the center of the gauge. After that, you fill the triangle.

To rotate the points, just google "code to rotate points in C++" and you'll find something like this.

It may be that whatever graphics library you use has a routine for drawing a filled polygon. If so, just use that, and Bob's your auntie. If not, you will have to draw the lines, and then fill the polygon. Since this is a triangle, you should be able to find the midpoint by averaging all three (x,y) coords, and then using whatever paint routine your library has to fill it.

I have not looked very far into this, but it looks like they have some example code that's very similar to what you're going for: https://www.ftdichip.com/Support/SoftwareExamples/FT800_Projects.htm#Example4

This particular screen has a graphics drawing language built-in, so fortunately all you have to do is send a series of instructions over the wire and it does most things for you.
 
The FT81x is a GPU, it has basic instructions, it can handle image files in the form of cells, assets, or direct (avi with audio, jpg or png). For example you can load two images (dial and needle); then, the rotation is a matter of simple math, the rest is done by the FT813, supported by the speed of the teensy 4 or 4.1 ...

 
Ah, but I've already done that particular crap-ton of work for my Nextion-based prototype! (If you use tools to batch process the graphics it actually isn't so bad… most of the work was in building the 3D model of the gauge. Export from Blender as a series of bitmaps, crop and scale…) W

But I take your point that drawing a needle isn't a big deal. I did actually take a quick look at that example, and my first impression was that it looked like it looked like an awful lot of code I couldn't really make much sense of to do something quite simple – but that was a first impression, and like I say I'm really not very proficient at coding. I mostly copy, paste and tweak till it works.

I guess it can't be that hard to figure out ;-)
 
Zogster we will see your progress, I suggest the capacitive screens with FT813 chip, the library supports both resistive and capacitive, I think that the capacitive ones support the continuous use of the touch panel much better, in addition to that they can be cleaned more easily, preserving their appearance for longer. The resistive touch film gets scratched with continuous use

This is the code adapted for the GD23ZUTX, the library is able to use the SDIO reader with the power of the SdFat beta library:

Code:
#include <GD23ZUTX.h>

//Aguja indicadora
  int Centro=400/2;  //AE8.png, 400x400 px, Centro=400/2
  float AnguloG=40;  //compensación para ajustar a la escala del dial
  float avance, rapidez;
//Aguja indicadora

void setup()
{
  GD.begin();

    GD.BitmapHandle(0);
    GD.cmd_loadimage(0, 0);
    GD.load("AE6.jpg");

    GD.BitmapHandle(1);
    GD.cmd_loadimage(-1, 0);
    GD.load("AE8.png");

  tacometro();
}

void loop(){}

float dato;

void tacometro()
{
  while(1){
  GD.Clear();

  GD.Begin(BITMAPS);
    GD.Vertex2ii(175, 10, 0);
  GD.End();

  GD.SaveContext();
  GD.Begin(BITMAPS);
    avance = (1.27*2)*dato;
    dato = dato + rapidez;
    if((AnguloG+avance)>=294){rapidez=-0.5;}
    if((AnguloG+avance)<=40){rapidez=0.5;}
    rotate_Center(DEGREES(AnguloG+avance), Centro);
    GD.cmd_setmatrix();
    GD.Vertex2ii(200, 38, 1);
    GD.cmd_loadidentity();
  GD.End();
  GD.RestoreContext();

  GD.SaveContext();
    GD.ColorA(100);  GD.ColorRGB(0,0,0); GD.printNfloat(405, 324, dato/10, 1, 29);  GD.ColorA(255);
    if (dato>=90){GD.ColorRGB(255,0,0);}else{GD.ColorRGB(255,255,255);}
        GD.printNfloat(400, 315, dato/10, 1, 29);
  GD.RestoreContext();
  
  GD.swap();}
}

static void rotate_Center(float a, int CXY)
{
  GD.cmd_translate(F16(CXY),F16(CXY));
  GD.cmd_rotate(a);
  GD.cmd_translate(F16(-CXY), F16(-CXY));
}
AE6.jpgAE8.png
 
Couple of quick questions, apologies if these are very basic…

I've downloaded the EVE Screen Editor software, which seems like it'll be pretty useful. (I'm Mac based, but do have a laptop for occasional Windows stuff).

•*It doesn't seem to offer Arduino export - is this a configuration issue, or do I have to export to one of the 'HAL 2.0 Projects' options (looks like a list of displays which I assume behave like the Newhaven displays) and adapt the code

• At a first look at code for several example projects, there's nothing in the void loop () part where I expected to see some kind of repeated process. How are these projects actually driving dynamic processes without something in the loop?

(I don't have a screen to try things out yet, btw. Just looking through resources and info by way of preparation)
 
Don't go the way that comes with most FT81x displays, it is very complex. The editor you mention is designed for another type of programming environment, nothing to do with the arduino IDE. The easiest route is to follow the development of the gameduino 23X. The GD23ZUTX library that I mentioned earlier, is based on the gameduino source code but modified to take advantage of the teensy 4, 4.1 or 3.6 SDIO reader, using the SdFat beta library.

Inside it you have many examples for the arduino environment, you just connect the TFT to the SPI 1 bus and voila, touch, TFT, GRAM will be available.
 
I have the display now and I'm just taking my first steps to get it working with the Teensy, with the code you kindly posted above.

I'm getting a lot of compilation errors though. Just the first couple look like this (there's more):

/Applications/Teensyduino.app/Contents/Java/hardware/teensy/../tools/arm/bin/arm-none-eabi-g++ -c -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=153 -DARDUINO=10813 -DARDUINO_TEENSY40 -DF_CPU=150000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -I/var/folders/hk/vs8rrqn51m111hbz8pc8dc4c0000gq/T/arduino_build_184882/pch -I/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/cores/teensy4 -I/Users/zog/Documents/Arduino/libraries/GD23ZUTX -I/Users/zog/Documents/Arduino/libraries/SdFat/src -I/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/SPI -I/Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/Wire /var/folders/hk/vs8rrqn51m111hbz8pc8dc4c0000gq/T/arduino_build_184882/sketch/Newhaven_display_test_1.ino.cpp -o /var/folders/hk/vs8rrqn51m111hbz8pc8dc4c0000gq/T/arduino_build_184882/sketch/Newhaven_display_test_1.ino.cpp.o
In file included from /Users/zog/Documents/Arduino/Newhaven_display_test_1/Newhaven_display_test_1.ino:1:0:
/Users/zog/Documents/Arduino/libraries/GD23ZUTX/GD23ZUTX.h:416:18: error: 'File32' has not been declared
byte loadSdFat(File32& archivo, void (*progress)(long, long) = NULL);
^
/Users/zog/Documents/Arduino/libraries/GD23ZUTX/GD23ZUTX.h:417:22: error: 'File32' has not been declared
void safeloadSdFat(File32& archivo);

Is this because the GD23ZUTX library is not properly installed?

That's my guess, as the errors all seem related to that library, and while I have added the library to the libraries directory it's not showing up as in installed library in Teensyduino… I'm now trying to follow the installation steps described on the GD23ZUTX Github page, which seems to say that there's a good deal more to getting the library installed than I've actually done so far
 
Quick update: I think I've solved that problem… I had installed the wrong version of the SdFat library. No compilation errors now

I don't have the screen working yet though, which maybe has to do with pin assignments? I'm looking at the GD23ZUTX library now to try and understand that
 
Hey, it's great that you already have your screen. Exactly what model do you have? Any link to know your screen?

For teensy 3.5 / 3.6 or 4 / 4.1 there is only one setting in the GD23ZUTX.h file that we need to fine-tune before proceeding. It shouldn't be complicated. Locate those lines within the file .h:

Code:
// *************** User editable line to select EVE TFT size
#define SizeFT813 35 // NHD: 7-7 ", 5-5", 43-4.3 ", 35-3.5", Riverdi: 51-5 ", 71-7", MO: 52-5 "BT815, MO: 53-5 "FT813
// *************** User editable line to select EVE TFT size

For 4.3 "NHD, must be:

Code:
#define SizeFT813 43

Adjust the wiring as follows:

Code:
MISO pin 12
MOSI pin 11
SCK pin 13
CS pin 10
GND GND
VCC 3.3V

BLGND GND
BLVCC 5V

We can connect the VCC line of the backlight to 3.3V, however the manufacturer recommends using 5V on that line, to significantly reduce the heat generated by the starter circuit of the LEDs. I should point out that the display has two independent VCC lines: the line near the spi pins must go to 3.3V, it powers the FT81x chip.

The furthest line is BLVCC, it can be connected to 3.3V or 5V

Waiting for your comments
 
It's working!

Thanks dude - yup, just made those changes in the library code and connected as specified, and I have the 'Hello world' example sketch working, so I know the Teensy is talking to the screen properly.

Just waiting for a Micro SD card module to arrive, and then I can try playing about with stuff using bitmaps, including the example you posted.
 
Upload some photos to browse the project you have in hand. You can build an SDIO reader for your teensy 4 with an SD-microSD adapter:

z8gmu7wtvswuciizg.jpg


9aysl5tr8c3hh7lzg.jpg


crb9akmvdwpv51tzg.jpg


i4qsslc1zpfrvxvzg.jpg
 
I adjusted the dial example to match the physical dimensions of the NHD-43 TFT.

Code:
#include <GD23ZUTX.h>

//Aguja indicadora
  int Centro=272/2;  //AE8.png, 400x400 px, Centro=400/2
  float AnguloG=40;  //compensación para ajustar a la escala del dial
  float avance, rapidez;
//Aguja indicadora

//Posición base dial
int PBX=104, PBY=0;
//Posición base dial

void setup()
{
   GD.begin();

    GD.BitmapHandle(0);
    GD.cmd_loadimage(0, 0);
    GD.load("AE6a.jpg");

    GD.BitmapHandle(1);
    GD.cmd_loadimage(-1, 0);
    GD.load("AE8a.png");

  tacometro();
}

void loop(){}

float dato;

void tacometro()
{
  while(1){
  GD.Clear();

  GD.Begin(BITMAPS);
    GD.Vertex2ii(PBX, PBY, 0);
  GD.End();

  GD.SaveContext();
  GD.Begin(BITMAPS);
    avance = (1.27*2)*dato;
    dato = dato + rapidez;
    if((AnguloG+avance)>=294){rapidez=-0.5;}
    if((AnguloG+avance)<=40){rapidez=0.5;}
    rotate_Center(DEGREES(AnguloG+avance), Centro);
    GD.cmd_setmatrix();
    GD.Vertex2ii(PBX+1, PBY+1, 1);  //104
    GD.cmd_loadidentity();
  GD.End();
  GD.RestoreContext();

  GD.SaveContext();
    GD.ColorA(100);  GD.ColorRGB(0,0,0); GD.printNfloat(PBX+141, PBY+180, dato/10, 1, 29);  GD.ColorA(255);
    if (dato>=90){GD.ColorRGB(255,0,0);}else{GD.ColorRGB(255,25  5,255);}
        GD.printNfloat(PBX+136, PBY+175, dato/10, 1, 29);
  GD.RestoreContext();
  
  GD.swap();}
}

static void rotate_Center(float a, int CXY)
{
  GD.cmd_translate(F16(CXY),F16(CXY));
  GD.cmd_rotate(a);
  GD.cmd_translate(F16(-CXY), F16(-CXY));
}

 

Attachments

  • AE6a.jpg
    AE6a.jpg
    79.6 KB · Views: 1,371
  • AE8a.png
    AE8a.png
    12.3 KB · Views: 1,337
Last edited:
Just tried that solution for the card reader, and I think it's pushing my soldering skills just a little too far, though I may try again with different wire.

I'd planned on using a DIY breakout board like thisScreenshot 2020-09-03 at 17.22.33.jpg ordered from JLCPCB (other tracks on reverse of board… I think if I get a 0.8mm thick board then that will sit easily enough between the Teensy and the header pins, and the SD interface pads will be easier to solder than loose wires
 
To clarify - the area bounded by the holes in the middle would be removed, to allow for the components on the underside of the Teensy 4
 
Certainly, the spacing between the pads meant that I will not weld all the wires together, I took my time to relax my pulse. I used the wires from an old IDE cable that was stored in the drawer and got the finer point soldering iron I could find at the hardware store.
 

Attachments

  • cable plano.jpg
    cable plano.jpg
    59.7 KB · Views: 106
  • cautin.jpg
    cautin.jpg
    54.8 KB · Views: 114
Making real progress here :)

I managed to get a Micro SD card adapter attached, and after a bit of fiddling with code have this:

I had a bit of trouble with alignment and centring of the needle, but I have an analogue input driving numerical and gauge data (using a simple pot for now), which is a big step

Nest step will be to sort out the serial/SPI stuff, with screen on SPI 1 and my RF module (CC1101) on SPI 2, and to implement a simple touch control to mute an audio warning signal
 
Thanks! I'd never have got this far without this thread ;-)

I've started on the next steps, but I'm having trouble getting both the CC1101 and the screen working with the Teensy at the same time. I now have sketches that work with both, but in each case they're using the main SPI bus… the route I'm taking is to use SPI1 (which I think is pins 0, 26, 1 and 27) for the second device - so far, I haven't been able to get the CC1101 working on that, so I may switch and try and put the screen on SPI1. (I think using two hardware SPI buses is best, as apparently the CC1101 communication is quite critical on timing to do the decoding of TPMS data that it does. My current working prototype, with a different screen, uses the TX and RX pins for touchscreen interface)
 
Thanks again! How could I modify this to make it work ono the SPI1 bus instead of the main SPI bus?

As per previous post, I used this to get a test interface working with my screen but after trying to roll the RF stuff into it also I think it may be easier to put the screen on SPI1 and leave the RF module on the SPI bus where I had it working correctly before.

After a
I adjusted the dial example to match the physical dimensions of the NHD-43 TFT.

Code:
#include <GD23ZUTX.h>

//Aguja indicadora
  int Centro=272/2;  //AE8.png, 400x400 px, Centro=400/2
  float AnguloG=40;  //compensación para ajustar a la escala del dial
  float avance, rapidez;
//Aguja indicadora

//Posición base dial
int PBX=104, PBY=0;
//Posición base dial

void setup()
{
   GD.begin();

    GD.BitmapHandle(0);
    GD.cmd_loadimage(0, 0);
    GD.load("AE6a.jpg");

    GD.BitmapHandle(1);
    GD.cmd_loadimage(-1, 0);
    GD.load("AE8a.png");

  tacometro();
}

void loop(){}

float dato;

void tacometro()
{
  while(1){
  GD.Clear();

  GD.Begin(BITMAPS);
    GD.Vertex2ii(PBX, PBY, 0);
  GD.End();

  GD.SaveContext();
  GD.Begin(BITMAPS);
    avance = (1.27*2)*dato;
    dato = dato + rapidez;
    if((AnguloG+avance)>=294){rapidez=-0.5;}
    if((AnguloG+avance)<=40){rapidez=0.5;}
    rotate_Center(DEGREES(AnguloG+avance), Centro);
    GD.cmd_setmatrix();
    GD.Vertex2ii(PBX+1, PBY+1, 1);  //104
    GD.cmd_loadidentity();
  GD.End();
  GD.RestoreContext();

  GD.SaveContext();
    GD.ColorA(100);  GD.ColorRGB(0,0,0); GD.printNfloat(PBX+141, PBY+180, dato/10, 1, 29);  GD.ColorA(255);
    if (dato>=90){GD.ColorRGB(255,0,0);}else{GD.ColorRGB(255,25  5,255);}
        GD.printNfloat(PBX+136, PBY+175, dato/10, 1, 29);
  GD.RestoreContext();
  
  GD.swap();}
}

static void rotate_Center(float a, int CXY)
{
  GD.cmd_translate(F16(CXY),F16(CXY));
  GD.cmd_rotate(a);
  GD.cmd_translate(F16(-CXY), F16(-CXY));
}

 
Also,I have tried to use both the display and cc1101 on the main SPI bus, with one using pin 10 for CS and the other pin 27, but so far I can’t get them working at the same time. Will post more details if I don’t make progress.
 
Status
Not open for further replies.
Back
Top