Hi Kris, Great project but a bit out of date on Library usage. In order to make this work people will need to make the following changes: Add this info to the beginning of the code: #include #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // On an arduino UNO: A4(SDA), A5(SCL) // On an arduino MEGA 2560: 20(SDA), 21(SCL) // On an arduino LEONARDO: 2(SDA), 3(SCL), ... #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); Remove the following code: #define SSD1306_128_64 #define READ_PIN A0 #define OLED_RESET A4 #define LOGO16_GLCD_HEIGHT 16 #define LOGO16_GLCD_WIDTH 16 // create the display object Adafruit_SSD1306 display(OLED_RESET); Then the code runs great!
Thanks for posting your tips. I'm sure my subs can make use of this. I posted that code some 5 years ago, and I've since moved on 2.8" color TFT,s with touch, hence I spend no time verifying the operation of these OLED's
Hi, Kris! Loved the video. It works well. I was wondering how refresh and start replotting once the data hits the end of the screen? Can you suggest a modification to the code? It would be very helpful.
I depends on how you want to continue.... 1) just erase the data and start drawing over or 2) have the grid "pan" so you can see previous data. for option 1 should be easy but will take some minor mods 1) upon the need to start over you will need to update the parameters in the function call 2) set the "redraw" variable to true--that will force a repaint 3) remember the last x value and you will have to offset the new plot area by that amount meaning 0 is no longer 0 it's now like 100 or what ever your last value was, when you call my DrawGraph function just change the x to x+offset and remember to add the offset to the range parameter, after resetting the "redraw flag" it will get you closer. Writing this from memory. Option #2 the pan one will take a bunch of changes--namely on a new point draw the grid area needs to pay--not hard, but probably more involved.
Kris Kasprzak, would you be able to increase your IDE font size in your next video. It's difficult to see. Otherwise, love the video. Thanks for sharing.
Just spent several hours trying to figure out why my display looks like it's putting a black line between every line. Therefor, only showing the top half of a full display. Otherwise it works great. I'm using a 128X64 OLED just like the one in the video. Any help would be greatly appreciated.
look in the Adafruit_SSD1306.h file. I suspect the wrong define is being used. Look for something like this.... // ONE of the following three lines must be #defined: // probably need to uncomment this line //#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen // probably need to comment out this line #define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen //#define SSD1306_96_16 ///< DEPRECATED: old way to specify 96x16 screen
@@KrisKasprzak thank you a lot, you helped me too. It was strange for me, that it needs changes in library code, but, it is deprecated approach now, and looks like in new constroctors you manually put in your project code width and height of display.
Cool, I too am using more and more of the TFT's--mostly the 2.8" versions. I've got them working with a Teensy 3.2 and have touch, and the SD card working. Took some hardware hacking though.
Thank you so much I don't much of arduini but how simple or hard o imposible would be to adapt these to graph data for a sensor that gives the data in i2c rather than analog values
Hi Sir! Thank you for sharing your function. So I was using this function on an 12c OLED (128x64) display. My problem though is that the title takes a lot of space, cutting the lower portion of the graph. I want to remove the title bar completely. How can I do that?
I got bit error with dual OLED interface with Arduino
3 года назад
The libraries used in these examples do not support Attiny85. I couldn't find anything related with creating graphs on Digispark/Attiny85 like you did on the video. Do you know any solution? Another question, is it possible to make pie chart like graphs which can be transformed into slices which also can be wider/narrower by a potentiometer like you just did? And even rotate the graph with another potentiometer or something else?
The APIs are just code written on code. For the 85, red the APIs and write the chunk you need into your 85 code... so no API needed. Pie graphs use Pythagorean theorem. a^2+b^2=c^2 and the edge of the pie is at "c" distance from 0,0. So, graph a line from 0,0 that has a slope of b/a and is c long.
hi again, Kris. How can display at the dial one, the actual value in numbers, besides de needle indication? . I have tried at the label place, but no result. Sorry for so many questions
Great! I want to graph two charts, barometric pressure at the top and Temp at the bottom. Same time scale but different Y axes. Is this possible? Regards
sure is. you will just need to create a second call to the graphing function, but with different screen coordinates, and its own Redraw variable. I've done this before, just very small graphs. you can also use 2 OLED displays and draw a single graph on each display. Same basic code implementation second graph: DrawBarChart(display2....) ruclips.net/video/yef23sJjiU0/видео.html
@@KrisKasprzak I've altered your code to store the graph Y contents into an array, then shift the plot position to make the cartesian graph 'scroll' as new entries are added. Cheers again!
sure the giant argument list has parameters for graph height and with. Look at the functions and find W and H, these are the graphs width, and height--just squeeze the height down to what you need. void DrawBarChartV(Adafruit_SSD1306 &d, double curval, double x , double y , double w, double h ,
@@KrisKasprzak I'm looking to use the dial. I see on the bar where to change it but I can't figure it out with the dial. Anyway you can send me a pic or something. Please!!
@@KrisKasprzak it would appear as though I have the same oled display as you. I've uploaded the code but the bottom half of the dial is cut off. Any way to fix this?
@@imgoingtwo2780 I think so. the default oled libs are for 128x32 look in your Adafruit_SSD1306.h and around line 29 un comment the #define SSD1306_128_64 and // #define SSD1306_128_32 like i have shown beow. // ONE of the following three lines must be #defined: #define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen // #define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
Hello. Thanks for making this available. Im trying to implement this to my project but im having trouble scaling it up for 1.3"oled. Can you give me some help?
This seems to be working for me,thanks! EDIT: it seems to update much slower then the example? Like only once per second or so . Ah , I need to set the delay to a shorter amount then the 1000. I also did the redraw for when it hits the end of the screen. Has anyone figured out how to make it pan/scroll so it keeps the valued and just inserts incoming values ? Couple of questions, can i shorten the time span for the envelope signal or the graph? EDIT: Figured out how to shorten the graph and the time. For example: DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, (CHANGE THIS -30), 25, 0, 1024, 512, 0, " And this if (x > 30) { Still that leaves how to make it sample faster , anything above a 6 hz sine wave gets turned into a triangle of some sortÐ Also can i somehow remove the measurement values and text only leaving the graph? If I wanted to run say 5 displays , do I need to get a teensy , seems weird that the arduino would almost max out on memory on one tiny display ...I am a beginner though so I might be wrong here ? I would also be cool to be able to use triggering somehow , so it can act more like a scope, whereas it would hold the waveform.My input signal is coming from a function generator and works cool , but would be nice to be able to trigger so it would not scroll.
Budhaditya Biswas it will definitely run on and Arduino I've had it working before, the only challenge you run into is the lack of RAM on those Unos and it makes it hard to use any other libraries for like SD cards and stuff never used to know to MCU not sure
Using the same hardware, the images do not appear fully, getting bigger than the display. How to solve this? When compiling appear errors: Arduino: 1.8.5 (Windows 10), Placa:"Arduino Nano, ATmega328P" OLEDGraphing:149: error: 'SSD1306_WHITE' was not declared in this scope OLEDGraphing:232: error: 'SSD1306_BLACK' was not declared in this scope Thanks! the explanations are excellent.
regarding the errors, open Adafruit_SSD1306.h and find the defines for the colors, my lib is #define SSD1306_BLACK 0, #define SSD1306_WHITE 1, #define SSD1306_INVERSE 2. I would change the ino to match what's listed in the .h. Regarding the wrong size, make sure this line in the Adafruit_SSD1306.h is uncommented #define SSD1306_128_64
there are also several areas in the Adafruit_SSD1306.cpp file that use that define, make sure you have all of them named correctly in the .ino, the .h, and the .cpp files.
Glad you got the #defines sorted out. I've since uploaded a new file that contains the sketch and the libs so others don't have to fight with that. in my loop() notice a line while (1) {} of x is > 100, this while is simply and infinite loop to "stop the code" by putting the code in an infinite loop (serial monitor will stop as well). You will need to implement your own way in processing what to do after x = 100, maybe redraw the graph and start over, maybe "pan" the graph so you can see previous values? curval = date to graph hahahaha type should say data to graph, which is basically the data point to be drawn on the screen.
try this loop, note that measuring a single point for display, then waiting is definitely not the best way to measure data. I would average as many readings as possible in the time interval the display--let me know if you need sample code. void loop(void) { // read some values and convert to volts bvolts = analogRead(A0); volts = (bvolts / 204.6 ) ; // draw the data on the graph DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, 100, 25, 0, 1024, 512, 0, "Bits vs Seconds", Redraw4); // if the data exceeds the graph range then reset the old graph markers and blank out only the graph area // note the selected values will need to be change if the size or location of the graph is changed if (x > 100) { ox = 30.0; oy = 50.0; x = 0.0; display.fillRect(31, 18, 75, 32, SSD1306_BLACK); display.display(); } delay(1000); // display every 1 second }
code to average the analog pin reads unsigned long OldTime; // best to move this line up where your other variable definitions are unsigned long counter; // best to move this line up where your other variable definitions are void loop(void) { // get as many reads as you can in the allotted time bvolts = bvolts + analogRead(A0); // add it to itself and average before display counter++; // check to see if the elapsed time exceeds the alloted time (note this is in milliseconds) if ((millis() - OldTime) > 1000) { // reset the old time counter to enable elapsed time computing OldTime = millis(); // if the code lands here, you must have read bvolts for 1000 ms // avarage the volts bvolts = bvolts / (double) counter; // draw the data on the graph DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, 100, 25, 0, 1024, 512, 0, "Bits vs Seconds", Redraw4); // reset everything bvolts = 0.0; counter = 0; // if the data exceeds the graph range then reset the old graph markers and blank out only the graph area // note the selected values will need to be change if the size or location of the graph is changed if (x > 100) { ox = 30.0; oy = 50.0; x = 0.0; display.fillRect(31, 18, 75, 32, SSD1306_BLACK); display.display(); } } }
Metal Coasters my displays are hard-coded colors cannot be changed I don't know of any others that can be changed they do make some small color ones though
again asking: no way to get more than the upper part of the display. I have tried to configure the 1306 .h file, but no results. My oled is AliExpress one 128x64, with 078 and 077 bridges, set for 0x3C. Of course I am almost a beginner. I do know that the solution is simple, but don't get it. I get the same problem on both 128x64 and 128 x32 displays. Any input, please?
Hey Kris,I noticed you didn't have anything for a license on that OLED code that I'd like to use for a project I'm building. I'd like to give credit where credit is due so if you want anything included please let me know.. Also, if you're into video editing you may want to take a crack at AVID Media Composer. It's a little more versatile if you're into pro level stuff. (Just a suggestion).Thanks, Andy
@@DoItYourDream In newer version of library you don't need to modify SSD1306.h, instead write display resolution while calling the constructor like // create the display object Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Not out of the box but a few changes it should (assuming your driver leverages adafruit_gfx methods). somewhere around line 73 change code to create the SH1106 object, just keep the instance name to display somewhere around line 83, change the code to begin or init your new object. That should be all you need to do.
Hi Kris, I know its been more than 2 years since you shared this brilliant code. I stumbled upon this for a personal project that requires plotting Temperature/Time function. All I require is temperature plotted against time for 24 hours. I tired to achieve that with your code, but with my limited coding abilities, I guess I messed it up. The temperature I want to measure is from 0-50 for 24 hours cycle. Then I want the graph to reset. Below is the modified code. I still haven't updated the source of data, so it still refers to A0. Please take a look. #include #include #define READ_PIN A0 #define OLED_RESET A4 // create what ever variables you need double volts; double bvolts; double x, y; // these are a required variables for the graphing functions bool Redraw4 = true; double ox , oy ; // create the display object Adafruit_SSD1306 display(OLED_RESET); void setup() { Serial.begin(9600); // initialize the display // note you may have to change the address // the most common are 0X3C and 0X3D display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // if you distribute your code, the adafruit license requires you show their splash screen // otherwise clear the video buffer memory then display display.display(); //delay(2000); display.clearDisplay(); display.display(); // establish whatever pin reads you need pinMode(A0, INPUT); } unsigned long OldTime; unsigned long counter; void loop(void) { // read some values and convert to volts bvolts = analogRead(A0); volts = (bvolts / 204.6 ) ; DrawCGraph(display, x++, bvolts, 20, 50, 96, 47, 0, 24, 12, 0, 50, 10, 0, "Bits vs Seconds", Redraw4); // Some values were changed. if (x > 100) { while (1) {} } delay(1000); // If I use delay to time the graph, the entire code will be subject to delay. I want to add other functions later. } void DrawCGraph(Adafruit_SSD1306 &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, double dig, String title, boolean &Redraw) { double i; double temp; int rot, newrot; if (Redraw == true) { Redraw = false; //d.fillRect(0, 0, 127 , 16, WHITE); //d.setTextColor(BLACK, WHITE); d.setTextSize(1); d.setCursor(2, 4); d.println(title); ox = (x - xlo) * ( w) / (xhi - xlo) + gx; oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy; // draw y scale d.setTextSize(1); d.setTextColor(WHITE, BLACK); for ( i = ylo; i
@@glasseffect Fixed up code, I added code to read a 10K NTC thermistor and plot. Also added a status bar since updates are every 20 min (so 24 hours will fill entire screen). #include #include #define READ_PIN A0 #define OLED_RESET A4 #define WHITE 1 #define BLACK 0 // constants for 10K NTC thermistors #define NTC_A 3.354016E-03 // from the data sheet #define NTC_B 2.569850E-04 // from the data sheet #define NTC_C 2.620131E-06 // from the data sheet #define NTC_D 6.383091E-08 // from the data sheet #define NTC_R1 9800.0 // resistor for thermsitor voltage divider #define tr1 9800.0 // resistor for thermsitor voltage divider // create what ever variables you need float volts = 0.0, TempF = 0.0, TempK = 0.0; long tr2 = 0; unsigned long bvolts; float x = 0.0, y = 0.0; int p = 0; // these are a required variables for the graphing functions bool Redraw4 = true; float ox , oy ; unsigned long OldTime = 0, CurTime = 0, ReadTime = 0, counter = 0; // create the display object Adafruit_SSD1306 display(OLED_RESET); void setup() { Serial.begin(9600); // initialize the display // note you may have to change the address // the most common are 0X3C and 0X3D display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // if you distribute your code, the adafruit license requires you show their splash screen // otherwise clear the video buffer memory then display display.display(); //delay(2000); display.clearDisplay(); display.display(); display.setTextSize(1); display.setCursor(2, 4); display.println("cat"); // establish whatever pin reads you need pinMode(A0, INPUT); DrawCGraph(display, x, volts, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4); ReadTime = millis(); OldTime = millis(); } void loop(void) { CurTime = millis(); // take a reading every second otherise we're averaging for 12 seconds eery pass is over kill // this will give 96 readings and let us draw a cute time status bar in the yellow area if ((CurTime - ReadTime) >= 12000) { // 12000 ReadTime = CurTime; // read some values and convert to volts bvolts = analogRead(A0); volts = volts + (bvolts / 204.6 ) ; display.fillRect(p++, 13, 2, 2, BLACK); display.display(); counter++; } // sicne were drawing every 80-20 or 60 times le't if ((CurTime - OldTime) > 1200000) { // 1,200,000 ms = 20 minutes OldTime = CurTime; volts = volts / counter; // voltage divider calculation // vo = 5 * r2 /(r1+r2) // solve for r2 // get the exact value for voltage divider r1 tr2 = ( volts * tr1) / (5.0 - volts); //equation from data sheet TempK = 1.0 / (NTC_A + (NTC_B * (log(tr2 / 10000.0))) + (NTC_C * pow(log(tr2 / 10000.0), 2)) + (NTC_D * pow(log(tr2 / 10000.0), 3))); TempF = (TempK * 1.8) - 459.67; if (x >= 24) { // 24 hours has passed // reset x and redraw the graph (erasing it) x = 0; Redraw4 = true; display.clearDisplay(); display.display(); DrawCGraph(display, x, TempF, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4); } else { // clear the stats bar display.fillRect(0, 13, 128, 2, WHITE); display.display(); //note graph starts at 20 and ends at 92--may seem odd but that gives 72 pixels of drawing with. so.... // we update the display every 20 minutes (24 * 60 = 1440 minutes, 1440 / 72 pixels = 20 min per pixel) DrawCGraph(display, x, TempF, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4); // Some values were changed. x++; p = 0; counter = 0; volts = 0.0; } } } void DrawCGraph(Adafruit_SSD1306 & 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, double dig, String title, boolean & Redraw) { double i; double temp; int rot, newrot; if (Redraw == true) { Redraw = false; d.fillRect(0, 0, 127 , 16, WHITE); d.setTextColor(BLACK, WHITE); d.setTextSize(1); d.setCursor(2, 4); d.println(title); ox = (x - xlo) * ( w) / (xhi - xlo) + gx; oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale d.setTextSize(1); d.setTextColor(WHITE, BLACK); d.drawFastVLine(gx, gy-h, h, WHITE); for ( i = ylo; i
This code is fantastic! Does what it says on the tin - and exceptionally well documented/commented! Well done!!
Glad I could help. If you use larger ili9341 displays check out my library to draw graphs on those I've got a video to show how
Hi Kris,
Great project but a bit out of date on Library usage. In order to make this work people will need to make the following changes:
Add this info to the beginning of the code:
#include
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Remove the following code:
#define SSD1306_128_64
#define READ_PIN A0
#define OLED_RESET A4
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
// create the display object
Adafruit_SSD1306 display(OLED_RESET);
Then the code runs great!
Thanks for posting your tips. I'm sure my subs can make use of this.
I posted that code some 5 years ago, and I've since moved on 2.8" color TFT,s with touch, hence I spend no time verifying the operation of these OLED's
Sir, this actually pretty cool and amazing, thanks for sharing, really valuable stuff u got here in your channel.
Wow Kris, thanks a lot, saved me a ton of time. I was beginging to write my own functions and i came across this video!
If you ever use a Teensy with the ili9341_t3 driver I wrote a better graphing lib someday I'll post a yt vid and lib link
Thank you for your video and hard work making the software available for others to use.
You're very welcome. Glad I could help.
Hi, Kris! Loved the video. It works well. I was wondering how refresh and start replotting once the data hits the end of the screen? Can you suggest a modification to the code? It would be very helpful.
I depends on how you want to continue.... 1) just erase the data and start drawing over or 2) have the grid "pan" so you can see previous data.
for option 1 should be easy but will take some minor mods 1) upon the need to start over you will need to update the parameters in the function call 2) set the "redraw" variable to true--that will force a repaint 3) remember the last x value and you will have to offset the new plot area by that amount meaning 0 is no longer 0 it's now like 100 or what ever your last value was, when you call my DrawGraph function just change the x to x+offset and remember to add the offset to the range parameter, after resetting the "redraw flag" it will get you closer. Writing this from memory.
Option #2 the pan one will take a bunch of changes--namely on a new point draw the grid area needs to pay--not hard, but probably more involved.
Hi! What an awesome project!! But I have a question: does this work with the library "AdafruitSSD_1331.h" for color oled screens??
Kris Kasprzak, would you be able to increase your IDE font size in your next video. It's difficult to see. Otherwise, love the video. Thanks for sharing.
Good tip, i'll be sure to do that on my next one.
Just spent several hours trying to figure out why my display looks like it's putting a black line between every line. Therefor, only showing the top half of a full display. Otherwise it works great. I'm using a 128X64 OLED just like the one in the video. Any help would be greatly appreciated.
look in the Adafruit_SSD1306.h file. I suspect the wrong define is being used. Look for something like this....
// ONE of the following three lines must be #defined:
// probably need to uncomment this line
//#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen
// probably need to comment out this line
#define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
//#define SSD1306_96_16 ///< DEPRECATED: old way to specify 96x16 screen
@@KrisKasprzak Thanks Kris, I figured it out an hour or so after posting and you are correct, appreciate the reply though. Take care.
@@KrisKasprzak thank you a lot, you helped me too. It was strange for me, that it needs changes in library code, but, it is deprecated approach now, and looks like in new constroctors you manually put in your project code width and height of display.
Thank you for your willingness to share your project..👏👏👏
Good stuff! Has anyone made it scrollable yet?
Thanks Kris! Will use this. I have been using part of your code in an antenna analyzer project. From your video using TFT displays.
Cool, I too am using more and more of the TFT's--mostly the 2.8" versions. I've got them working with a Teensy 3.2 and have touch, and the SD card working. Took some hardware hacking though.
How to arduino inverter sine wave feedback volt? 12VDC To 220AC. Thank you.
Quick tip wenn explaining the code, zoom in so that we can see what's happening.
Thank you so much
I don't much of arduini but how simple or hard o imposible would be to adapt these to graph data for a sensor that gives the data in i2c rather than analog values
Hi Sir! Thank you for sharing your function. So I was using this function on an 12c OLED (128x64) display. My problem though is that the title takes a lot of space, cutting the lower portion of the graph. I want to remove the title bar completely. How can I do that?
With this display, you can't. the pixel colors are built into the display.
This looks great, thank you for sharing!
Thanks for watching!
Amazing functions, very useful... Thank you very much!
Good job, Kris!
i love it! thanks. do you have something for 128x32?
Glad I could help.
How did you solve the problem?
Can we plot ecg wave on this display using the same function !?
Brilliant, thanks. I was looking for how to do what I was trying to do, but you did it for me.
Malcolm
I got bit error with dual OLED interface with Arduino
The libraries used in these examples do not support Attiny85. I couldn't find anything related with creating graphs on Digispark/Attiny85 like you did on the video. Do you know any solution?
Another question, is it possible to make pie chart like graphs which can be transformed into slices which also can be wider/narrower by a potentiometer like you just did? And even rotate the graph with another potentiometer or something else?
The APIs are just code written on code. For the 85, red the APIs and write the chunk you need into your 85 code... so no API needed.
Pie graphs use Pythagorean theorem.
a^2+b^2=c^2
and the edge of the pie is at "c" distance from 0,0.
So, graph a line from 0,0 that has a slope of b/a and is c long.
hi again, Kris.
How can display at the dial one, the actual value in numbers, besides de needle indication? . I have tried at the label place, but no result. Sorry for so many questions
have you tried something like this?
display.setcursor(somex, somey);
display.print(your value);
@@KrisKasprzak now perfect, thanks a lot
Great! I want to graph two charts, barometric pressure at the top and Temp at the bottom. Same time scale but different Y axes. Is this possible? Regards
sure is. you will just need to create a second call to the graphing function, but with different screen coordinates, and its own Redraw variable. I've done this before, just very small graphs. you can also use 2 OLED displays and draw a single graph on each display. Same basic code implementation second graph: DrawBarChart(display2....)
ruclips.net/video/yef23sJjiU0/видео.html
Thank you, you did a really great work!
Glad you liked it!
Legend! Thanks, saved me a lot of time coding the same up! Although if ylo is any number > 0 the X axis doesn't get drawn
Glad it helped!
@@KrisKasprzak I've altered your code to store the graph Y contents into an array, then shift the plot position to make the cartesian graph 'scroll' as new entries are added. Cheers again!
@@chimeranzl9147 Sounds cool, post a vid, I would love to see it.
@@KrisKasprzak hey Kris, sorry for the delay. Here’s some of your code adapted to scroll graphs ruclips.net/video/XNXTgcp3NIk/видео.html
@@chimeranzl9147 Very nice, the next time I’m in your neck of the woods I’ll stop by for a beer.
Thank you for sharing.
Looking very cool mate!
Glad I could help.
Hello there! Are still available? Where can be downloaded? Didn't foud them in Github!
Cheers from Argentina
have a look again at the description. Not sure why my link didn't save, but it's there now.
@@KrisKasprzak thanks!!! Great work!!!
This is awesome. Anyway to shrink it down for a 128x32 oled display?
sure the giant argument list has parameters for graph height and with. Look at the functions and find W and H, these are the graphs width, and height--just squeeze the height down to what you need.
void DrawBarChartV(Adafruit_SSD1306 &d, double curval, double x , double y , double w, double h ,
@@KrisKasprzak I'm looking to use the dial. I see on the bar where to change it but I can't figure it out with the dial. Anyway you can send me a pic or something. Please!!
@@KrisKasprzak it would appear as though I have the same oled display as you. I've uploaded the code but the bottom half of the dial is cut off. Any way to fix this?
@@imgoingtwo2780 I think so. the default oled libs are for 128x32
look in your Adafruit_SSD1306.h and around line 29
un comment the #define SSD1306_128_64 and // #define SSD1306_128_32 like i have shown beow.
// ONE of the following three lines must be #defined:
#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen
// #define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
Hi Kris.
Do you have code to draw graphs like this one in ug8lib in 128x64 oled ?
Best Regards, Nuno
Hello. Thanks for making this available. Im trying to implement this to my project but im having trouble scaling it up for 1.3"oled. Can you give me some help?
Did you find a solution?I'm hitting the same walls
@@ElectricPaoloIAM Nope, sorry. I found a better thing than this to do what I wanted ...
super mais marche pas pour moi !!!
'SSD1306_WHITE' was not declared in this scope ?
erase SSD1306_ only write the color WHITE in the new version of the library "SSD1306" Adafruit
@@luisbmalave OK thanks
Hi Kris!! Great Job, helps a lot. One small question: the screen scrolls automatically horizontally. How can i switch that off? Cheers Daniel
Great work, although the download link doesn't seems to be working . Please reupload it
Just tested, and worked fine at my end.
@@KrisKasprzak Thanks for the reply, checked again and it works now
Need to include Wire.h to function
Just learning but this definitely is a step In the direction I want ;) TY
Glad I could help
This seems to be working for me,thanks!
EDIT: it seems to update much slower then the example? Like only once per second or so .
Ah , I need to set the delay to a shorter amount then the 1000.
I also did the redraw for when it hits the end of the screen.
Has anyone figured out how to make it pan/scroll so it keeps the valued and just inserts incoming values ?
Couple of questions, can i shorten the time span for the envelope signal or the graph?
EDIT: Figured out how to shorten the graph and the time.
For example: DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, (CHANGE THIS -30), 25, 0, 1024, 512, 0, "
And this if (x > 30) {
Still that leaves how to make it sample faster , anything above a 6 hz sine wave gets turned into a triangle of some sortÐ
Also can i somehow remove the measurement values and text only leaving the graph?
If I wanted to run say 5 displays , do I need to get a teensy , seems weird that the arduino would almost max out on memory on one tiny display ...I am a beginner though so I might be wrong here ?
I would also be cool to be able to use triggering somehow , so it can act more like a scope, whereas it would hold the waveform.My input signal is coming from a function generator and works cool , but would be nice to be able to trigger so it would not scroll.
Not without several mods, new lib display updates and all that jazz....
Thanks alot! You should really put this into a library, don't think there is anything like it.
Yea, i really should I've got tons of these types of utility functions for these displays, 2.8" tft's etc. Someday...
Thanks for sharing this. Really appreciate your efforts. Keep it up :)
thanks, glad i could help.
Great stuff, thank you!
Nice work man, Thanks :)
Glad I could help.
Hi Kris, it the code run on NodeMCU and Arduino UNO?
Budhaditya Biswas it will definitely run on and Arduino I've had it working before, the only challenge you run into is the lack of RAM on those Unos and it makes it hard to use any other libraries for like SD cards and stuff never used to know to MCU not sure
Great Video. Well done!!
Thank you very much!
Using the same hardware, the images do not appear fully, getting bigger than the display. How to solve this? When compiling appear errors:
Arduino: 1.8.5 (Windows 10), Placa:"Arduino Nano, ATmega328P"
OLEDGraphing:149: error: 'SSD1306_WHITE' was not declared in this scope
OLEDGraphing:232: error: 'SSD1306_BLACK' was not declared in this scope
Thanks! the explanations are excellent.
regarding the errors, open Adafruit_SSD1306.h and find the defines for the colors, my lib is #define SSD1306_BLACK 0, #define SSD1306_WHITE 1, #define SSD1306_INVERSE 2. I would change the ino to match what's listed in the .h.
Regarding the wrong size, make sure this line in the Adafruit_SSD1306.h is uncommented #define SSD1306_128_64
there are also several areas in the Adafruit_SSD1306.cpp file that use that define, make sure you have all of them named correctly in the .ino, the .h, and the .cpp files.
Glad you got the #defines sorted out. I've since uploaded a new file that contains the sketch and the libs so others don't have to fight with that.
in my loop() notice a line while (1) {} of x is > 100, this while is simply and infinite loop to "stop the code" by putting the code in an infinite loop (serial monitor will stop as well). You will need to implement your own way in processing what to do after x = 100, maybe redraw the graph and start over, maybe "pan" the graph so you can see previous values?
curval = date to graph hahahaha type should say data to graph, which is basically the data point to be drawn on the screen.
try this loop, note that measuring a single point for display, then waiting is definitely not the best way to measure data. I would average as many readings as possible in the time interval the display--let me know if you need sample code.
void loop(void) {
// read some values and convert to volts
bvolts = analogRead(A0);
volts = (bvolts / 204.6 ) ;
// draw the data on the graph
DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, 100, 25, 0, 1024, 512, 0, "Bits vs Seconds", Redraw4);
// if the data exceeds the graph range then reset the old graph markers and blank out only the graph area
// note the selected values will need to be change if the size or location of the graph is changed
if (x > 100) {
ox = 30.0;
oy = 50.0;
x = 0.0;
display.fillRect(31, 18, 75, 32, SSD1306_BLACK);
display.display();
}
delay(1000); // display every 1 second
}
code to average the analog pin reads
unsigned long OldTime; // best to move this line up where your other variable definitions are
unsigned long counter; // best to move this line up where your other variable definitions are
void loop(void) {
// get as many reads as you can in the allotted time
bvolts = bvolts + analogRead(A0); // add it to itself and average before display
counter++;
// check to see if the elapsed time exceeds the alloted time (note this is in milliseconds)
if ((millis() - OldTime) > 1000) {
// reset the old time counter to enable elapsed time computing
OldTime = millis();
// if the code lands here, you must have read bvolts for 1000 ms
// avarage the volts
bvolts = bvolts / (double) counter;
// draw the data on the graph
DrawCGraph(display, x++, bvolts, 30, 50, 75, 30, 0, 100, 25, 0, 1024, 512, 0, "Bits vs Seconds", Redraw4);
// reset everything
bvolts = 0.0;
counter = 0;
// if the data exceeds the graph range then reset the old graph markers and blank out only the graph area
// note the selected values will need to be change if the size or location of the graph is changed
if (x > 100) {
ox = 30.0;
oy = 50.0;
x = 0.0;
display.fillRect(31, 18, 75, 32, SSD1306_BLACK);
display.display();
}
}
}
Do you know if it's possible to change the yellow and blue color to other places on the screen? Or is it physically permanent?
Metal Coasters my displays are hard-coded colors cannot be changed I don't know of any others that can be changed they do make some small color ones though
Okay, thank you!
Great! Thanks for sharing.
can this work with u8g2?
again asking: no way to get more than the upper part of the display. I have tried to configure the 1306 .h file, but no results. My oled is AliExpress one 128x64, with 078 and 077 bridges, set for 0x3C. Of course I am almost a beginner. I do know that the solution is simple, but don't get it. I get the same problem on both 128x64 and 128 x32 displays. Any input, please?
What MCU? What library? what color tab on the display protective screen?
@@KrisKasprzak thank you Kris, problem solved
Great Project! Can you update download link , the link is error, thx
just fixed the link, try this.. drive.google.com/open?id=1HAx40pu7ITrY-4fbalt2SH88imSYLwKq
@@KrisKasprzak to day also not working!
@@billferner6741 what is not working?
@@KrisKasprzak it was with my phone, with my computer the links are working. Thank you.
Thank you Sir, it is awsome work right there, much appreciated here in newbie lab :)
Hey Kris,I noticed you didn't have anything for a license on that OLED code that I'd like to use for a project I'm building. I'd like to give credit where credit is due so if you want anything included please let me know.. Also, if you're into video editing you may want to take a crack at AVID Media Composer. It's a little more versatile if you're into pro level stuff. (Just a suggestion).Thanks, Andy
I tried this but my graph goes off the bottom of the screen, any ideas how to fix it?
hope you've figured it out by now, the code was written with old library where display resolution had to modify in Adafruit_SSD1306.h file
by chance do you know what modification need to be done to Adafruit_SSD1306.h
@@DoItYourDream In newer version of library you don't need to modify SSD1306.h, instead write display resolution while calling the constructor like
// create the display object
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Thank you Sir, It helps me build a similar project
You are welcome
Will this work with SH1106 driver?
Not out of the box but a few changes it should (assuming your driver leverages adafruit_gfx methods).
somewhere around line 73 change code to create the SH1106 object, just keep the instance name to display
somewhere around line 83, change the code to begin or init your new object.
That should be all you need to do.
Does the code work with TFT Display?
This one no, but I have other libs that will. What MCU are you using?
Hi Kris,
I know its been more than 2 years since you shared this brilliant code. I stumbled upon this for a personal project that requires plotting Temperature/Time function. All I require is temperature plotted against time for 24 hours. I tired to achieve that with your code, but with my limited coding abilities, I guess I messed it up. The temperature I want to measure is from 0-50 for 24 hours cycle. Then I want the graph to reset. Below is the modified code. I still haven't updated the source of data, so it still refers to A0. Please take a look.
#include
#include
#define READ_PIN A0
#define OLED_RESET A4
// create what ever variables you need
double volts;
double bvolts;
double x, y;
// these are a required variables for the graphing functions
bool Redraw4 = true;
double ox , oy ;
// create the display object
Adafruit_SSD1306 display(OLED_RESET);
void setup() {
Serial.begin(9600);
// initialize the display
// note you may have to change the address
// the most common are 0X3C and 0X3D
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// if you distribute your code, the adafruit license requires you show their splash screen
// otherwise clear the video buffer memory then display
display.display();
//delay(2000);
display.clearDisplay();
display.display();
// establish whatever pin reads you need
pinMode(A0, INPUT);
}
unsigned long OldTime;
unsigned long counter;
void loop(void) {
// read some values and convert to volts
bvolts = analogRead(A0);
volts = (bvolts / 204.6 ) ;
DrawCGraph(display, x++, bvolts, 20, 50, 96, 47, 0, 24, 12, 0, 50, 10, 0, "Bits vs Seconds", Redraw4);
// Some values were changed.
if (x > 100) {
while (1) {}
}
delay(1000);
// If I use delay to time the graph, the entire code will be subject to delay. I want to add other functions later.
}
void DrawCGraph(Adafruit_SSD1306 &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, double dig, String title, boolean &Redraw) {
double i;
double temp;
int rot, newrot;
if (Redraw == true) {
Redraw = false;
//d.fillRect(0, 0, 127 , 16, WHITE);
//d.setTextColor(BLACK, WHITE);
d.setTextSize(1);
d.setCursor(2, 4);
d.println(title);
ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale
d.setTextSize(1);
d.setTextColor(WHITE, BLACK);
for ( i = ylo; i
I'll fix this to meet your needs.
@@KrisKasprzak
Thanks a lot Kris for your valuable time.
@@glasseffect
Fixed up code, I added code to read a 10K NTC thermistor and plot. Also added a status bar since updates are every 20 min (so 24 hours will fill entire screen).
#include
#include
#define READ_PIN A0
#define OLED_RESET A4
#define WHITE 1
#define BLACK 0
// constants for 10K NTC thermistors
#define NTC_A 3.354016E-03 // from the data sheet
#define NTC_B 2.569850E-04 // from the data sheet
#define NTC_C 2.620131E-06 // from the data sheet
#define NTC_D 6.383091E-08 // from the data sheet
#define NTC_R1 9800.0 // resistor for thermsitor voltage divider
#define tr1 9800.0 // resistor for thermsitor voltage divider
// create what ever variables you need
float volts = 0.0, TempF = 0.0, TempK = 0.0;
long tr2 = 0;
unsigned long bvolts;
float x = 0.0, y = 0.0;
int p = 0;
// these are a required variables for the graphing functions
bool Redraw4 = true;
float ox , oy ;
unsigned long OldTime = 0, CurTime = 0, ReadTime = 0, counter = 0;
// create the display object
Adafruit_SSD1306 display(OLED_RESET);
void setup() {
Serial.begin(9600);
// initialize the display
// note you may have to change the address
// the most common are 0X3C and 0X3D
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// if you distribute your code, the adafruit license requires you show their splash screen
// otherwise clear the video buffer memory then display
display.display();
//delay(2000);
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setCursor(2, 4);
display.println("cat");
// establish whatever pin reads you need
pinMode(A0, INPUT);
DrawCGraph(display, x, volts, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4);
ReadTime = millis();
OldTime = millis();
}
void loop(void) {
CurTime = millis();
// take a reading every second otherise we're averaging for 12 seconds eery pass is over kill
// this will give 96 readings and let us draw a cute time status bar in the yellow area
if ((CurTime - ReadTime) >= 12000) { // 12000
ReadTime = CurTime;
// read some values and convert to volts
bvolts = analogRead(A0);
volts = volts + (bvolts / 204.6 ) ;
display.fillRect(p++, 13, 2, 2, BLACK);
display.display();
counter++;
}
// sicne were drawing every 80-20 or 60 times le't
if ((CurTime - OldTime) > 1200000) { // 1,200,000 ms = 20 minutes
OldTime = CurTime;
volts = volts / counter;
// voltage divider calculation
// vo = 5 * r2 /(r1+r2)
// solve for r2
// get the exact value for voltage divider r1
tr2 = ( volts * tr1) / (5.0 - volts);
//equation from data sheet
TempK = 1.0 / (NTC_A + (NTC_B * (log(tr2 / 10000.0))) + (NTC_C * pow(log(tr2 / 10000.0), 2)) + (NTC_D * pow(log(tr2 / 10000.0), 3)));
TempF = (TempK * 1.8) - 459.67;
if (x >= 24) {
// 24 hours has passed
// reset x and redraw the graph (erasing it)
x = 0;
Redraw4 = true;
display.clearDisplay();
display.display();
DrawCGraph(display, x, TempF, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4);
}
else {
// clear the stats bar
display.fillRect(0, 13, 128, 2, WHITE);
display.display();
//note graph starts at 20 and ends at 92--may seem odd but that gives 72 pixels of drawing with. so....
// we update the display every 20 minutes (24 * 60 = 1440 minutes, 1440 / 72 pixels = 20 min per pixel)
DrawCGraph(display, x, TempF, 20, 50, 92, 30, 0, 24, 6, 50, 100, 25, 0, "Temperature", Redraw4);
// Some values were changed.
x++;
p = 0;
counter = 0;
volts = 0.0;
}
}
}
void DrawCGraph(Adafruit_SSD1306 & 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, double dig, String title, boolean & Redraw) {
double i;
double temp;
int rot, newrot;
if (Redraw == true) {
Redraw = false;
d.fillRect(0, 0, 127 , 16, WHITE);
d.setTextColor(BLACK, WHITE);
d.setTextSize(1);
d.setCursor(2, 4);
d.println(title);
ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale
d.setTextSize(1);
d.setTextColor(WHITE, BLACK);
d.drawFastVLine(gx, gy-h, h, WHITE);
for ( i = ylo; i
also my code has a temp rage between 50 and 100, you will need to change that if you want 0-50
Thank you for the sharing ;-)
Useful. Thx
MAD PROPS ! THIS IS AMAZING ! SSD1306 is
Glad u liked it!
Very useful. Thank you very much :-)
Cool... very inspire..
Glad you liked it
Wow, thanks for sharing :-)
how can I get the code?
There is a link in the description
@@KrisKasprzak thank you very much, Kris
Thanks for sharing
I'm very like, and easy use, but i used with gps neo6 this is can't run, I wont solution, sory bad my english language. thank
Your English is fine, what is not working?
wow excellent!!
Good one
Thanks
Awesome
Спасибо, вспомню тебя добрым словом если пригодится
Wow!
Ok
thx rspct