Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: ILI9341 CAN Display - Gauge rendering on display

  1. #1

    ILI9341 CAN Display - Gauge rendering on display

    Hi all,

    After spending months getting my automotive CAN BUS display working, I really want to beautify the UI and make it a bit more easier to read.
    My ultimate goal is to display two gauges in the display in place of the two main readouts (Boost & AFR) but I am really struggling with code on this part - I am clueless here.

    Here is what I have built so far:
    Click image for larger version. 

Name:	IMG_0990.jpg 
Views:	5 
Size:	69.7 KB 
ID:	18310

    What I would like to add is two gauge displays as can be seen below - One for boost, ranging from -30 inHg up to 30 PSI. the other is an Air fuel ratio ranging from roughly 8 to 22.
    Click image for larger version. 

Name:	defi.jpg 
Views:	7 
Size:	290.2 KB 
ID:	18311 Click image for larger version. 

Name:	aem_afr.jpg 
Views:	4 
Size:	41.5 KB 
ID:	18312
    As you can see, the boost gauge is not linear in its layout (90deg for vacuum, 180deg for boost - air fuel layout is roughly 270-300deg).

    Hardware being used is a Teensy 3.2 with a can transceiver and a 2.8" ILI9341 display.
    Im using FlexCan and ILI9341_t3 libraries to drive everything.

    My questions are:
    1. Is ILI9341_t3 capable of doing what I want?
    2. Will I be sacrificing process speed for refresh rate?
    3. Will the T3.2 be enough or should I upgrade to a T4.0?
    4. Can anyone help me with writing the code for the gauges or provide examples that I can modify?


    Cheers,
    David

  2. #2
    Senior Member
    Join Date
    Apr 2019
    Posts
    156
    Quote Originally Posted by Rezo View Post
    Hi all,

    After spending months getting my automotive CAN BUS display working, I really want to beautify the UI and make it a bit more easier to read.
    My ultimate goal is to display two gauges in the display in place of the two main readouts (Boost & AFR) but I am really struggling with code on this part - I am clueless here.

    Here is what I have built so far:
    Click image for larger version. 

Name:	IMG_0990.jpg 
Views:	5 
Size:	69.7 KB 
ID:	18310

    What I would like to add is two gauge displays as can be seen below - One for boost, ranging from -30 inHg up to 30 PSI. the other is an Air fuel ratio ranging from roughly 8 to 22.
    Click image for larger version. 

Name:	defi.jpg 
Views:	7 
Size:	290.2 KB 
ID:	18311 Click image for larger version. 

Name:	aem_afr.jpg 
Views:	4 
Size:	41.5 KB 
ID:	18312
    As you can see, the boost gauge is not linear in its layout (90deg for vacuum, 180deg for boost - air fuel layout is roughly 270-300deg).

    Hardware being used is a Teensy 3.2 with a can transceiver and a 2.8" ILI9341 display.
    Im using FlexCan and ILI9341_t3 libraries to drive everything.

    My questions are:
    1. Is ILI9341_t3 capable of doing what I want?
    2. Will I be sacrificing process speed for refresh rate?
    3. Will the T3.2 be enough or should I upgrade to a T4.0?
    4. Can anyone help me with writing the code for the gauges or provide examples that I can modify?


    Cheers,
    David

    I am assuming the gauges work using a voltage from a sensor

    you need to output the voltage from your T3.2 to drive them

    https://www.arduino.cc/reference/en/...o/analogwrite/


    you need to take the can data and convert it to the correct voltage to drive the gauge


    the map function may help you convert from one unit to another

    https://www.arduino.cc/reference/en/...ions/math/map/


    how did you get your can data from the ecu - e.g AFR and oil temperature ?

  3. #3
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,265
    Quote Originally Posted by Gadget999 View Post
    I am assuming the gauges work using a voltage from a sensor

    you need to output the voltage from your T3.2 to drive them

    ...


    you need to take the can data and convert it to the correct voltage to drive the gauge

    ...
    I think OP has all that sorted and wants to know how to animate the needle and draw a background image to the display... (I can't help with this)

    I did find this https://busy.org/@pakganern/oled-dis...ometer-arduino for a different display but at least some of the major graphics calls look compatable, e.g. .drawCircle()

    It doesn't use a background image and I have no idea if it's actually helpful towards what you want to do... anyone?

  4. #4
    You could do this with Teensy 3.2 by storing the background image in flash and updating the needle with triangle rasterization on top of it. Since you don't need to actually update other than previous and current frame needle positions, it would be pretty fast.

  5. #5
    Senior Member
    Join Date
    Apr 2019
    Posts
    156
    Quote Originally Posted by oddson View Post
    I think OP has all that sorted and wants to know how to animate the needle and draw a background image to the display... (I can't help with this)

    I did find this https://busy.org/@pakganern/oled-dis...ometer-arduino for a different display but at least some of the major graphics calls look compatable, e.g. .drawCircle()

    It doesn't use a background image and I have no idea if it's actually helpful towards what you want to do... anyone?
    ok - understood

    you may need to use a nextion display instead


    I would be keen to find out how to do this, does anyone have an example

  6. #6
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,915
    The main choke point in pretty pictures would be the display rather than the teensy because of the time taken to send one screen worth of pixels is fixed by the display interface. If you can live with the needle not overlapping the gauge markings the idea would be draw the background image once (or on a very limited rate) and then just draw the black pixels to erase the old needle position and the red pixels for the new position without needing to output a pile of unchanged pixels.

    If drawing the needle from first principles you get to revisit your trigonometry. First identify the final angle you want, possibly using some IF statements to handle the divergent scales. Then use sin and cos of that angle times your needle length to get your X and Y end point pixels. To pretty things up a bit and get a wedge shaped needle you can also do things like find the point 3 pixels out from the pivot point at 90 and 270 degrees from your angle, then draw lines from that point to the previously found pointer tip.

    Experimenting with something like excel can help get the formulas right without doing lots waiting for code to compile.

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,960
    Or with a Teensy with more memory like T3.6/3.5 or T4, you can use the ILI9341_t3n library and turn on using frame buffer.

    With this you can write the code pretty sloppy and for example each time you wish to update the position of the needle you simply:
    rewrite the whole screen:
    For example have an internal array with the bitmap for the background which you draw, then draw the needle in new position, and then tell the screen to update... Also with this option, you have the option to tell the screen to update using DMA, so you don't have to wait for it to complete to do something else. You may need to wait if you decide you need to update the display again, before you start writing new data to the frame buffer.

  8. #8
    Quote Originally Posted by GremlinWrangler View Post
    The main choke point in pretty pictures would be the display rather than the teensy because of the time taken to send one screen worth of pixels is fixed by the display interface. If you can live with the needle not overlapping the gauge markings the idea would be draw the background image once (or on a very limited rate) and then just draw the black pixels to erase the old needle position and the red pixels for the new position without needing to output a pile of unchanged pixels.

    If drawing the needle from first principles you get to revisit your trigonometry. First identify the final angle you want, possibly using some IF statements to handle the divergent scales. Then use sin and cos of that angle times your needle length to get your X and Y end point pixels. To pretty things up a bit and get a wedge shaped needle you can also do things like find the point 3 pixels out from the pivot point at 90 and 270 degrees from your angle, then draw lines from that point to the previously found pointer tip.

    Experimenting with something like excel can help get the formulas right without doing lots waiting for code to compile.
    Thank you for this - it’s exactly my plan: draw the frame in the setup and update the needle position in the loop.
    But, my maths has not been put to practice in many years and thats actually where I am stuck.

    Ill try some of the examples here plus some others I found via Google.

    I just might go for a T4.0 to speed up the display rate.

  9. #9
    You only need to update pixels for the needle so there's no perf issue and the needle can also overlap the background graphics. You can even have a texture for the needle for some added visual flair. The challenge is to figure out how to do triangle rasterization, but it's not terribly complicated: https://fgiesen.wordpress.com/2013/0...n-in-practice/

  10. #10
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,960
    You might try: tft.fillTriangle...

  11. #11
    Senior Member
    Join Date
    Dec 2015
    Location
    LA
    Posts
    148
    This guy has what you want. Just replace all the Adafruit_HX8357 with ILI9341_t3 and make a few other pin assignments. He also has some great plotting software.

    https://youtu.be/U5hOU-xxQgk

  12. #12
    Senior Member
    Join Date
    Apr 2017
    Posts
    201
    Will this help?

    https://www.youtube.com/watch?v=U5hOU-xxQgk


    OPPS I see this link was already posted.

  13. #13
    That youtube clip appears to have been done on an arduino, and it is having a hard time driving that display.
    I don't have any experience with that driver, but with SSD1309 I have good success at fast fluid displays by avoiding the 'clear.display' and writing the background colour to the Needle's previous pixels and foreground colour to the Needle's new pixels.
    My suggestion would be set up an interval timer and refresh/redisplay the needle at a fixed speed preferably at least 10Hz as anything less looks terrible. Use another interval timer to update numerical display (such as the red 7-segment in your picture) at 1Hz. You can play with the intervals and the phasing to find your point of best performance. Do not do any display in the loop, unless you use conditional statements and or flags to ensure you are not doing needless pixel-poking.

  14. #14
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,960
    For the fun of it, I did a quick and dirty version of gauge with a needle using my ILI9341_t3n library, which is done pretty dirty... That is I enable frame buffer to make it easy to not have any flashing...
    As such it requires a Teensy that has enough memory T3.5/6 or T4... I ran it on T4..

    If I were doing it for something to use, I would take a lot more care. The background image, I took screen shoot from your image, saved it to file, used http://www.rinkydinkelectronics.com/...nverter565.php

    To convert the file to a 565 format image file, which I included and draw from memory every time....
    Click image for larger version. 

Name:	IMG_1007.jpg 
Views:	11 
Size:	110.3 KB 
ID:	18462

    Zip file of sketch included

    Sorry my math skills are extremely rusty, so some of this could be done better, but to draw the needle I have:
    Code:
    const double NEEDLE_LEN = 100;
    const double TRI_HALF_WIDTH = 3;
    const double CENTER_X = 160;
    const double CENTER_Y = 120;
    void drawNeedle(int percent, uint16_t color) {
      double rads = HALF_PI + TWO_PI * percent/100.0;
      uint16_t x0 = cos(rads) * NEEDLE_LEN + CENTER_X;
      uint16_t y0 = sin(rads) * NEEDLE_LEN + CENTER_Y;
      uint16_t x1 = cos(rads - HALF_PI) * TRI_HALF_WIDTH + CENTER_X;
      uint16_t y1 = sin(rads - HALF_PI) * TRI_HALF_WIDTH + CENTER_Y;
      uint16_t x2 = cos(rads + HALF_PI) * TRI_HALF_WIDTH + CENTER_X;
      uint16_t y2 = sin(rads + HALF_PI) * TRI_HALF_WIDTH + CENTER_Y;
    /*
      Serial.print("Percent: ");Serial.print(percent, 3);
      Serial.print("Rads: ");Serial.print(rads, 3);
      Serial.printf(" (%u, %u) (%u %u) (%u %u)\n", x0, y0, x1, y1, x2, y2);
    */
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, color);
    }
    The setup code draws a couple of different colored needles as to get an idea of were percentages hit...

    Then main loop revs up from 0-75 percent and then back down...
    Again quick and dirty as relying on frame buffer to controlling when pixels go to the display to remove flicker...
    Code:
    void loop(void) {
      Serial.println("Press any key to continue");
      while(Serial.read() == -1);
      while (Serial.read() != -1) ;
    
      for (int percent=0; percent < 75; percent++) {
        tft.writeRect(40, 0, 240, 240, (const uint16_t*)gauge);
        drawNeedle(percent, ILI9341_RED);
        tft.updateScreen();
      }
      for (int percent=75; percent >= 0; percent--) {
        tft.writeRect(40, 0, 240, 240, (const uint16_t*)gauge);
        drawNeedle(percent, ILI9341_GREEN);
        tft.updateScreen();
      }
      
    }
    Attached Files Attached Files

  15. #15
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,960
    Just thought I would mention, that I just updated the sketch to also work on our new ST7735/89_t3 library...
    Attached Files Attached Files

  16. #16
    KurtE, this is amazing stuff!!! Thank you for putting time into this - definitely will give me a solid start and the code is simple enough to help me understand how the needle is being calculated and drawn.

    We can speed things up by drawing the frame and numbers/ticks outside of the ring in the setup, and then update the previous needle positioning with the background color in the loop - similar to what I have done with my current display to print out all the numbers centred to the decimal point.

    I'll also get an order for a T4.0 and give it a test with the ILI9341

  17. #17
    Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    49
    Something like this useful?
    Click image for larger version. 

Name:	ulcd-220rd-ar_feature_right.png 
Views:	4 
Size:	308.3 KB 
ID:	18469
    Found here:-
    https://4dsystems.com.au/products/4d..._list_limit=42

  18. #18
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,502
    Quote Originally Posted by KurtE View Post
    Just thought I would mention, that I just updated the sketch to also work on our new ST7735/89_t3 library...
    @KurtE
    Just tried it on a 240x240 ST7789 with no CS pin (yes I had to change the setup). Almost forgot how. Runs great. No real noticeable flicker at all with updating the display as the needle moves.

  19. #19
    @KurtE @mjs513
    can either of you upload a short video or GIF of the gauge/needle sweep
    I'll only be able to run this on my hardware next week and I'm really interested in seeing the smoothness of it.

    @MatrixRat that's a nice display, but I'm looking to place two gauges + several other numeric parameters on a bigger display (2.8"-3.5")

  20. #20
    @KurtE

    I just placed an order for two T4's - and I am getting the gauge image cleaned up by a graphic designer. So I will have that ready to test hopefully in a few weeks.
    Meanwhile, I am preparing for the case that I might need a larger display, perhaps the 3.5" TFT that runs on the ILI9488 - I see you've put together a library for that controller too, but does it also support frame buffering?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •