Gauge indicator

Hi all

Fresh experience here coding, I have a Gauge indicator with a needle moving 180 degree from 0 to 100% proportional to a 0 to 5 volt.

The code is working but my problem now is that when the needle change position it dont delete the last needle position so it make to have many needle indication.

here is my Void Loop:

p = analogRead(potmeterPin); // Read the analog pin
w = map(p, 0, 1023, 0, 100); // Map the read value to 0-100
m = map(p, 0, 1023, 0, 90); // Map the needle movement
angle = m; // Adjust the angle for needle position

if (angle < 45) {
angle =angle+135;
} else {
angle = angle-45;
}
drawGauge(angle);

delay(100);

any help I will appreciate.

It will help if you post details on your gauge indicator; i.e. product type and preferably a link to documentation or a datasheet. Also indicate which library you're using for this indicator. Furthermore, when posting code, please always post a complete sketch, not just a code snippet. For instance, the library used could have been gleaned from your code if it had been complete.

Yeap sorry
Using Arduino Giga R1 and Arduino Giga Display Shield with GigaDisplay_GFX.

#include <Arduino_GigaDisplay_GFX.h>

GigaDisplay_GFX display; // Initialize the display with correct resolution for GIGA Display Shield

// Constants for gauge dimensions and centering
const int xmax = 800;
const int ymax = 480;
const int xcenter = xmax / 2;
const int ycenter = ymax / 2;
const int arc = ymax / 5;

#define BLACK 0x0000
#define GREEN 0x07E0

float potmeterPin = A1; // Pin for the potentiometer
int p;
int w;
int m;
float angle;

char* labels[] = {"LOAD", "COOLANT", "INTAKE", "VOLT"};
int labelXpos[] = {53, 45, 49, 53};

void drawGauge(float angle) {

display.drawCircleHelper(xcenter, ycenter, 100, 1, GREEN);
display.drawCircleHelper(xcenter, ycenter, 99, 1, GREEN);
display.drawCircleHelper(xcenter, ycenter, 98, 1, GREEN);
display.drawCircleHelper(xcenter, ycenter, 100, 2, GREEN);
display.drawCircleHelper(xcenter, ycenter, 99, 2, GREEN);
display.drawCircleHelper(xcenter, ycenter, 98, 2, GREEN);

// Calculate the needle's position
float x1 = sin(2 * angle * 2 * 3.14159 / 360);
float y1 = cos(2 * angle * 2 * 3.14159 / 360);
display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
display.fillCircle(xcenter, ycenter, 5, GREEN);

// Set font and draw gauge labels
display.setTextSize(2);
display.setCursor(labelXpos[0], 32);
display.print(labels[0]);

// Display the numeric value
display.setCursor(54, 60);
if (w < 10) {
display.print('0');
}
display.print(w);
}

void setup() {
display.begin(); // Initialize the display
display.setRotation(1);
display.fillScreen(BLACK);
display.setTextColor(GREEN); // Set text color to white
pinMode(A1, INPUT);
}

void loop() {

p = analogRead(potmeterPin); // Read the analog pin
w = map(p, 0, 1023, 0, 100); // Map the read value to 0-100
m = map(p, 0, 1023, 0, 90); // Map the needle movement
angle = m; // Adjust the angle for needle position

if (angle < 45) {
angle =angle+135;
} else {
angle = angle-45;
}
drawGauge(angle);

delay(100);

}

OK, this helps.

When drawing the gauge, try drawing it first in its old location in the background color (presumably black), and then draw it in the new location in the foreground color (green, apparently). This way, you first erase the gauge line by overwriting it in black, before writing the new one.

dont worked, when I use drawGauge two time it show mw two needle in two difference position with two diference movement value.

If you could show the code that didn't work, I or someone else can indicate why it didn't work. The principle as such surely does work.

Alternatively you could clear the entire area where the gauge is and then draw the whole thing again.

Btw, for good performance without flickering etc. I think you're going to need to rewrite the drawGauge routine. I'd split it out into two functions: one that draws the borders, scale/labels etc, and one that only draws the needle. Then you can use the needle routine to erase the gauge in its previous location in black/background color and draw the new one in green in its new location.

1 Like

I think the solution is a (DO / WHILE) for example:
Do ( drawGauge)
While(gauge value change)
it mean that everytime the value of the needle change it will go out of the loop and start again.
Now I am trying to do it like this.

Give it a try, but I'd suggest rethinking what you wrote above. Is a momentary change of a value really a "while" condition, or is it more something like an "if"? And is the drawing of the gauge really an enduring activity that gets repeated over and over as long as the value doesn't change?

So personally, I wouldn't use a do/while in this case. But feel free to try and see what happens.

With a real simple gauge like this code, you can probably get away with just writing black over the previous needle and then draw new one...

Something like:

#include <Arduino_GigaDisplay_GFX.h>

GigaDisplay_GFX display;  // Initialize the display with correct resolution for GIGA Display Shield

