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

Graph and meters #3

Closed
sorriso93 opened this issue Apr 1, 2019 · 4 comments
Closed

Graph and meters #3

sorriso93 opened this issue Apr 1, 2019 · 4 comments

Comments

@sorriso93
Copy link

I know you are already planning this but just to inform you some code is already available maybe you can easily integrate it (I tested it and it is almost ok with your library).

Found on github various code maybe you can improve it
many thanks

ringmeter below

`/*
An example showing 'ring' analogue meters on a 2.2" ILI9341 TFT 240x320
colour screen

The meter graphic function works best with slowly changing values without
large rapid changes such as environmental parameters (temperature etc)

This example uses the hardware SPI and a board based on the ATmega328
such as an UNO. If using a Mega or outher micocontroller then comment out
the following line:
#define F_AS_T
in the "Adafruit_ILI9341_FAST.h" found within the Adafruit_ILI9341_AS
library folder. Change pins for other Arduinos to the hardware SPI pins.

Needs Fonts 2, and 4 (also Font 6 if using a large size meter)

Alan Senior 18/3/2015
*/

// These are the connections from the UNO to the display
#define sclk 13 // Don't change
#define mosi 11 // Don't change
#define cs 10 // If cs and dc pin allocations are changed then
#define dc 9 // comment out #define F_AS_T line in "Adafruit_ILI9341_FAST.h"
// (which is inside "Adafriit_ILI9341_AS" library)

#define rst 7 // Can alternatively connect this to the Arduino reset

// Meter colour schemes
#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5

#include <Adafruit_GFX_AS.h> // Core graphics library
#include <Adafruit_ILI9341_AS.h> // Fast hardware-specific library
#include <SPI.h>

#define ILI9341_GREY 0x2104 // Dark grey 16 bit colour

Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(cs, dc, rst); // Invoke custom library

uint32_t runTime = -99999; // time for next update

int reading = 0; // Value to be displayed
int d = 0; // Variable used for the sinewave test waveform

void setup(void) {
tft.init();

tft.setRotation(3);

tft.fillScreen(ILI9341_BLACK);
}

void loop() {
if (millis() - runTime >= 2000L) { // Execute every 2s
runTime = millis();

// Test with a slowly changing value from a Sine function
d += 5; if (d >= 360) d = 0;

// Set the the position, gap between meters, and inner radius of the meters
int xpos = 0, ypos = 5, gap = 4, radius = 52;

// Draw meter and get back x position of next meter

// Test with Sine wave function, normally reading will be from a sensor
reading = 250 + 250 * sineWave(d+0);
xpos = gap + ringMeter(reading, 0, 500, xpos, ypos, radius, "mA", GREEN2RED); // Draw analogue meter

reading = 20 + 30 * sineWave(d+60);
xpos = gap + ringMeter(reading, -10, 50, xpos, ypos, radius, "degC", BLUE2RED); // Draw analogue meter

reading = 50 + 50 * sineWave(d + 120);
ringMeter(reading, 0, 100, xpos, ypos, radius, "%RH", BLUE2BLUE); // Draw analogue meter


// Draw two more larger meters
xpos = 20, ypos = 115, gap = 24, radius = 64;

reading = 1000 + 150 * sineWave(d + 90);
xpos = gap + ringMeter(reading, 850, 1150, xpos, ypos, radius, "mb", BLUE2RED); // Draw analogue meter

reading = 15 + 15 * sineWave(d + 150);
xpos = gap + ringMeter(reading, 0, 30, xpos, ypos, radius, "Volts", GREEN2GREEN); // Draw analogue meter

// Draw a large meter
xpos = 40, ypos = 5, gap = 15, radius = 120;
reading = 175;
// Comment out above meters, then uncomment the next line to show large meter
//ringMeter(reading,0,200, xpos,ypos,radius," Watts",GREEN2RED); // Draw analogue meter

}
}

// #########################################################################
// Draw the meter on the screen, returns x coord of righthand side
// #########################################################################
int ringMeter(int value, int vmin, int vmax, int x, int y, int r, char *units, byte scheme)
{
// Minimum value of r is about 52 before value text intrudes on ring
// drawing the text first is an option

x += r; y += r; // Calculate coords of centre of ring

int w = r / 4; // Width of outer ring is 1/4 of radius

int angle = 150; // Half the sweep angle of meter (300 degrees)

int text_colour = 0; // To hold the text colour

int v = map(value, vmin, vmax, -angle, angle); // Map the value to an angle v

byte seg = 5; // Segments are 5 degrees wide = 60 segments for 300 degrees
byte inc = 5; // Draw segments every 5 degrees, increase to 10 for segmented ring

// Draw colour blocks every inc degrees
for (int i = -angle; i < angle; i += inc) {

// Choose colour from scheme
int colour = 0;
switch (scheme) {
  case 0: colour = ILI9341_RED; break; // Fixed colour
  case 1: colour = ILI9341_GREEN; break; // Fixed colour
  case 2: colour = ILI9341_BLUE; break; // Fixed colour
  case 3: colour = rainbow(map(i, -angle, angle, 0, 127)); break; // Full spectrum blue to red
  case 4: colour = rainbow(map(i, -angle, angle, 63, 127)); break; // Green to red (high temperature etc)
  case 5: colour = rainbow(map(i, -angle, angle, 127, 63)); break; // Red to green (low battery etc)
  default: colour = ILI9341_BLUE; break; // Fixed colour
}

// Calculate pair of coordinates for segment start
float sx = cos((i - 90) * 0.0174532925);
float sy = sin((i - 90) * 0.0174532925);
uint16_t x0 = sx * (r - w) + x;
uint16_t y0 = sy * (r - w) + y;
uint16_t x1 = sx * r + x;
uint16_t y1 = sy * r + y;

// Calculate pair of coordinates for segment end
float sx2 = cos((i + seg - 90) * 0.0174532925);
float sy2 = sin((i + seg - 90) * 0.0174532925);
int x2 = sx2 * (r - w) + x;
int y2 = sy2 * (r - w) + y;
int x3 = sx2 * r + x;
int y3 = sy2 * r + y;

if (i < v) { // Fill in coloured segments with 2 triangles
  tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
  tft.fillTriangle(x1, y1, x2, y2, x3, y3, colour);
  text_colour = colour; // Save the last colour drawn
}
else // Fill in blank segments
{
  tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_GREY);
  tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_GREY);
}

}

// Convert value to a string
char buf[10];
byte len = 4; if (value > 999) len = 5;
dtostrf(value, len, 0, buf);

// Set the text colour to default
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
// Uncomment next line to set the text colour to the last segment value!
// tft.setTextColor(text_colour, ILI9341_BLACK);

// Print value, if the meter is large then use big font 6, othewise use 4
if (r > 84) tft.drawCentreString(buf, x - 5, y - 20, 6); // Value in middle
else tft.drawCentreString(buf, x - 5, y - 20, 4); // Value in middle

// Print units, if the meter is large then use big font 4, othewise use 2
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
if (r > 84) tft.drawCentreString(units, x, y + 30, 4); // Units display
else tft.drawCentreString(units, x, y + 5, 2); // Units display

// Calculate and return right hand side x coordinate
return x + r;
}

// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow(byte value)
{
// Value is expected to be in range 0-127
// The value is converted to a spectrum colour from 0 = blue through to 127 = red

byte red = 0; // Red is the top 5 bits of a 16 bit colour value
byte green = 0;// Green is the middle 6 bits
byte blue = 0; // Blue is the bottom 5 bits

byte quadrant = value / 32;

if (quadrant == 0) {
blue = 31;
green = 2 * (value % 32);
red = 0;
}
if (quadrant == 1) {
blue = 31 - (value % 32);
green = 63;
red = 0;
}
if (quadrant == 2) {
blue = 0;
green = 63;
red = value % 32;
}
if (quadrant == 3) {
blue = 0;
green = 63 - 2 * (value % 32);
red = 31;
}
return (red << 11) + (green << 5) + blue;
}

// #########################################################################
// Return a value in range -1 to +1 for a given phase angle in degrees
// #########################################################################
float sineWave(int phase) {
return sin(phase * 0.0174532925);
}`

barchart H and V

`
void DrawBarChartV(TFT_eSPI & d, long int x , long int y , long int w, long int h , long int loval , long int hival , long int inc , long int curval , int dig , int dec, unsigned int barcolor, unsigned int voidcolor, unsigned int bordercolor, unsigned int textcolor, unsigned int backcolor, String label, boolean & redraw)
{

double stepval, range;
double my, level;
double i, data;
// draw the border, scale, and label once
// avoid doing this on every update to minimize flicker
if (redraw == true) {
redraw = false;

d.drawRect(x - 1, y - h - 1, w + 2, h + 2, bordercolor);
d.setTextColor(textcolor, backcolor);
//d.setTextSize(2);
d.setCursor(x , y + 10);
d.println(label);
// step val basically scales the hival and low val to the height
// deducting a small value to eliminate round off errors
// this val may need to be adjusted
stepval = ( inc) * (double (h) / (double (hival - loval))) - .001;
for (i = 0; i <= h; i += stepval) 
{
  my =  y - h + i;
  d.drawFastHLine(x + w + 1, my,  5, textcolor);
  // draw lables
  //  d.setTextSize(1);
  d.setTextColor(textcolor, backcolor);
  d.setCursor(x + w + 12, my - 3 );
  data = hival - ( i * (inc / stepval));
  d.println(Format(data, dig, dec));
}

}
// compute level of bar graph that is scaled to the height and the hi and low vals
// this is needed to accompdate for +/- range
level = (h * (((curval - loval) / (hival - loval))));
// draw the bar graph
// write a upper and lower bar to minimize flicker cause by blanking out bar and redraw on update
d.fillRect(x, y - h, w, h - level, voidcolor);
d.fillRect(x, y - level, w, level, barcolor);
// write the current value
d.setTextColor(textcolor, backcolor);
//d.setTextSize(2);
d.setCursor(x , y - h - 15); //23
d.println(Format(curval, dig, dec));
}

/*
This method will draw a horizontal bar graph for single input
it has a rather large arguement list and is as follows

&d = display object name
x = position of bar graph (upper left of bar)
y = position of bar (upper left of bar (add some vale to leave room for label)
w = width of bar graph (does not need to be the same as the max scale)
h = height of bar graph
loval = lower value of the scale (can be negative)
hival = upper value of the scale
inc = scale division between loval and hival
curval = date to graph (must be between loval and hival)
dig = format control to set number of digits to display (not includeing the decimal)
dec = format control to set number of decimals to display (not includeing the decimal)
barcolor = color of bar graph
voidcolor = color of bar graph background
bordercolor = color of the border of the graph
textcolor = color of the text
back color = color of the bar graph's background
label = bottom lable text for the graph
redraw = flag to redraw display only on first pass (to reduce flickering)
*/

void DrawBarChartH(TFT_eSPI & d, long int x , long int y , long int w, long int h , long int loval , long int hival , long int inc , long int curval , int dig , int dec, unsigned int barcolor, unsigned int voidcolor, unsigned int bordercolor, unsigned int textcolor, unsigned int backcolor, String label, boolean & redraw)
{
double stepval, range;
double mx, level;
double i, data;

// draw the border, scale, and label once
// avoid doing this on every update to minimize flicker
// draw the border and scale
if (redraw == true) {
redraw = false;
d.drawRect(x , y , w, h, bordercolor);
d.setTextColor(textcolor, backcolor);
// d.setTextSize(2);
d.setCursor(x , y - 20);
d.println(label);
// step val basically scales the hival and low val to the width
stepval = inc * (double (w) / (double (hival - loval))) - .00001;
// draw the text
for (i = 0; i <= w; i += stepval) {
d.drawFastVLine(i + x , y + h + 1, 5, textcolor);
// draw lables
// d.setTextSize(1);
d.setTextColor(textcolor, backcolor);
d.setCursor(i + x , y + h + 10);
// addling a small value to eliminate round off errors
// this val may need to be adjusted
data = ( i * (inc / stepval)) + loval + 0.00001;
d.println(Format(data, dig, dec));
}
}
// compute level of bar graph that is scaled to the width and the hi and low vals
// this is needed to accompdate for +/- range capability
// draw the bar graph
// write a upper and lower bar to minimize flicker cause by blanking out bar and redraw on update
level = (w * (((curval - loval) / (hival - loval))));
d.fillRect(x + level + 1, y + 1, w - level - 2, h - 2, voidcolor);
d.fillRect(x + 1, y + 1 , level - 1, h - 2, barcolor);
// write the current value
d.setTextColor(textcolor, backcolor);
// d.setTextSize(2);
d.setCursor(x + w + 10 , y + 5);
d.println(Format(curval, dig, dec));
}

/*

function to draw a cartesian coordinate system and plot whatever data you want
just pass x and y and the graph will be drawn

huge arguement list
&d name of your display object
x = x data point
y = y datapont
gx = x graph location (lower left)
gy = y graph location (lower left)
w = width of graph
h = height of graph
xlo = lower bound of x axis
xhi = upper bound of x asis
xinc = division of x axis (distance not count)
ylo = lower bound of y axis
yhi = upper bound of y asis
yinc = division of y axis (distance not count)
title = title of graph
xlabel = x asis label
ylabel = y asis label
&redraw = flag to redraw graph on first call only
color = plotted trace colour
*/

void Graph(TFT_eSPI &d, long int x, long int y, long int gx, long int gy, long int w, long int h, long int xlo, long int xhi, long int xinc, long int ylo, long int yhi, long int yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int pcolor, unsigned int tcolor, unsigned int bcolor, boolean &redraw)
{
//if (redraw1==true){redraw=true;}
double ydiv, xdiv;
// initialize old x and old y in order to draw the first point of the graph
// but save the transformed value
// note my transform funcition is the same as the map function, except the map uses long and we need doubles
//static double ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
//static double oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
double i;
double temp;
int rot, newrot;

if (redraw == true) {
redraw = false;
ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale
for ( i = ylo; i <= yhi; i += yinc) {
// compute the transform
temp = (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
if (i == 0) {
d.drawLine(gx, temp, gx + w, temp, acolor);
}
else {
d.drawLine(gx, temp, gx + w, temp, gcolor);
}
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(gx - 40, temp);
// precision is default Arduino--this could really use some format control
int strip =i;
d.println(strip);
}
// draw x scale
for (i = xlo; i <= xhi; i += xinc) {
// compute the transform
temp = (i - xlo) * ( w) / (xhi - xlo) + gx;
if (i == 0) {
d.drawLine(temp, gy, temp, gy - h, acolor);
}
else {
d.drawLine(temp, gy, temp, gy - h, gcolor);
}
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(temp, gy + 10);
// precision is default Arduino--this could really use some format control
//int strip =(i/.66666666666666666666);
int strip=(i/2)/3600;
d.println(strip);
}
//now draw the labels
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(gx , gy - h - 30);
d.println(title);
d.setTextSize(0);
d.setTextColor(acolor, bcolor);
d.setCursor(gx , gy + 20);
d.println(xlabel);
d.setTextSize(0);
d.setTextColor(acolor, bcolor);
d.setCursor(gx - 30, gy - h - 10);
d.println(ylabel);
}
//graph drawn now plot the data
// the entire plotting code are these few lines...
// recall that ox and oy are initialized as static above
x = (x - xlo) * ( w) / (xhi - xlo) + gx;
y = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
d.drawLine(ox, oy, x, y, pcolor);
d.drawLine(ox, oy + 1, x, y + 1, pcolor);
d.drawLine(ox, oy - 1, x, y - 1, pcolor);
ox = x;
oy = y;
}

void Graph2(TFT_eSPI &d, long int x1, long int y, long int gx, long int gy, long int w, long int h, long int xlo, long int xhi, long int xinc, double ylo, long int yhi, long int yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int pcolor, unsigned int tcolor, unsigned int bcolor, boolean &redraw)
{
//if (redraw1==true){redraw=true;}
double ydiv, xdiv;
// initialize old x and old y in order to draw the first point of the graph
// but save the transformed value
// note my transform funcition is the same as the map function, except the map uses long and we need doubles
//static double ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
//static double oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
double i;
double temp;
int rot, newrot;

if (redraw == true) {
redraw = false;
ox2 = (x - xlo) * ( w) / (xhi - xlo) + gx;
oy2 = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale
for ( i = ylo; i <= yhi; i += yinc) {
// compute the transform
temp = (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
if (i == 0) {
d.drawLine(gx, temp, gx + w, temp, acolor);
}
else {
d.drawLine(gx, temp, gx + w, temp, gcolor);
}
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(gx - 40, temp);
// precision is default Arduino--this could really use some format control
int strip =i;
d.println(strip);
}
// draw x scale
for (i = xlo; i <= xhi; i += xinc) {
// compute the transform
temp = (i - xlo) * ( w) / (xhi - xlo) + gx;
if (i == 0) {
d.drawLine(temp, gy, temp, gy - h, acolor);
}
else {
d.drawLine(temp, gy, temp, gy - h, gcolor);
}
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(temp, gy + 10);
// precision is default Arduino--this could really use some format control
//int strip =(i/.66666666666666666666);
int strip=(i/2)/3600;
d.println(strip);
}
//now draw the labels
d.setTextSize(0);
d.setTextColor(tcolor, bcolor);
d.setCursor(gx , gy - h - 30);
d.println(title);
d.setTextSize(0);
d.setTextColor(acolor, bcolor);
d.setCursor(gx , gy + 20);
d.println(xlabel);
d.setTextSize(0);
d.setTextColor(acolor, bcolor);
d.setCursor(gx - 30, gy - h - 10);
d.println(ylabel);
}
//graph drawn now plot the data
// the entire plotting code are these few lines...
// recall that ox and oy are initialized as static above
x = (x - xlo) * ( w) / (xhi - xlo) + gx;
y = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
d.drawLine(ox2, oy2, x, y, pcolor);
d.drawLine(ox2, oy2 + 1, x, y + 1, pcolor);
d.drawLine(ox2, oy2 - 1, x, y - 1, pcolor);
ox2 = x;
oy2= y;
}`

@Bodmer
Copy link
Owner

Bodmer commented Apr 1, 2019

Thanks for the info. I will have a look.

@Bodmer Bodmer closed this as completed Apr 1, 2019
@Alexandre2003
Copy link

Hello friend, well I saw that you passed these information to Bodmer look I really need to create vertical and horizontal bars I tried with the code that you described there above but it didn't work I'm a beginner and it was difficult for me I asked Bodmer for help but I went iguinorado kkkk if you can help me or give me a semi finished condition i will be forever grateful to you sorry for the inconvenience ok i'm from brazil

Att Alexandre Guaita

#3 (comment)

@Bodmer
Copy link
Owner

Bodmer commented Mar 29, 2020

Look here.

@sorriso93
Copy link
Author

Ciao, you can also look into this example

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

No branches or pull requests

3 participants