Kris, thank you for sharing this code. it's very useful. regarding the flickering of the needle: the simplest improvement (if you haven't done it already) is to compare the value being passed into the function with the value on the previous call to the function. if they are the same then nothing has changed so no need to redraw the needle. In addition, I would recommend that users apply a significant change analysis to the variables they are monitoring. no need to do this in the library. it should be an application feature. so, for example, if measuring a voltage and the change is less than (for example) 1% then do not call the graph functions at all. Thanks again.
Thank you so much for this! This also works with the Adafruit 2.8" tft (1770) on an Arduino Uno and the Adafruit_ILI9341 library with a few tweaks. You need to make the graphs smaller of course, but it still looks very nice. Just replace all the references to HX8357 with ILI9341 and change the pins according to the Adafruit tutorial.
I wish! It faults for Adafruit_HX8357.h: No such file or dir... I tried finding it, and the best I get is a notepad file. I copied that and saved it as the .h file, but I still can't get it to work. If this were easy, everyone would be doing it, but No, it's freakin really difficult! And if I get this figured out, I'm sure it'll fault out for the next thing I'm missing. Hours upon hours wasted.... Note: I may be frustrated!
Glad I could help. If you start running out of memory, check out Teensy 4.0--very compatible with Arduino code, fast and tons of memory. Keep inventing!
A tip and BIG thanks to Kris! This is exactly what I wanted as I fine tune sensor processing for Assistive Technology use. The tip - change the Draw functions to use the parent class, i.e., "DrawBarChartH(Adafruit_GFX & d, ..." then include Adafruit_GFX.h - no need to change for each new display. I can still pass my tft object by reference, which is an instance of my specific device and a child class of Adafruit_GFX. I copied the code to a .cpp and .h file as I migrate this to a library, and I have a graph_st struct that contains all of the attributes and the redraw flag. The attributes (colors, redraw, scaling) can be manipulated as I evaluate the sensor data in different routines until I'm ready to redraw everything at the end of my loop. I invoke drawWhatever(Adafruit_GFX & d, graph_st & graph) with drawWhatever(tft, graph1) etc. and it splits out all of the arguments. Again, MANY, MANY THANKS!
Thanks for the tip that really is an outstanding tip. I have since moved away from Arduino sand I now use teensies exclusively. Mainly faster processors 32-bit bus with and more RAM memory. I have Rewritten this graphing function into an actual library that only runs on the ili_934I_t3 driver. My new library is much better but again only runs on a Teensy
Thanks for the great tutorial. Just two questions, please. (How) can I realize a "curved" bar graph? And ... is it possible to define the center of the dial graph "outside" the display?
Hi and thanks for the info! Question - if I wanted to create a bar graph that changed backgrounds like a "fuel level gauge" from green, to yellow, to red, so that at the 2/3 mark, the background appears yellow, then at the 1/3 mark the background appears red, would that be three "different" graphs superimposed on the same area of the screen, or is there a way to make 3x background colors for the same graph? Or perhaps a graph with a black background, where the actual gauge bar itself changed to green/yellow/red at the different levels?
Very Handy! Thank You very much. I modified it to have a null center needle instead of bar. I also modified it so it does not need the Adafruit GFX Lib.
thank you so much for this, i have reused your code, for my greensand moisture level measurer! i hope to make a video about it, i'll be sure to link to your video and mention you. many many thanks!
Thank you very much for sharing this with all of us! you made my day!! :) As I am reading the comments I am glad you made some improvements. :) Hopefully, when I will try it the code will be flawless. :)
I ended up placing most of your function arguments into a structure: struct grafix { int x; // upper left coordinate horizontal int y; // upper left coordinate vertical int w; // width of graph int h; // height of graph int minX; // minimum graph value, can be negative int maxX; // maximum graph value float inc; // scale division between lo and hi float currentValue; // Current value int digitTotal; // total digits displayed, not counting decimal point int decimals; // digits after decimal point int barColor; // Color for bar int backBar; // Background bar color int border; // Border color int textColor; // Color for text int backFill; // Background color for entire graph char label[30]; // Label text } myG; I also changed the data type for several arguments, as ints are processed faster than floats. I used this structure mainly for the bar graph, as that's what my needs are for. Also, I needed a way to suppress the tick marks for all but the last bar in a stacked bar graph. I now have it split so the axes are done on one pass and the data on anther. An example of a stacked bar graph (for SWR on ham radio bands), see: s283.photobucket.com/user/econjack/media/AllBandMinSWR.jpg.html?sort=3&o=0
I'm not an expert, but about the flickering of the dial thing: It looks like the needle is erased first and then redrawn. I think the new position should be drawn before the old position is erased. The tricky part would probably be to erase the old position without erasing anything that should not be erased… (and when I say erase I mean redraw the background, kind of)
I know about UTFT library under arduino, but before purchasing any TFT from random website how I can be sure that this TFT is going to work with UTFT library, could you please help me with that. I am looking for 4.3 inch, 5 inch and 7 inch TFTs with resistive or capacitive touch.
The dial redraw is effective, but I ran into the same type of problem for that sort of movement. The need to redraw the entire needle twice with each update seems to be the only bottleneck. Instead of redrawing the entire needle, you could devise some math to figure out what DOESNT need to be drawn and draw/redraw what does. It could save you from needing to update at least 50 percent of your pixels (by my estimation) making it at least twice as fast.
@@KrisKasprzak Today I'm using the ili9341 SPI screen with Bodmer's TFE_eSPI library on an ESP32 with the screen running at 60MHZ and the processor running at 240MHZ. The performance is insane. At 60FPS operation, I'm not too worried about delay flicker anymore. I'm still impressed you could get your system to work with a microcontroller at 8mhz 8bit. As far as flicker goes, I'm trying to figure out how to read the display through the MISO pin.
I've done some more work which splits the axis and label drawing from the actual data plotting. There's no reason to pass the string data and other fixed parameters on each call. Also, I changed from the String class to C char arrays because of reduced overhead.
Great sketch. What about drawing non linear scales, is that possible? eg in Ham radio an SWR scale. eg 1 is at left side, 3 is middle, and infinity at right side of a horizontal bar graph
It would be relatively simple to change the scale to show log or other. Probably a few lines of code in the draw scale section, and of you are passing data in at the drawn scale, it should display w/o any changes. I'd have to mess with it though.
thank you !! this is awesome!! every display code i have seen with graphs and bars are always getting the data from the potentiometer,or reading a pin, and i have yet to see the data collected or created during the sketch being displayed.. for instance if i had a radiation meter counting clicks and converting to mR/hr. how would one go about display that info? any help would greatly appreciated
I got your function to work with the MCUFRIEND_kbv in conjunction with the Adafruit GFX library. Now that I have it working, I want to see the impact that pre-filling the x,y array and having a single call to Graph() makes on the speed and, perhaps, flicker.
code works great. i have 4 vertical bar charts but they all read from the same A0 pin. how do you separate each chart to read from a different analog pins
you can, just read the value from each pin into it's own variable then have a call to the graph function for each variable, set the coordinates for each graph. Don't forget to have a bool redraw for each graph.
Hi, amazing code! Thanks for sharing. I had one question though... For some reason the compiler does not recognize "Format" in the line: d.println(Format(data, dig, dec)); When i comment it out, everything else works. I tried searching the Arduino site for the println function and all it says is the format for println is supposed to be println(val, foramt). Any insight into why this is happening. Any help would be greatly appreciated!
+TBCman99 My mistake. I wrote a function called Format(number, digits, decimals) so I could really control the display but forgot to include that function and so it pads spaces to keep the decimal lined up. // example // dog = 98.9876655 // cat = Format(Dog,4,3); // dog = " 98.988 // Format(Data, Digits, DecimalPlaces); String Format(double val, int dec, int dig ) { int addpad = 0; char sbuf[20]; String condata = (dtostrf(val, dec, dig, sbuf)); int slen = condata.length(); for ( addpad = 1; addpad
I have a question... can I use this to measure the voltage that is being generated when I press the screen? I am using a adafruit 2.8 tft shield v2 capacitive touch screen
Hi Kris, I love so much what you did and thank you for the code. I bought the Adafruit display and the Arduino UNO just to use your nice code, unfortunately didn't work for me, I do not know what else to do, I downloaded the libraries in you link and the code but could not make it work, it give me errors and will not compile . Any suggestion please ?
Is the link at the end still active? I see a box saying "Invalid link 'Code'". Wonder if the flickering is eliminated by using a faster board, such as an ESP32?
Hello, its nice gauges, if i upload it to my UNO it say exit status 1 'u8g2' was not declared in this scope ? any help with that ? Im trying to run it on 2.8 TFT display.
I got opened another arduino window and that was problem for u8g2 error. Now i compile and upload but i got white screen, I use www.velleman.eu/products/view/?id=435582 screen, and when i insert in void loop section Serial.println(volts); Serial.println(bvolts); Serial.println(pmvolts); Serial.println(analogRead(A0)); i got some numbers running that means program is running but i have white screen. Any help with that, whit some other library when i get white screen i need to insert 0X9341 in tft.begin(0x9341) and i get the pictures, maybe here is the same simple solution ? Thanks for help, :)
Step 1 forget my code and get your display working. Try the sample programs that come with libraries. Until you get the display working, this code can't fix that.
I have used these libraries with just plays based on the 9341 ship you have to choose change a few lines of code to utilise the right library and initialisation
If you have a adafruit libraries for that chip then yes it will. I use this code with the adafruit 8357 libraries and it works fine. I also use it with the ili_9341_T3 libraries for teenseys.
Sir ,I already know PROGRAM array in .c file uses for drawbitmap() function which contain rgb565 color. How can i convert that PROGRAM array element into rgb color for drawpixel(). Thanks for Reply..
Hard to follow what you are asking and w/o knowing what you are trying to do i'm really guessing at what your problem is. If you have an array of you converted RAW image, why not loop through each row, getting each pixel from each column and calling drawPixel(). for i = 0 to rows for j=0 to cols drawpixel(i,j,Get_RGB_FROM_ARRAY_AT_i_j)
AndrewMascoloJr He did, some fairly advanced geometric math is required to only redraw IF changed, THEN to calculate the pixels that need to be drawn VERSES the pixels already existing (kind of difficult). There can also be a PID for the needle position to allow smooth transition between changes. By using a few (drawLine) commands might be able to speed up the needle draw. Drawing a triangle is harder for a computer than drawing a rectangle. Use a small black triangle at the tip of the needle to give it a point.
Thank you so much! I bouth a Sain Smart 4.3'' TFT and I've been looking for information but I can not find anything. My question is.... Is it really necessary to use the shield with the screen 4.3'' TFT?
Kris, thank you for sharing this code. it's very useful. regarding the flickering of the needle: the simplest improvement (if you haven't done it already) is to compare the value being passed into the function with the value on the previous call to the function. if they are the same then nothing has changed so no need to redraw the needle. In addition, I would recommend that users apply a significant change analysis to the variables they are monitoring. no need to do this in the library. it should be an application feature. so, for example, if measuring a voltage and the change is less than (for example) 1% then do not call the graph functions at all.
Thanks again.
Thank you so much for this!
This also works with the Adafruit 2.8" tft (1770) on an Arduino Uno and the Adafruit_ILI9341 library with a few tweaks. You need to make the graphs smaller of course, but it still looks very nice. Just replace all the references to HX8357 with ILI9341 and change the pins according to the Adafruit tutorial.
Good tips on using this with a different library
I wish! It faults for Adafruit_HX8357.h: No such file or dir... I tried finding it, and the best I get is a notepad file. I copied that and saved it as the .h file, but I still can't get it to work. If this were easy, everyone would be doing it, but No, it's freakin really difficult! And if I get this figured out, I'm sure it'll fault out for the next thing I'm missing. Hours upon hours wasted.... Note: I may be frustrated!
I know this is a bit old but every little bit counts. Thanks so much for your video efforts, this takes a lot of time to put together!
Glad I could help. If you start running out of memory, check out Teensy 4.0--very compatible with Arduino code, fast and tons of memory.
Keep inventing!
@@KrisKasprzak Thanks Kris, I'll give them a try. I've never played with them and frankly didn't know how powerful they really are! 👍
You make the world a better place.
+Nathan Brewer Glad you enjoyed this. Post a project, i'd like to see what others are doing.
A tip and BIG thanks to Kris! This is exactly what I wanted as I fine tune sensor processing for Assistive Technology use.
The tip - change the Draw functions to use the parent class, i.e., "DrawBarChartH(Adafruit_GFX & d, ..." then include Adafruit_GFX.h - no need to change for each new display. I can still pass my tft object by reference, which is an instance of my specific device and a child class of Adafruit_GFX.
I copied the code to a .cpp and .h file as I migrate this to a library, and I have a graph_st struct that contains all of the attributes and the redraw flag. The attributes (colors, redraw, scaling) can be manipulated as I evaluate the sensor data in different routines until I'm ready to redraw everything at the end of my loop.
I invoke drawWhatever(Adafruit_GFX & d, graph_st & graph) with drawWhatever(tft, graph1) etc. and it splits out all of the arguments. Again, MANY, MANY THANKS!
Thanks for the tip that really is an outstanding tip. I have since moved away from Arduino sand I now use teensies exclusively. Mainly faster processors 32-bit bus with and more RAM memory. I have Rewritten this graphing function into an actual library that only runs on the ili_934I_t3 driver. My new library is much better but again only runs on a Teensy
I have posted the .ino files to this function and another for drawing a Cartesian style graph on GITHUB github.com/KrisKasprzak/GraphingFunction
Thanks for the great tutorial. Just two questions, please. (How) can I realize a "curved" bar graph? And ... is it possible to define the center of the dial graph "outside" the display?
Hi and thanks for the info! Question - if I wanted to create a bar graph that changed backgrounds like a "fuel level gauge" from green, to yellow, to red, so that at the 2/3 mark, the background appears yellow, then at the 1/3 mark the background appears red, would that be three "different" graphs superimposed on the same area of the screen, or is there a way to make 3x background colors for the same graph? Or perhaps a graph with a black background, where the actual gauge bar itself changed to green/yellow/red at the different levels?
Very Handy! Thank You very much. I modified it to have a null center needle instead of bar. I also modified it so it does not need the Adafruit GFX Lib.
thank you so much for this, i have reused your code, for my greensand moisture level measurer! i hope to make a video about it, i'll be sure to link to your video and mention you. many many thanks!
glad I could help.
Thank you very much for sharing this with all of us! you made my day!! :) As I am reading the comments I am glad you made some improvements. :) Hopefully, when I will try it the code will be flawless. :)
You’re doing God’s work
I ended up placing most of your function arguments into a structure:
struct grafix {
int x; // upper left coordinate horizontal
int y; // upper left coordinate vertical
int w; // width of graph
int h; // height of graph
int minX; // minimum graph value, can be negative
int maxX; // maximum graph value
float inc; // scale division between lo and hi
float currentValue; // Current value
int digitTotal; // total digits displayed, not counting decimal point
int decimals; // digits after decimal point
int barColor; // Color for bar
int backBar; // Background bar color
int border; // Border color
int textColor; // Color for text
int backFill; // Background color for entire graph
char label[30]; // Label text
} myG;
I also changed the data type for several arguments, as ints are processed faster than floats. I used this structure mainly for the bar graph, as that's what my needs are for. Also, I needed a way to suppress the tick marks for all but the last bar in a stacked bar graph. I now have it split so the axes are done on one pass and the data on anther. An example of a stacked bar graph (for SWR on ham radio bands), see:
s283.photobucket.com/user/econjack/media/AllBandMinSWR.jpg.html?sort=3&o=0
+Jack Purdum very cool, glad this code gave you a start.
I'm not an expert, but about the flickering of the dial thing: It looks like the needle is erased first and then redrawn. I think the new position should be drawn before the old position is erased. The tricky part would probably be to erase the old position without erasing anything that should not be erased… (and when I say erase I mean redraw the background, kind of)
+Johnny Rosenberg tried that, still flickering but not as bad. I sure wish these displays had double buffers...
I know about UTFT library under arduino, but before purchasing any TFT from random website how I can be sure that this TFT is going to work with UTFT library, could you please help me with that.
I am looking for 4.3 inch, 5 inch and 7 inch TFTs with resistive or capacitive touch.
The dial redraw is effective, but I ran into the same type of problem for that sort of movement. The need to redraw the entire needle twice with each update seems to be the only bottleneck. Instead of redrawing the entire needle, you could devise some math to figure out what DOESNT need to be drawn and draw/redraw what does. It could save you from needing to update at least 50 percent of your pixels (by my estimation) making it at least twice as fast.
billybbob18 I've actually put some code in there to only draw the needle when it moves made a huge difference
@@KrisKasprzak Today I'm using the ili9341 SPI screen with Bodmer's TFE_eSPI library on an ESP32 with the screen running at 60MHZ and the processor running at 240MHZ. The performance is insane. At 60FPS operation, I'm not too worried about delay flicker anymore. I'm still impressed you could get your system to work with a microcontroller at 8mhz 8bit. As far as flicker goes, I'm trying to figure out how to read the display through the MISO pin.
I've done some more work which splits the axis and label drawing from the actual data plotting. There's no reason to pass the string data and other fixed parameters on each call. Also, I changed from the String class to C char arrays because of reduced overhead.
Great sketch. What about drawing non linear scales, is that possible?
eg in Ham radio an SWR scale. eg 1 is at left side, 3 is middle, and infinity at right side of a horizontal bar graph
It would be relatively simple to change the scale to show log or other. Probably a few lines of code in the draw scale section, and of you are passing data in at the drawn scale, it should display w/o any changes. I'd have to mess with it though.
Thanks for sharing. Much appreciated.
Glad I could help.
thank you !! this is awesome!! every display code i have seen with graphs and bars are always getting the data from the potentiometer,or reading a pin, and i have yet to see the data collected or created during the sketch being displayed.. for instance if i had a radiation meter counting clicks and converting to mR/hr. how would one go about display that info? any help would greatly appreciated
What is your independent variable?
Also, if you can switch to a Teensy MCU, I have a better library for drawing graphs.
im wanting to be able to display the mr/hr as if it were an old analog survey meter.. like the nds2000
maybe a line. looks like the wedge is being calculated and drawn. on my youtube screen, i can see the wedge being painted
Very nice, thanks for sharing.
Glad I could help.
I got your function to work with the MCUFRIEND_kbv in conjunction with the Adafruit GFX library. Now that I have it working, I want to see the impact that pre-filling the x,y array and having a single call to Graph() makes on the speed and, perhaps, flicker.
+Jack Purdum cool if it works, please let us know.
code works great. i have 4 vertical bar charts but they all read from the same A0 pin. how do you separate each chart to read from a different analog pins
you can, just read the value from each pin into it's own variable then have a call to the graph function for each variable, set the coordinates for each graph. Don't forget to have a bool redraw for each graph.
I'm only getting a white screen on my LCD TFT.
Hi, amazing code! Thanks for sharing.
I had one question though...
For some reason the compiler does not recognize "Format" in the line:
d.println(Format(data, dig, dec));
When i comment it out, everything else works. I tried searching the Arduino site for the println function and all it says is the format for println is supposed to be println(val, foramt).
Any insight into why this is happening. Any help would be greatly appreciated!
+TBCman99 My mistake. I wrote a function called Format(number, digits, decimals) so I could really control the display but forgot to include that function and so it pads spaces to keep the decimal lined up.
// example
// dog = 98.9876655
// cat = Format(Dog,4,3);
// dog = " 98.988
// Format(Data, Digits, DecimalPlaces);
String Format(double val, int dec, int dig ) {
int addpad = 0;
char sbuf[20];
String condata = (dtostrf(val, dec, dig, sbuf));
int slen = condata.length();
for ( addpad = 1; addpad
+Kris Kasprzak ahhh, I see. Thanks so much for clearing that up!! Much appreciated! :)
I have a question... can I use this to measure the voltage that is being generated when I press the screen? I am using a adafruit 2.8 tft shield v2 capacitive touch screen
You can measure voltages, but i'm not sure how your display sends touch info. I suspect it's not a simple analog voltage.
Whats the fastest refresh rate i can get out of these display
Does it help the flashing if then needle is created as a sprite?
interesting idea. In my implementations, i only update the needle if the data was change by a certain amount.
Hi Kris, I love so much what you did and thank you for the code. I bought the Adafruit display and the Arduino UNO just to use your nice code, unfortunately didn't work for me, I do not know what else to do, I downloaded the libraries in you link and the code but could not make it work, it give me errors and will not compile . Any suggestion please ?
You will need to be more specific as to what the errors are
Thank you for the fast reply. I got warnning: spurious .ghub folder in 'Adafruit 2.8" display Library' Library
@@florentinpolmolea7961 Sounds like something was not installed inside Arduino.
Is the link at the end still active? I see a box saying "Invalid link 'Code'".
Wonder if the flickering is eliminated by using a faster board, such as an ESP32?
I just looked at the link and it will allow me to download, it does say, unable to generate a preview.
This is great!
Hello,
its nice gauges,
if i upload it to my UNO it say
exit status 1
'u8g2' was not declared in this scope
?
any help with that ?
Im trying to run it on 2.8 TFT display.
I have no idea why. my functions do not use this library. I suspect you are trying compile with libraries that require the U8 lib.
I got opened another arduino window and that was problem for u8g2 error.
Now i compile and upload but i got white screen, I use www.velleman.eu/products/view/?id=435582 screen, and when i insert in void loop section
Serial.println(volts);
Serial.println(bvolts);
Serial.println(pmvolts);
Serial.println(analogRead(A0));
i got some numbers running that means program is running but i have white screen.
Any help with that, whit some other library when i get white screen i need to insert 0X9341 in tft.begin(0x9341) and i get the pictures, maybe here is the same simple solution ?
Thanks for help, :)
Step 1 forget my code and get your display working. Try the sample programs that come with libraries. Until you get the display working, this code can't fix that.
Will this work with TFT_320QVT_9341 ?
I have used these libraries with just plays based on the 9341 ship you have to choose change a few lines of code to utilise the right library and initialisation
Link is out of date. Just Google Kris and his UA-cam channel for an updated video and comments.
As of January 2018, the link provided does not work.
not Texas hmmmm i was just able to download graphing.ino.
sooooo helpfulll
Thanks for the video tutorial and the code!
I have a Display 3.5 inch 320 x 480 ILI9488, will it work? Thank you
If you have a adafruit libraries for that chip then yes it will. I use this code with the adafruit 8357 libraries and it works fine. I also use it with the ili_9341_T3 libraries for teenseys.
@@KrisKasprzak Thank you; I will test.
Thanks a lot! :)
Nice work.
Is it possible covert raw image with drawpixel() function in utft??
Shapath Sust draw pixel simply draws a DOT on a screen at an XY location given a color
if the color value come from image pixel of raw image then is it possible??
probably, drawPixel needs location and RGB value.
Sir ,I already know PROGRAM array in .c file uses for drawbitmap() function which contain rgb565 color. How can i convert that PROGRAM array element into rgb color for drawpixel().
Thanks for Reply..
Hard to follow what you are asking and w/o knowing what you are trying to do i'm really guessing at what your problem is. If you have an array of you converted RAW image, why not loop through each row, getting each pixel from each column and calling drawPixel().
for i = 0 to rows
for j=0 to cols
drawpixel(i,j,Get_RGB_FROM_ARRAY_AT_i_j)
Very nice.
thank you for sharing
You're very welcome.
I get "invalid link "code"" when trying to download.
Google User I am getting the same but am using IPad.
I am going to get onto the tower computer as that could be the reason.
You can increase your speed by only drawing when something has changed.
AndrewMascoloJr
He did, some fairly advanced geometric math is required to only redraw IF changed, THEN to calculate the pixels that need to be drawn VERSES the pixels already existing (kind of difficult). There can also be a PID for the needle position to allow smooth transition between changes. By using a few (drawLine) commands might be able to speed up the needle draw. Drawing a triangle is harder for a computer than drawing a rectangle. Use a small black triangle at the tip of the needle to give it a point.
Does the code work for 4.3'' TFT?
If you are using the Adafruit libraries, then yes. If others I'm guessing the methods will be different and may only need some renaming.
Thank you so much!
I bouth a Sain Smart 4.3'' TFT and I've been looking for information but I can not find anything. My question is.... Is it really necessary to use the shield with the screen 4.3'' TFT?
You don't need the shield if you know what the pins are, do you have a link to the display?
No, can you please send me a link?
Because I'm having trouble turning it on...
Thank you!
Link to free code no longer works. :-(
Odd, you can't get to the location? github.com/KrisKasprzak/GraphingFunction
Thanks for sharing. Much Much appreciated.
Glad I could help