// Constants for gauge dimensions and centering
const int xmax = 800;
const int ymax = 480;
const int xcenter = xmax / 2;
const int ycenter = ymax / 2;
const int arc = ymax / 5;

#define BLACK 0x0000
#define GREEN 0x07E0

float potmeterPin = A1;  // Pin for the potentiometer
int p;
int w;
int m;
float angle;

char* labels[] = { "LOAD", "COOLANT", "INTAKE", "VOLT" };
int labelXpos[] = { 53, 45, 49, 53 };

float prev_x1 = 0;
float prev_y1 = 0;


void drawGauge(float angle) {

  display.drawCircleHelper(xcenter, ycenter, 100, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 100, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 2, GREEN);

  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}
void updateGauge(float angle) {
  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * prev_x1, ycenter - arc * prev_y1, BLACK);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}



void setup() {
  while(!Serial && millis() < 4000){}
  Serial.begin(115200);
  display.begin();  // Initialize the display
  display.setRotation(1);
  display.fillScreen(BLACK);
  display.setTextColor(GREEN);  // Set text color to white
  pinMode(A1, INPUT);
  drawGauge(90.0);
}

void loop() {

  //p = analogRead(potmeterPin);  // Read the analog pin
  int ch;
  while ((ch = Serial.read()) != -1) {}
  while ((ch = Serial.read()) == -1) {}
  p = 0;
  while ((ch >= '0') && (ch <= '9')) {
    p = p * 10 + ch - '0';
    ch = Serial.read();
  }

  w = map(p, 0, 1023, 0, 100);  // Map the read value to 0-100
  m = map(p, 0, 1023, 0, 90);   // Map the needle movement
  angle = m;                    // Adjust the angle for needle position
  Serial.print("angle: ");
  Serial.println(angle, 2);

  if (angle < 45) {
    angle = angle + 135;
  } else {
    angle = angle - 45;
  }
  updateGauge(angle);

  delay(100);
}

Sorry did not feel like finding a pot so just entered the new pot value in the serial port.
However I would probably not do it this simply. Would probably at a minimum has a minimum delta angle, that if it did not change more than a specific amount, do update... Otherwise will probably see lots of flicker... Simplest test would be the pot value changed or not.

In more complex setups, where maybe you have background image drawn in gauge, or other stuff, then other approaches can be used. Like computing the new location of where the needle will be displayed, and save away the underlying pixels from that location, and then compute which bits need to be updated to previously saved value, or new value or stays the same... Can be a pain.

In other cases you can cheat. That is you use something like like a frame buffer, and simply draw the full new screen out into the frame buffer and then tell the display to update to that new frame buffer contents. With GFX, you can I believe do things like that using their Canvas objects.

I don't use the Adafruit GFX code enough to remember all details, I know I played with some of it in the thread:
Drawing a few pixels on Giga Display Shield - Hardware / GIGA Display Shield - Arduino Forum

Thank you for your help but your code did no worked, the needle position is pointing down and dont do any movement.

Thanks again.

Did you try typing in numbers...
As I mentioned, I did not hook up analog input, but instead typed in the analog values.

in the code I showed...

 //p = analogRead(potmeterPin);  // Read the analog pin
  int ch;
  while ((ch = Serial.read()) != -1) {}
  while ((ch = Serial.read()) == -1) {}
  p = 0;
  while ((ch >= '0') && (ch <= '9')) {
    p = p * 10 + ch - '0';
    ch = Serial.read();
  }

Try simply removing most of this and uncomment the analogRead call... As for initial position, again quick dirty to get it up and running...

This loop was used to do the same in a OLED 128x64, how can we translate it to GigaDisplay_GFX?

// picture loop

{

u8g.firstPage(); 

do {             

  gauge(xx);

}

while( u8g.nextPage() );

}

Regarding my last post:

display.startWrite and display.endWrite did not resolved the problem.

I am new coding so I dont know how to do it, but thanks.

I did this, two needle, one green and one black, but the needle is flicking too much between green and black.

float x1=sin(2angle23.14/360); // needle position
float y1=cos(2
angle23.14/360);
display.drawLine(xcenter, ycenter, xcenter+arcx1, ycenter-arcy1, GREEN);
display.drawLine(xcenter, ycenter, xcenter+arcx1, ycenter-arcy1, BLACK);

Something like this:

#include <Arduino_GigaDisplay_GFX.h>

GigaDisplay_GFX display;  // Initialize the display with correct resolution for GIGA Display Shield

// Constants for gauge dimensions and centering
const int xmax = 800;
const int ymax = 480;
const int xcenter = xmax / 2;
const int ycenter = ymax / 2;
const int arc = ymax / 5;

#define BLACK 0x0000
#define GREEN 0x07E0

float potmeterPin = A1;  // Pin for the potentiometer
int p;
int w;
int m;
float angle;

const char* labels[] = { "LOAD", "COOLANT", "INTAKE", "VOLT" };
int labelXpos[] = { 53, 45, 49, 53 };

