Waveshare 1.28 display programming

I am making a gauge for my motorcycle. the sensor connects to an analog pin.

The display draws a line by pixel position. the following is the line of code that does that.

Paint_DrawLine  (120, 150, 20, 125, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 

The first two numbers are the starting point of the line. the last two numbers are the end point of the line. the rest is just to format the text.

The starting point numbers will never change but as the analog value changes I need to change the last two number which are the end points to make the gauge sweep..

So my question is how do i convert the analog value number into the two numbers for the line ending pixel position?

I hope i explained that correctly.

thanks john

You may need to use numbers to explain. The value read from the analog port is an integer value from 0 to 1023 for a 10-bit ADC.

Decimal values are often lost when converting to integers, but can be used when multiplying by a constant that passes the decimal digit to an integer value position.

12.34 ----> (12.34 x10): 123.4

You appear to have a fixed length "red pointer" that you need to draw at a specific angle.
So it is just a question of determining the "end point" e.g. by x = len * cos(angle) and y = len * sin(angle)

It looks as if your 100F point is at -80 degrees and the +250F point is at +80 degrees.
I note that your 100F. 150F, 180F, 210F, 250F are not "linear". So you would need a "look-up" table to convert temperature to the angle.

In practical terms. You keep track of the "current" temperature.
If it changes you re-draw the white scale. Draw the new red pointer. Save the new temperature.

I doubt if "linear" is important when you measure things in inches, bushels etc.
If "traditional appearance" is what you want, you could store say 10 different hi-res pictures in a Flash memory. Then display the appropriate picture.

David.

Here's what I'm thinking but I don't know how to program it correctly or if will even work.

Like I said the last two number represent the end point of the line.

Paint_DrawLine (120, 150, 20, 125, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID);

I would change the line ending numbers to variables?

Paint_DrawLine (120, 150, x_val_1 , y_val_1 , RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID);

so

if analog value = 100 then x_val_1 = 40 , y_val_1 =70

if analog value = 200 then x_val_1 = 70 , y_val_1 =100

my thought is to only change the end values of the code.

does that make sense?

so the program complied using th varables.

Paint_DrawLine (120, 150, x_val_1 , y_val_1 , RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID);

i can move the line by changing the numbers in the in the varables.

[code]
#include <SPI.h>
#include "LCD_Driver.h"
#include "GUI_Paint.h"
#include "image.h"

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor


int x_val_1 =120; // line end position
int y_val_1 =50;

void setup()
{
  pinMode(ledPin, OUTPUT);
  Config_Init();
  LCD_Init();
  LCD_SetBacklight(1000);
  Paint_NewImage(LCD_WIDTH, LCD_HEIGHT, 0, BLACK);
  Paint_Clear(BLACK);

  // NEEDLE RED CENTER DOT
  Paint_DrawCircle(120, 150, 10, RED , DOT_PIXEL_2X2, DRAW_FILL_FULL);
  Paint_DrawCircle(120,150, 75, BLUE ,DOT_PIXEL_2X2,DRAW_FILL_EMPTY);

  // GUAGE NUMBER LINES
  Paint_DrawLine  (40, 120, 60, 120, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //100 line
  Paint_DrawLine  (70, 70, 80, 80, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //150 line
  Paint_DrawLine  (120, 40, 120, 50, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //180 line
  Paint_DrawLine  (160, 80, 180, 70, WHITE, DOT_PIXEL_2X2, LINE_STYLE_SOLID); //210 line
  Paint_DrawLine  (170, 120, 190, 120, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); // 250 line

  // GUAGE LETTERING AND NUMBERS
  //void Paint_DrawString_EN(UWORD Xstart, UWORD Ystart, const char * pString, sFONT* Font, UWORD Color_Foreground,  UWORD Color_Background)
      
  Paint_DrawString_EN(20, 120, "100", &Font20,  BLACK, WHITE); 
  Paint_DrawString_EN(30, 50, "150", &Font20,  BLACK, WHITE);
  Paint_DrawString_EN(95, 15, "180", &Font20,  BLACK, WHITE);
  Paint_DrawString_EN(180, 50, "210", &Font20,  BLACK, WHITE);
  Paint_DrawString_EN(195, 120, "250", &Font20,  BLACK, WHITE);
  Paint_DrawString_EN(95, 180, "OIL", &Font24,  BLACK, WHITE);
  Paint_DrawString_EN(98, 202, "TEMP", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(115, 220, "F", &Font20,  BLACK, WHITE);


    Paint_DrawLine  (120, 150, x_val_1 , y_val_1 , RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); // X- Y
//Paint_DrawLine(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color, LINE_STYLE Line_Style ,  LINE_STYLE Line_Style)
       

               
   // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  // turn the ledPin on
  digitalWrite(ledPin, HIGH);
  // stop the program for <sensorValue> milliseconds:
  delay(sensorValue);
  // turn the ledPin off:
  digitalWrite(ledPin, LOW);
  // stop the program for for <sensorValue> milliseconds:
  delay(sensorValue);

}
void loop()
{

}



/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

[/code]

The following function will fill in the variables of your Paint_DrawLine function

void temperature(angle){
 	rads = angle * (PI/180);
  	x = X_center + sin(rads) * radius;
  	y = Y-center - cos(rads) * radius;
	Paint_DrawLine  (X_center, Y_center, x, y, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 
	}

X_center,Y_center and radius(length of the needle) would be defined as constants.

To determine the angle for 100 you could start by plugging in a few values between 0 and 360 until the needle came to rest on the 100 mark then do the same for 150,180 etc.

If you adjusted the position of the tick marks so that the reading was 100 to 250 deg. temperature with tick marks equally spaced in between moving the needle would be much simpler for example 1 degree of angle = 1 degree of temp.

Tried inputting that code but unfortunate I not that good at programming yet.

Getting errors

You said the last piece of code that you posted that you could move the line if you change the variables. The code that I last posted I have rewritten to match the values in your code so that it might be easier to understand.

try replacing

void loop()
{
}

with

void loop() {
  
for (word angle = 0; angle <= 360; angle++) {
float rads = angle * (PI/180);
word x_val_1 = 120 + sin(rads) * 30;
word y_val_1 = 150 + cos(rads) * 30;
Paint_DrawLine  (120, 150, x_val_1, y_val_1, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 
delay(300);
}

}

the idea is that this will rotate the needle through 360 degrees. If you need a longer or shorter needle adjust the two values of 30, this represents the radius.

Thanks sumguy

That bit of code draws a solid circle.

It appears I have to delete the current needle position and redraw the new needle position in order to make the needle sweep.

I thinking my original idea of putting. The needle end positions X_val_1 and Y_val_1 in and array and just moving thru the array and the needle position changes. ( that’s my thought anyways)

I will still need to erase/delete the old needle position. There is a clear screen command that I can use.

Just need to keep experimenting.



That looks good and is what should be happening.

You dont need an array what you need is a function that takes an angle as an argument.

So working toward that goal try modifying the loop like this

include these variables

word angle;
word x_val_1;
word y_val_1;
word old_x;
word old_y;
void loop() {

if (angle<360){
  
for (angle = 0; angle <= 360; angle++) {
  
float rads = angle * (PI/180);
x_val_1 = 120 + sin(rads) * 60;
y_val_1 = 150 + cos(rads) * 60;
Paint_DrawLine  (120, 150, x_val_1, y_val_1, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 

if ((old_x + old_y)>0){
Paint_DrawLine  (120, 150, old_x, old_y, BLACK , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 
}

old_x=x_val_1;
old_y=y_val_1;
delay(300);

    }
  }
}

I see how your just redrawing the position using the black. But it overwrites the pixels used for the temp marking.

Mabe it’s just the limitations of the display?

I keep working on it.

Also I tried moving the gauge marking into the void loop so it rewrite everything but that didn’t work.



Maybe a compromise, move the temperature values and their tick marks to the very outer edge of the display then adjust the length of the needle so that it is just one pixel away from each tick mark as it passes. That way the black will not over write your graphics, perhaps the tick marks would look ok shorter maybe 2 or 3 pixels. I think there is a better way to draw the ticks but maybe we can discuss that later.

I spoke of a function that takes an angle as a parameter this is something like what I meant. In the loop() change the value in the DrawAtAngle() function call until you find the angles that correspond to each temperature reading on the display and lets see how it looks.

void loop() {

DrawAtAngle(360);
delay(500);

}


void DrawAtAngle(int angle) {

float rads = angle * (PI/180);
x_val_1 = 120 + sin(rads) * 60;
y_val_1 = 150 + cos(rads) * 60;
Paint_DrawLine  (120, 150, x_val_1, y_val_1, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 

if ((old_x + old_y)>0){
Paint_DrawLine  (120, 150, old_x, old_y, BLACK , DOT_PIXEL_2X2, LINE_STYLE_SOLID); 
}

old_x=x_val_1;
old_y=y_val_1;

}



I have the gauge needle sweeping the correct way based on an analog input but the previous needle position don't erase.

[code]
#include <SPI.h>
#include "LCD_Driver.h"
#include "GUI_Paint.h"
#include "image.h"

int potpin = A0;
int val;

void setup() {
  Serial.begin(9600);
  Config_Init();
  LCD_Init();
  LCD_SetBacklight(1000);
  Paint_NewImage(LCD_WIDTH, LCD_HEIGHT, 0, BLACK);
  Paint_Clear(BLACK);

  // NEEDLE RED CENTER DOT
  //Paint_DrawCircle(120, 150, 10, RED , DOT_PIXEL_2X2, DRAW_FILL_FULL);

  // GUAGE NUMBER LINES
  Paint_DrawLine  (0, 120, 10, 120, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //100 line
  Paint_DrawLine  (70, 70, 80, 80, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //150 line
  Paint_DrawLine  (120, 40, 120, 50, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); //180 line
  Paint_DrawLine  (160, 80, 180, 70, WHITE, DOT_PIXEL_2X2, LINE_STYLE_SOLID); //210 line
  Paint_DrawLine  (230, 120, 240, 120, WHITE , DOT_PIXEL_2X2, LINE_STYLE_SOLID); // 250 line

  // GUAGE LETTERING AND NUMBERS
  //void Paint_DrawString_EN(UWORD Xstart, UWORD Ystart, const char * pString, sFONT* Font, UWORD Color_Foreground,  UWORD Color_Background)

  Paint_DrawString_EN(10, 120, "100", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(30, 60, "150", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(95, 15, "180", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(180, 60, "210", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(195, 120, "250", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(95, 180, "OIL", &Font24,  BLACK, WHITE);
  Paint_DrawString_EN(98, 202, "TEMP", &Font16,  BLACK, WHITE);
  Paint_DrawString_EN(115, 220, "F", &Font20,  BLACK, WHITE);
}

void loop () {

  word angle;
  word x_val_1;
  word y_val_1;
  word old_x;
  word old_y;

  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  angle = map(val, 0, 1023, 270, 90);

  float rads = angle * (PI / 180);
  x_val_1 = 120 + sin(rads) * 60;
  y_val_1 = 120 + cos(rads) * 60;
  Paint_DrawLine  (120, 150, x_val_1, y_val_1, RED , DOT_PIXEL_2X2, LINE_STYLE_SOLID);

  if ((old_x + old_y) > 0) {
    Paint_DrawLine  (120, 150, old_x, old_y, BLACK , DOT_PIXEL_2X2, LINE_STYLE_SOLID);
  }

  old_x = x_val_1;
  old_y = y_val_1;

  Serial.println(val);

}



[/code]

I think you should have kept the angle function but you may have your reasons. Try making angle, old_x and old_y global and add another global variable called old_angle. Lastly modify the if statement that looks at old_x and old_y like this

if ((old_x + old_y)>0 && old_angle != angle){
        Paint_DrawLine(80, 64, (old_x| 0), (old_y| 0),  BLACK , DOT_PIXEL_2X2, LINE_STYLE_SOLID);
     }

It should stop any needle flicker when there is no change.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.