TFT LCD analog gauge

I am using the library from Electronics - Henning Karlsen to interface with my TFT LCD. I want to make an virtual level gauge with an arm that pivots a center point like your gas gauge or pressure gauge. The sensor I am using is on A0 and A1. If there is already a post on this please point me in that direction... anything will help.

Thanks

I have Hennings old library ITDB02_Graph16, but thankfully he kept his functions all the same.

Note: this will only draw a semicircle, it will not draw a single line. To get a single line to show, you need to remember the position of the last line and draw over it with the background color. You can also use the map function instead of the FOR loop.

double pi = 3.14159265;
double x = 0; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
double y = 0;// same as above
int cx = 100; // screen coord X
int cy = 100; // screen coord Y
int rad = 50; // radius 50 pixels

for (double i = 0; i <=  pi; i += .01) {
  x = cx + sin(i + (pi/2)) * rad;
  y = cy + cos(i + (pi/2)) * rad;
  myGLCD.setColor(0,0,0);
  myGLCD.drawLine(100,100,x, y); // (cx, cy, calculated x, calculated y)
}

Thanks that helped a lot.

If you need the line to be thicker, you can use the fillrect function instead of drawLine, but it might look a little strobe like when it moves.

I have something working now with a pot as my "sensor" I am getting a pretty interesting flickering wave effect. I've added delayMicroseconds; it helps a little. I might end up adding something where it just draws a line over the last position and see if that helps. Below is what I have so far.

#include <UTFT.h>
extern uint8_t SmallFont[];
UTFT myGLCD(ITDB32S, 38,39,40,41);   // Remember to change the model parameter to suit your display module!

void setup(){
  myGLCD.InitLCD();
  myGLCD.setBackColor(50, 50, 50);
  myGLCD.setFont(SmallFont);
}
double mD(double x, double in_min, double in_max, double out_min, double out_max)//Map double
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void drawNeedle(int sensor,int pos_x, int pos_y){

  myGLCD.setColor(125,255,255);
  myGLCD.fillRect(50,50,150,150);
  double pi = 3.14159265;
  double x = 0; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
  double y = 0;// same as above
  double cur = mD(analogRead(sensor),0,1023,0,pi);
  int rad = 50; // radius 50 pixels
  x = pos_x + sin(cur + (pi/2)) * rad;
  y = pos_y + cos(cur + (pi/2)) * rad;
  myGLCD.setColor(255,0,0);
  myGLCD.drawLine(pos_x,pos_y,x, y); // (cx, cy, calculated x, calculated y)
  myGLCD.printNumF(cur,2,CENTER,10);//used for debugging  
}
void loop(){
  drawNeedle(0,100,100);
  delayMicroseconds(30000);//Added to reduce flickering
}

I think this is more of what you want.

Note the changes and the ones need to work with my screen.

//#include <UTFT.h>
#include <ITDB02_Graph16.h>
extern uint8_t SmallFont[];
//UTFT myGLCD(ITDB32S, 38,39,40,41);   // Remember to change the model parameter to suit your display module!
ITDB02 myGLCD(A1,A2,A0,A4,A5,2);

double pi = 3.14159265;
double x = 0, oldx = 50; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
double y = 0, oldy = 50;// same as above
int rad = 50; // radius 50 pixels
void setup()
{
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.setBackColor(50, 50, 50);
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(125,255,255);
  myGLCD.fillRect(50,50,150,100);
  delay(1);
}