float prev_x1 = 0;
float prev_y1 = 0;


void drawGauge(float angle) {

  display.drawCircleHelper(xcenter, ycenter, 100, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 100, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 2, GREEN);

  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}
void updateGauge(float angle) {
  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * prev_x1, ycenter - arc * prev_y1, BLACK);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}



void setup() {
  while(!Serial && millis() < 4000){}
  Serial.begin(115200);
  display.begin();  // Initialize the display
  display.setRotation(1);
  display.fillScreen(BLACK);
  display.setTextColor(GREEN);  // Set text color to white
  pinMode(A1, INPUT);
}

void loop() {

  p = analogRead(potmeterPin);  // Read the analog pin
  w = map(p, 0, 1023, 0, 100);  // Map the read value to 0-100
  m = map(p, 0, 1023, 0, 90);   // Map the needle movement
  angle = m;                    // Adjust the angle for needle position
  Serial.print("angle: ");
  Serial.println(angle, 2);

  if (angle < 45) {
    angle = angle + 135;
  } else {
    angle = angle - 45;
  }
  static bool first_call = true;
  if (first_call) {
    drawGauge(angle);
    first_call = false;
  }
  else updateGauge(angle);

  delay(100);
}

But you will probably notice a lot of flickering of the needle...

You can reduce this several different ways, one is simply don't update if the values do not change less than some minimum... Maybe something like:

#include <Arduino_GigaDisplay_GFX.h>

GigaDisplay_GFX display;  // Initialize the display with correct resolution for GIGA Display Shield

// Constants for gauge dimensions and centering
const int xmax = 800;
const int ymax = 480;
const int xcenter = xmax / 2;
const int ycenter = ymax / 2;
const int arc = ymax / 5;

#define BLACK 0x0000
#define GREEN 0x07E0

float potmeterPin = A1;  // Pin for the potentiometer
int previous_p = -100;   // some value out of range of what p can be.
#define MIN_P_DELTA 2    // how far P needs to change before you update.
int p;
int w;
int m;
float angle;

const char* labels[] = { "LOAD", "COOLANT", "INTAKE", "VOLT" };
int labelXpos[] = { 53, 45, 49, 53 };

float prev_x1 = 0;
float prev_y1 = 0;


void drawGauge(float angle) {

  display.drawCircleHelper(xcenter, ycenter, 100, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 1, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 100, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 99, 2, GREEN);
  display.drawCircleHelper(xcenter, ycenter, 98, 2, GREEN);

  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}
void updateGauge(float angle) {
  // Calculate the needle's position
  float x1 = sin(2 * angle * 2 * 3.14159 / 360);
  float y1 = cos(2 * angle * 2 * 3.14159 / 360);
  display.drawLine(xcenter, ycenter, xcenter + arc * prev_x1, ycenter - arc * prev_y1, BLACK);
  display.drawLine(xcenter, ycenter, xcenter + arc * x1, ycenter - arc * y1, GREEN);
  display.fillCircle(xcenter, ycenter, 5, GREEN);
  prev_x1 = x1;
  prev_y1 = y1;

  // Set font and draw gauge labels
  display.setTextSize(2);
  display.setCursor(labelXpos[0], 32);
  display.print(labels[0]);

  // Display the numeric value
  display.setCursor(54, 60);
  if (w < 10) {
    display.print('0');
  }
  display.print(w);
}



void setup() {
  while (!Serial && millis() < 4000) {}
  Serial.begin(115200);
  display.begin();  // Initialize the display
  display.setRotation(1);
  display.fillScreen(BLACK);
  display.setTextColor(GREEN);  // Set text color to white
  pinMode(A1, INPUT);
}

void loop() {

  p = analogRead(potmeterPin);  // Read the analog pin
  if (abs(p - previous_p) > MIN_P_DELTA) {
    w = map(p, 0, 1023, 0, 100);  // Map the read value to 0-100
    m = map(p, 0, 1023, 0, 90);   // Map the needle movement
    angle = m;                    // Adjust the angle for needle position
    Serial.print("angle: ");
    Serial.println(angle, 2);

    if (angle < 45) {
      angle = angle + 135;
    } else {
      angle = angle - 45;
    }
    static bool first_call = true;
    if (first_call) {
      drawGauge(angle);
      first_call = false;
    } else updateGauge(angle);
    previous_p = p;
  }

  delay(100);
}

Where I check to see if the p value changes more than:
#define MIN_P_DELTA 2 // how far P needs to change before you update.
Which I defined here as 2, but you could try 1 and see if that is sufficient... There are several other approaches like averaging the last n inputs and the like, but hopefully this gives you some starting point

The problem is gone.

I did a diplay.fillCircle, BLACK color with the same radius of the needle move, the needle move fine with cero flickering.

Thanks everyone for your help.

Yes, that'll work. As I suggested earlier:

:handshake: :handshake: :handshake: