Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gauge Needles #571

Closed
Petros144 opened this issue Mar 17, 2020 · 8 comments
Closed

Gauge Needles #571

Petros144 opened this issue Mar 17, 2020 · 8 comments
Labels

Comments

@Petros144
Copy link

Hi Bodmer!

I want to make a nice looking gauge like this:
car-dashboard-ui-modern-vector

You can see that the neede start is not in center, how is this possible to offset?

is it possible to have a layer 1 (background) with the gauge face and a second layer 2 with the needle? so I dont have to draw it each time the needle position changes?

I would really apreciate a little help or tip where to start...

@Bodmer
Copy link
Owner

Bodmer commented Mar 17, 2020

You can set the destination pivot position (e.g. x,y on the TFT). You can also set the pivot point for the Sprite, relative to the top left corner of the Sprite. The Sprite pivot point does not need to be within the bounds of the Sprite. Run and study the Sprite rotation examples which are commented.

The library has no concept of layers, any compositing would need to be coded by yourself.

The simplest approach to a gauge is to ensure the swept area of the needle does not pass over any other graphics. This make updates fast, for example try this:

// Created by Bodmer 17/3/20 as an example to the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI

#define NEEDLE_LENGTH 25  // Visible length
#define NEEDLE_RADIUS 80  // Radius at tip

#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle

// =======================================================================================
// Setup
// =======================================================================================
void setup()   {
  Serial.begin(115200); // Debug only

  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(TFT_NAVY);

  // Create the needle Sprite
  createNeedle();

  // Define where the needle pivot point is on the TFT
  tft.setPivot(tft.width()/2, tft.height()/2);  // Set the TFT pivot point

  // Full scale to sweep area (angle, delay_per_degree)
  plotNeedle(240, 1);

  // Reset needle position to 0
  plotNeedle(0, 1);
}

// =======================================================================================
// Loop
// =======================================================================================
void loop() {
  // Plot needle at random angle in range 0 to 240, speed 5ms per degree
  plotNeedle(random(241), 5);

  // Pause at new position
  delay(250);
}

// =======================================================================================
// Create the needle Sprite
// =======================================================================================
void createNeedle(void)
{
  needle.setColorDepth(8);
  needle.createSprite(11, NEEDLE_LENGTH);  // create the needle Sprite 11 pixels wide by 30 high

  needle.fillSprite(TFT_BLACK); // Fill with black

  // Define needle pivot point
  uint16_t piv_x = needle.width() / 2;   // pivot x in Sprite (middle)
  uint16_t piv_y = NEEDLE_RADIUS;        // pivot y in Sprite
  needle.setPivot(piv_x, piv_y);         // Set pivot point in this Sprite

  // Draw the red needle with a yellow tip
  // Keep needle tip 1 pixel inside dial circle to avoid leaving stray pixels
  needle.fillRect(piv_x - 1, 2, 3, NEEDLE_LENGTH, TFT_RED);
  needle.fillRect(piv_x - 1, 2, 3, 5, TFT_YELLOW);
}

// =======================================================================================
// Move the needle to a new position
// =======================================================================================
void plotNeedle(int angle, byte ms_delay)
{
  static int16_t old_angle = -120; // Starts at -120 degrees

  if (angle < 0) angle = 0; // Limit angle to emulate needle end stops
  if (angle > 240) angle = 240;

  angle -= 120; // Starts at -120 degrees

  // Move the needle until new angle reached
  while (angle != old_angle) {

    if (old_angle < angle) old_angle++;
    else old_angle--;

    // Draw the needle in the new postion
    needle.pushRotated(old_angle);

    // Slow needle down slightly as it approaches new postion
    if (abs(old_angle - angle) < 10) ms_delay += ms_delay / 5;

    // Wait before next update
    delay(ms_delay);
  }
}

// =======================================================================================

@Petros144
Copy link
Author

Wow ! Thank you.

is it possible to plot the needle over text? so that the Black Arc is "transparent"?

that makes it longer and easier to see.

@Bodmer
Copy link
Owner

Bodmer commented Mar 18, 2020

There is no simple solution. For an arbitrary background you would have to create a copy of all pixels obliterated by the needle. When the needle moves the pixels that were obliterated would need to be redrawn and then the needle drawn in the new position. See "TFT_Meter_linear" and "Rotated_Sprite_2" examples.

The solution for your needs is something you will have to work out and code yourself.

@Bodmer Bodmer closed this as completed Mar 18, 2020
@Bodmer
Copy link
Owner

Bodmer commented Mar 20, 2020

I have updated the library and added a new "Animated_dial" example that will be of interest to you. This draws a needle over a jpeg image of a dial.

@wooggiebooggie
Copy link

wooggiebooggie commented Dec 22, 2021

Hi @Bodmer , i am testing your amazing Animated_dial example, when it sweeps it deletes the numbers in the background, how can one solve this?

@Bodmer
Copy link
Owner

Bodmer commented Dec 23, 2021

To operate correctly the TFT screen must support reading pixel data. The TFT_ReadWrite_Test example sketch will text this.

@wooggiebooggie
Copy link

Thank you for your help! Turns out my GC9A01 doesnt support reading pixel data :(

@VolosR
Copy link

VolosR commented Mar 8, 2023

Hello, I found this Thread few days ago and when I saw this image I decided to make car dashboard and gauges.
Dear Petros i hope you dont mind, i dont know if you managed to make this, but if you want you can use my code.
I posted video on my YT chanell and you can find code in description. Video is here:
https://youtu.be/cBtsLxZ13hQ

I used pure tft_espi and whole design is created using simple lines ,rectangles, circles ...
Also, thank you Bodmer, Thank you for evry upadate and every new function you are giving us. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants