Here is a example of a graphing function that I adapted for a Digole display (320x240). It graphs a temporal series on the screen. In this case, it was to display current measured via an Adafruit INA219 I2C current/voltage sensor. All the work is done by the Graph() function.
Note that the digole library referenced is an extended library I created to add extra graphics primitives (triangle, filled triangle, ellipse, filled ellipse, etc.). This library is not required and the unmodified Digole library can be substituted. Also, this code was writte for a Particle Photon so the includes at the top may vary based on the target platform.
#include "ina219Spark.h"
#include "math.h"
#define _Digole_Serial_UART_
#include "DigoleGeo.h"
DigoleSerialDisp disp(&Serial1, 115200);
//Colours defined as 8-bit value RRRG GGBB
#define VGA_BLACK 0x00
#define VGA_WHITE 0x01
#define VGA_BLUE 0x03
#define VGA_DARKRED 0x20
#define VGA_RED 0xE0
#define VGA_GREEN 0x1C
#define VGA_LIME 0x14
#define VGA_YELLOW 0xFC
Adafruit_INA219 USBprobe;
unsigned long samplingTime;
int ina219Mode = 2; // 32V, 2A to start
// this is the only external variable used by the graph
// it's a flat to draw the coordinate system only on the first pass
bool display = true;
int count = 0;
void Graph(DigoleSerialDisp &d, double x, double y, double gx, double gy, double w, double h, double xlo, double xhi, double xinc, double ylo, double yhi, double yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int pcolor, unsigned int tcolor, unsigned int bcolor, boolean &redraw);
void setup()
{
Serial.begin(9600);
disp.begin();
disp.setRotation(0);
disp.clearScreen();
disp.disableCursor();
USBprobe.begin();
display = true;
samplingTime = millis();
}
void loop()
{
float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power = 0;
if ((millis() - samplingTime) >= 2000) {
shuntvoltage = USBprobe.getShuntVoltage_mV();
busvoltage = USBprobe.getBusVoltage_V();
current_mA = USBprobe.getCurrent_mA();
loadvoltage = (busvoltage + (shuntvoltage / 1000));
power = (loadvoltage * current_mA)/1000;
if (count < 270) {
Graph(disp, 270-count, current_mA, 40, 230, 310, 200, 0, 290, 1, 0, 15.0, 1, "Current", "x", "Amps", VGA_BLACK, VGA_BLUE, VGA_LIME, BLACK, VGA_WHITE, display);
count++;
}
else {
disp.clearScreen();
display = true;
count = 0;
}
samplingTime = millis();
}
}
/*
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
gcolor = graph line colors
acolor = axi ine colors
pcolor = color of your plotted data
tcolor = text color
bcolor = background color
&redraw = flag to redraw graph on fist call only
*/
void Graph(DigoleSerialDisp &d, double x, double y, double gx, double gy, double w, double h, double xlo, double xhi, double xinc, double ylo, double yhi, double yinc, String title, String xlabel, String ylabel, unsigned int gcolor, unsigned int acolor, unsigned int pcolor, unsigned int tcolor, unsigned int bcolor, boolean &redraw) {
static double ox, oy;
double ydiv, xdiv;
// note my transform function is the same as the map function, except the map uses long and we need doubles
double i;
double temp;
int rot, newrot;
if (redraw == true) {
d.setColor(bcolor);
d.drawBox(0,0,320,240);
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.setColor(acolor);
d.drawLine(gx, temp, gx + w, temp);
}
else {
d.setColor(gcolor);
d.drawLine(gx, temp, gx + w, temp, gcolor);
}
d.setFont(6);
d.setColor(bcolor);
d.setBgColor();
d.setColor(tcolor);
d.setTextPosAbs((gx - 40, temp);
// precision is default Arduino--this could really use some format control
d.println(i);
}
// draw x scale
for (i = xlo; i <= xhi; i += xinc) {
// compute the transform
temp = (i - xlo) * ( w) / (xhi - xlo) + gx;
if (i == 0) {
d.setColor(acolor);
d.drawLine(temp, gy, temp, gy - h);
}
else {
d.setColor(gcolor);
d.drawLine(temp, gy, temp, gy - h);
}
d.setFont(6);
d.setColor(bcolor);
d.setBgColor();
d.setColor(tcolor);
d.setTextPosAbs((temp, gy + 10);
// precision is default Arduino--this could really use some format control
d.println(i);
}
//now draw the labels
d.setFont(10);
d.setColor(bcolor);
d.setBgColor();
d.setColor(tcolor);
d.setTextPosAbs((gx , gy - h - 30);
d.println(title);
d.setFont(6);
d.setColor(acolor);
d.setBgColor();
d.setColor(bcolor);
d.setTextPosAbs((gx , gy + 20);
d.println(xlabel);
//d.setFont(6);
//d.setColor(acolor);
//d.setBgColor();
//d.setColor(bcolor);
d.setTextPosAbs((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.setColor(pcolor);
d.drawLine(ox, oy, x, y);
d.drawLine(ox, oy + 1, x, y + 1);
d.drawLine(ox, oy - 1, x, y - 1);
ox = x;
oy = y;
}
/*
End of graphing functioin
*/