double mD(double data, double in_min, double in_max, double out_min, double out_max)//Map double
{
  return (data - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void drawNeedle(int sensor,int pos_x, int pos_y){
  double cur = mD(analogRead(sensor),0,1023,0,pi);
  x = pos_x + sin(cur + (pi/2)) * rad;
  y = pos_y + cos(cur + (pi/2)) * rad;

  if(x != oldx && y != oldy)
  {
    myGLCD.setColor(125,255,255);
    myGLCD.drawLine(oldx, oldy,pos_x,pos_y);  
    myGLCD.setColor(255,0,0);
    myGLCD.drawLine(x, y,pos_x,pos_y); // (cx, cy, calculated x, calculated y)
    oldx = x; 
    oldy = y;
    myGLCD.printNumF(cur,2,CENTER,10);//used for debugging  
  }
}

void loop(){
  drawNeedle(A15,100,100);
  //delayMicroseconds(30000);//Added to reduce flickering
}

HazardsMind:
I think this is more of what you want.

Note the changes and the ones need to work with my screen.

Would the same code work for triangles? Couldn't get the base of the triangle to rotate around an arc/point.

Here's what I tried. Base doesn't seem to move in an arc.

void drawNeedle(int sensor,int pos_x, int pos_y, int pos_x2, int pos_y2){
  double cur = mD(analogRead(A0),0,1023,0,(1.5 * pi));
  x = ((pos_x + pos_x2)/2) + cos(cur + (pi/2)) * rad;
  y = ((pos_y + pos_y2)/2) + sin(cur + (pi/2)) * rad;

      trx = pos_x + cos(cur + (pi/2)) * 1;
      tr = pos_y + sin(cur + (pi/2)) * 1;
      tlx = pos_x2 + cos(cur + (pi/2)) * 1;
      tl = pos_y2 + sin(cur + (pi/2)) * 1;
      topx = x;
      top = y;

Is the whole triangle going to be the needle or will the triangle be on the tip of the needle?

#include <ITDB02_Graph16.h>

extern uint8_t SmallFont[];
//UTFT myGLCD(ITDB32S, 38,39,40,41);   // Remember to change the model parameter to suit your display module!
ITDB02 myGLCD(A1, A2, A0, A4, A5, 2);


double pi = 3.14159265;
double x = 0, oldx = 50; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
double y = 0, oldy = 50;// same as above
int rad = 50; // radius 50 pixels
void setup()
{
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.setBackColor(50, 50, 50);
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(125, 255, 255);
  myGLCD.fillRect(50, 50, 150, 100);
  delay(1);
}

double mD(double data, double in_min, double in_max, double out_min, double out_max)//Map double
{
  return (data - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void drawNeedle(int sensor, int pos_x, int pos_y) {
  double cur = mD(analogRead(sensor), 0, 1023, 0, pi);

  int rhbx = pos_x + sin(cur) * 10; // right half base
  int rhby = pos_y + cos(cur) * 10; // right half base
      x = pos_x + sin(cur + (pi / 2)) * rad; // tip
      y = pos_y + cos(cur + (pi / 2)) * rad; // tip
  int lhbx = pos_x + sin(cur + pi) * 10; // left half base
  int lhby = pos_y + cos(cur + pi) * 10; // left half base
  
  if (x != oldx && y != oldy)
  {
    myGLCD.setColor(125, 255, 255);
    myGLCD.drawLine(oldx, oldy, pos_x, pos_y);
    Triangle(oldx, oldy, rhbx, rhby, lhbx, lhby);
    myGLCD.setColor(255, 0, 0);
    myGLCD.drawLine(x, y, pos_x, pos_y); // (cx, cy, calculated x, calculated y)
    Triangle(x, y,rhbx, rhby, lhbx, lhby);
    oldx = x;
    oldy = y;
    myGLCD.printNumF(cur, 2, CENTER, 10); //used for debugging
  }
}

void loop() {
  drawNeedle(A15, 100, 100);
}

void Triangle(int x1, int y1,int x2,int y2,int x3,int y3)
{
  myGLCD.drawLine(x1,y1,x2,y2);// lean left
  myGLCD.drawLine(x2,y2,x3,y3);// _ base
  myGLCD.drawLine(x3,y3,x1,y1);// / lean right
}

The whole triangle is gona be the needle.

Thanks again. I think I got what I need. Gona try to edit the code you just posted to use fillTriangle.

HazardsMind:
Is the whole triangle going to be the needle or will the triangle be on the tip of the needle?

#include <ITDB02_Graph16.h>

extern uint8_t SmallFont[];
//UTFT myGLCD(ITDB32S, 38,39,40,41);  // Remember to change the model parameter to suit your display module!
ITDB02 myGLCD(A1, A2, A0, A4, A5, 2);

double pi = 3.14159265;
double x = 0, oldx = 50; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
double y = 0, oldy = 50;// same as above
int rad = 50; // radius 50 pixels
void setup()
{
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.setBackColor(50, 50, 50);
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(125, 255, 255);
  myGLCD.fillRect(50, 50, 150, 100);
  delay(1);
}

double mD(double data, double in_min, double in_max, double out_min, double out_max)//Map double
{
  return (data - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void drawNeedle(int sensor, int pos_x, int pos_y) {
  double cur = mD(analogRead(sensor), 0, 1023, 0, pi);

int rhbx = pos_x + sin(cur) * 10; // right half base
  int rhby = pos_y + cos(cur) * 10; // right half base
      x = pos_x + sin(cur + (pi / 2)) * rad; // tip
      y = pos_y + cos(cur + (pi / 2)) * rad; // tip
  int lhbx = pos_x + sin(cur + pi) * 10; // left half base
  int lhby = pos_y + cos(cur + pi) * 10; // left half base
 
  if (x != oldx && y != oldy)
  {
    myGLCD.setColor(125, 255, 255);
    myGLCD.drawLine(oldx, oldy, pos_x, pos_y);
    Triangle(oldx, oldy, rhbx, rhby, lhbx, lhby);
    myGLCD.setColor(255, 0, 0);
    myGLCD.drawLine(x, y, pos_x, pos_y); // (cx, cy, calculated x, calculated y)
    Triangle(x, y,rhbx, rhby, lhbx, lhby);
    oldx = x;
    oldy = y;
    myGLCD.printNumF(cur, 2, CENTER, 10); //used for debugging
  }
}

void loop() {
  drawNeedle(A15, 100, 100);
}

void Triangle(int x1, int y1,int x2,int y2,int x3,int y3)
{
  myGLCD.drawLine(x1,y1,x2,y2);// lean left
  myGLCD.drawLine(x2,y2,x3,y3);// _ base
  myGLCD.drawLine(x3,y3,x1,y1);// / lean right
}

It doesn't quite delete the old triangle before drawing the new one. It leaves an outline.

But the arc part of the needle seems to be working.

Yea, I noticed that too. :confused:

Thanks anyways :wink: . Gona use the funky thick thin needle in the meantime.

Actually, I have two screens and one is faster than the other, but when I originally wrote the code for the gauge, I was using the slower screen. However now that I have the newer screen I can refresh the screen so much faster now, so instead of drawing then redrawing the needle, just redraw the background.

#include <UTFT.h>

extern uint8_t SmallFont[];
UTFT myGLCD(ITDB32S, 38, 39, 40, 41); // Remember to change the model parameter to suit your display module!

double pi = 3.14159265;
double x = 0, oldx = 50; // setting variable to 0 is not needed, it will be written over anyways, it just looks good.
double y = 0, oldy = 50;// same as above
int rad = 50; // radius 50 pixels
void setup()
{
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.clrScr();
  myGLCD.setBackColor(0x0);
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(125, 255, 255);
  myGLCD.fillRect(50, 50, 150, 100);
  delay(1);
}

double mD(double data, double in_min, double in_max, double out_min, double out_max)//Map double
{
  return (data - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void drawNeedle(int sensor, int pos_x, int pos_y) {
  double cur = mD(analogRead(sensor), 0, 1023, 0, pi);

  int rhbx = pos_x + sin(cur) * 10; // right half base
  int rhby = pos_y + cos(cur) * 10; // right half base
  x = pos_x + sin(cur + (pi / 2)) * rad; // tip
  y = pos_y + cos(cur + (pi / 2)) * rad; // tip
  int lhbx = pos_x + sin(cur + pi) * 10; // left half base
  int lhby = pos_y + cos(cur + pi) * 10; // left half base

  if (x != oldx && y != oldy)
  {
    myGLCD.setColor(125, 255, 255);
    myGLCD.fillRect(50, 50, 150, 110); // redraw box slightly bigger than the needle base
    
    myGLCD.setColor(255, 0, 0);
    myGLCD.drawLine(x, y, pos_x, pos_y); // (cx, cy, calculated x, calculated y)
    Triangle(x, y, rhbx, rhby, lhbx, lhby);
    oldx = x;
    oldy = y;
    myGLCD.printNumF(cur * (180 /pi), 2, CENTER, 10); //used for debugging
  }
}

void loop() 
{
  drawNeedle(A15, 100, 100);
}

void Triangle(int x1, int y1, int x2, int y2, int x3, int y3)
{
  myGLCD.drawLine(x1, y1, x2, y2); // lean left
  myGLCD.drawLine(x2, y2, x3, y3); // _ base
  myGLCD.drawLine(x3, y3, x1, y1); // / lean right
}

HazardsMind:
Actually, I have two screens and one is faster than the other, but when I originally wrote the code for the gauge, I was using the slower screen. However now that I have the newer screen I can refresh the screen so much faster now, so instead of drawing then redrawing the needle, just redraw the background.

Thanks man. Works great, a bit of flicker but much better than the old funky needle. Probably just gona add a timer to reduce flicker.

Used fillTriangle instead of fillRect or fillCircle.

 {
    myGLCD.setColor(BLACK);
        geo.fillTriangle(oldx2, oldy2, oldx3, oldy3, oldx1, oldy1);
    myGLCD.setColor(RED);
      geo.fillTriangle(lhbx, lhby, rhbx, rhby, x, y);
       Triangle(x, y, rhbx, rhby, lhbx, lhby);
  
    oldx1 = x;
    oldy1 = y;
    oldx2 = lhbx;
    oldy2 = lhby;
    oldx3 = rhbx;
    oldy3 = rhby;
  }