Hi Ralph Many thanks for such an informative video, I have a question, is it possible to open the *.h and *.cpp files in the Arduino IDE, sorry if I missed something in your video which explains this I have watched it three times. You stated in the video that we could play around with these files and if we made a mess of them we just download them again, from that I thought you meant we can alter things in all three of the files. Many thanks Graham
Hi Graham! THREE times you say? You probably know it word for word by now! Yes, you most certainly CAN open the .h (header) and .cpp (c plus plus) files using the Arduino IDE. There are some caveats: 1. To CREATE a new file (which will reside in the same folder as your sketch) click the small triangle at right hand side of the toolbar (containing the sketch tab). You will then be prompted to enter a name (eg myheader.h). The prompt appears at the bottom of the code window (!) 2. To OPEN an existing library file, copy both the .h and .cpp files to your sketch folder, then open your sketch. The additional files will appear as separate tabs next to your sketch's tab. 3. To include a library file in your sketch, when the library file header resides in the same folder as your sketch, use the format #include "mylibrary.h" *not* #include as the latter format is used when you want the Arduino IDE to search your libraries folder (and elsewhere) to find a library. 4. If you muck up the .h or .cpp files you can just re-copy them over to your sketch folder again whilst you experiment. If you enhance the library, and want to keep the changes MOVE the files back to the libraries folder (but do take a backup of the original files first, just append .old to the filename or something). Then refer to that library in the usual way with the standard #include again. I guess I should have clarified this in the video better, but maybe this comment will be read by gazillions of viewers too. Thanks for posting this question, it will benefit others wondering this.
Hi Ralph! Many thanks for the quick reply, Item 2 answers my question and works fine, I now have all three files together so I can play with them. Please keep up the great work, very interesting content, I am also going to watch more of you videos. Regards Graham
@@RalphBacon Well, I don't know about gazillions... but I've definitely read it. Comments can hold vast amounts of additional information and are worth reading.
@@RalphBacon Thanks for the informative video. As for #2, it would seem that you're opening a copy of the library that you're using via , not the actual library that it's compiling? That there's not an easier way to view libraries with the IDE is a bit of an annoyance (not your fault, obviously). Seems like Notepad++ or similar is a good way to take a peak at them to figure out what functions etc are available, but that's not perfect either.
arduino noob here... after months and months and months of studying, watching videos... its the first time i see how to collapse sets of codes... my gosh, so many tutorials and this is the only one that explains that! thank you!
thanks for this lesson with detail explanations on each lines and resons. I picked up many knowledge not known before as I was trying to make my own library.
I very much like the way you teach. It is as if I was sitting down with a friend or colleague who wants me to understand something, but wants it to be a pleasant experience.
Ralph, I came across this video (#71) a few months back, and am now proud to say that I have written my first Arduino library. I've a lot of work to do on the code, but I have built a class with methods, and it is likable into a users sketch. I am now working to configure it to allow easy importing into the IDE and compliance with Github standards. So many thanks for your inspiring and instructive videos.
Wow thank you so much. Some people are complaining about how long this video is but its was great because you not only created a library live in front of us but also explained the background of whats happening. Great Video!!
Complaining? About MY video lengths! Actually, Aldrick, I gave up trying to make shorter videos some time ago and now just make them whatever length they need to be, usually around the 30-minute mark. It's about the right length if we're going to discuss stuff in the correct level of detail, don't you think? Well, it seems you do! Thanks for posting!
Thank you Ralph. I hesitated to start a 38 minute video tutorial, but it was worth it just for the calm Pommy accent and absence of duffa duffa music! I am an old veteran since the 70s of programming assembler on bare metal for embedded realtime controls, and only just in retirement wrapping my head around C/CPP. Some of the syntax conventions really "get" me, and I have to remind myself I am dealing with a very simplistic one-pass compiler that needs lots of cues in order to work. The work flow from multiple tabs / project folder to files in the library folder was very helpful.
Glad you found it useful, David. All my videos are a bit long but watch them at 1.25 speed and it shaves many minutes off the length. And I don't sound like a chipmunk on helium either!
I never thought I would understand such a complicated subject but you made it so understandable. Thank you so much! You have a special 'teaching gift'...
Thank you, Harry, for your supportive words. I'm glad it's helped you (and hopefully others too!). Once you've done it a couple of times it gets quite automatic to move stuff into a library. Good to hear from you.
Hi Ralph, Your videos are wonderful. Very instructive and very easy to understand. I have written my first library using your video and just wanted to say thanks and keep it up!
Thank you very much Timothy, I'm glad I'm being of some use! Like most things, once you're shown how (and, possibly, why) then the mystery disappears and you think "Is that it then?" I hope you create many more libraries (I must admit to cheating whilst developing and just stuffing items into a .h file until I'm ready but don't tell anyone!). Thanks for posting, much appreciated.
Omg this is so good... I learned a lot today for me to try write a code to sniff the LIN bus protocol. going to use this way of clean setup and also make it easy for me to reference to other codes available. now I can connect the dots a lot better.
Totally brilliant ! Thank you so much for explaining that ... and at a good pace: neither too fast or too slow, and in an accent that my ancient ears can cope with!
Benny says that you are most welcome too, and sends his regards to Sammy & Morgan who are probably experts in Arduino C++ now (cats learn fast apparently). 😺
Thanks for this walkthrough, Ralph. I'm coming from other programming languages (primarily web dev), and this was a great overview of the idiosyncrasies of c++ when it comes to object oriented code and including local libraries. I had been reading through articles and posts that explain the same thing, but none of them were as clear and well presented as this video :) Thanks for taking the time to make this and for posting a link to the code. It's much appreciated :D
Well, thank you, cschmitz, for your kind words! I'm glad to have helped. I, too, have taken many paths in coding, from µProcessor assembler through various BASIC dialects, C#, JavaScript, and C++. I think once you have a programmer's way of thinking then the language is secondary to what you want to do, so you (as a web developer) are well placed to mastering this very quickly. Thanks for posting and good luck in creating your own libraries!
I forgot how good this video is. I think the grammar of classes are what make them seem intimidating. The textbook jargon like instantiate, constructors, deconstructors, self.label type stuff. But if people let go of the jargon like you're showing then people understand it better. When I started, and I'm no expert but the 'self.' Stuff got me confused the worst because all the constructor variables were just stated above. Haha
When I created this video, Joey, I was very careful to _not_ mention anything OOP-related as I knew it would put viewers off! Talking about polymorphic inheritance might be a bit off-putting (just a wild guess). 😁
Ralph many thanks for a very clear explanation of how to create an Arduino library. Apart from tidying up the sketch I would say the other main reason to create a library is for code that you tend to find yourself using in several projects. Once it's been debugged then you can forget about the dirty details and simply use it every time you need those methods. BTW I never knew about the IDE being able to collapse or 'fold' code so thanks also for that insight!
You've grasped the real use of a library completely, Philip. TBH even if you don't use the code elsewhere it's still good to 'modularise' the sketch this way as you quite rightly say you can forget about it. Glad you now know about code folding, it's quite useful. Thanks for your supportive words, appreciated.
Well thank you Goldichan92, I appreciate that you took the time and trouble to post that. Unless my Arduinite viewers tell me how I'm doing I have to guess which is not the best way to build up an audience. So thanks again, and keep watching! And don't forget, if you like what you see, consider subscribing! :)
You are the man, I could not figure out how to use the serial port in my cpp file. I tried everything until you showed the method to - begin serial. Like you said, there just isn't any useful online documentation available for this - JOLLY GOOD SHOW !
very helpful! I also had forgotten the semi-colon at the end of the class declaration. Luckily, it was the first thing I randomly landed on when I was flipping through the video to check if it was any good.
Awesome, Bernebeer! Congratulations on having done this. Now you have started you can progress to more complex libraries. Perhaps one day I will be using a library that you created, who knows. Thanks for letting me know, great post.
Glad you liked it, Franz-Juergen, ziemlich einfach, gel? Now that you have some knowledge you can create your own libraries, but start slowly, as there are some 'gotchas' as they get more complicated. Thanks for posting.
Extremely interesting and useful. Wish I had found it a couple of months ago when I was just getting started with Arduino. I'll have to watch it a couple of more times as I'm a slow learner.
You sound surprised! Yes, once you have written one library you can progress and learn all about classes, objects, private, protected and public functions and variables... the list goes on. Well done!
The reason why the text does not come out correctly while the "void setup() {...}" is not called, is very simple. The "void setup() {...}" is just part of a basic library framework library that sets up stuff like buffers, timers and so on. While the "void setup() {...}" was not called already, the text written makes the serial-out-buffer overflowing and from the most characters, apart from those that had gone into the hardware fifo from the USART hardware, are lost. So it is a pre-initialization issue, since in the first version the constructor was already called at the "TestLib testlib(true);", before ever entering "void setup() {...}". By the way, putting serial initialization routines in classes is very bad style, since having more classes then just your gives the problem that they might all try to intialize serial, one after another when called trough out constructors/methods. So your "serial.begin(...)" to put once into your "setup()" is certainly the better way to go, because then it does not get out of control if, when and how many times this is issued.
Spot on, I realised this belatedly, but as it was more about how a library is constructed I kept it going. The whole serial thing is a bit of a mess - I traced the code (the Arduino.cc written code) and it really is a bit convoluted, to say the least. Definitely not the best thing to put into a library example. I hope you still consider there is still value in the video though for others to learn about OOP.
Of course it is usefull, expscially for beginners into C/C++ along with Arduino, to see how Libraries could be done, instead of having endless spagetti code like looking source files. So I think your video is very good to take a look into the Libs aspect of Arduino developments.
very helpful. I have done a lot of programming but never really took the time to sit down and do that library stuff (eventhough I started a few times) . Will do again with help of your video. Oops, Sorry, I forgot I already commented on this video. Must be my age. Anyway, extra proof I like the video
I think you have just proven that you REALLY like this video! I'm happy with that! Constructing library classes is not magic, voodoo or only for "experienced" programmers. It's a series of steps and concepts that can make your programs "better" (oh, dear, red rag to a bull I know). Best thing is to try it with a really, really simple function (as per my demo) and get that working - then build on that. Thanks for reiterating your love of this video, I hope others feel the same way :)
indeed. I am no stranger to making 'classes' but wrapping it in the library files is something I just haven't taken enough time for yet to be able to do it fluently. Enjoy yr weekend
Great video Ralph. This steps it up a gear for anyone who wants to understand object oriented programming. Once you 'Get It' the concepts are then only language specific. C++ is a bit unwieldy with its header files and you explained the concepts really well. The only thing , (and could be difficult for beginners), is Scope, the :: syntax. Really good Ralph, excellent mental workout following the code, cheers Alan
Ha ha, I'm glad your brain got a good mental workout trying to follow my meanderings through class construction! But the point you make about 'getting' the concepts is spot on. Once you have that lightbulb moment all else is 'just typing'. I'm hoping enough people take my example, break it, fix it, break it again and basically get a good grasp on how libraries work and in doing so understand how classes work too in the (semi-) object oriented world of Arduino C++. Thanks for your kind words about me explaining it well. I don't normally watch my videos all the way through (after a couple of hours of editing I've usually had enough of my own voice) but I felt this time I had to make sure it all hung together properly and I think it does provide a good starting point for Arduinites expanding their wings, so to speak. Thanks for posting Alan, always good to get constructive feedback.
Thanks for a great tutorial it has helped me on my Arduino journey as it’s time to really understand what some libraries do and the place to start is making your own.
Thanks for a very clear and informative video. I had wondered what the cpp and .h files were for - now I know. Not sure I like OOP, it just adds another level of complexity. Many thanks for sharing this. Best wishes Arthur
Hi Arthur! I'm glad you enjoyed the video, but what's all this about "adding complexity"? :) OK, it IS something different but simple classes in Arduino can lead to better programming. Mmm, perhaps I need to do an introductory video into classes (well, OOP) for Arduino! Maybe. Lots of other stuff to cover first. Anyway, glad you liked it and thanks for posting, great to hear from you.
Yes do try, Bob (Yoda: there is do or not do, there is no try), it's not difficult but start small and work your way up! Thanks for posting here, nice to hear from you. (I hope you got the Yoda reference)
Ah! An anomaly for the Arduino IDE then. Strictly speaking, quotes around a library simply mean "look in the sketch folder _FIRST_ then in the usual place(s)". But without the quotes it won't look in the sketch folder at all, it seems. I shall be aware of that in the future.
Thank you for your time and effort in making this video, i was able to follow along in real time recreating the sketch while modifying various attributes of it. Very good tutorial highly recommended.
@@RalphBacon Not a trouble I always leave a like. Don't suppose you fancy making a video about using other libraries with a library. Got square eyes trying to figure out how to include the wtv20sd16p library in my library. 😅
@@RalphBacon I did figure it out in the end but it's surprising how scattered the info is, I couldn't figure out where to instance the object correctly to use it throughout the library. I actually found two methods one used pointers which I no longer use but Google hot to use a library in a library and there is no definitive guide or tutorial on the do's and don'ts thanks for your reply though.
Thanks much Ralph! Here's where I get into stall mode. For instance if I wanted to output an instantiation message to another device apart from a serial port or output to another library function ie. write to an SD card then things get confusing. I know that your code is just an example and that any 'portable' library wouldn't open a serial port regardless, but further thinking brings on many complex options. Great example nonetheless!
Hi ya Phil, interesting comment there! If you wanted to output serial data to another device, when we have already used it for our debugging window (Serial Monitor), you could always use the Software Serial library which allows any pin to use serial data. I've used it many times and it works well and stops you being restricted to pins 0 & 1. But as you say, this was but an example showing how to put a library together (rather than concentrating on the functionality) and I'm glad you liked the example. Good to hear from you.
Thanks for the video Ralph - yes I know it's mature. Lovely to see Benny again. I think the reason you cant put Serial.begin in a constructor is that Serial is a static class, it's a single resource. That's to say you can't really create another Serial for each instance of your class. I created a Ping)) class with OTT features including limiting the time pulseIn will wait based on a user decided maximum distance of interest. I wanted to check the maths with a debug method; in that method I simply use if (Serial) { print lovely stuff}.
A good workaround you have there. Another solution is to try a singleton for the Serial.begin but I suspect that might not work either. Probably just better is the user sets up the Serial interface anyway, as it might be Serial1 on another device.
Don't tell anyone, Pekka, but I do the same when I need some (good) advice, heh heh! I guess as long as you know there is a video with information here then it's perfect that you returned and watched it when you needed it. Thanks for getting in touch, good to hear from you.
Nice job explaining what can be somewhat daunting for those learning. One thing, when coding in C/C++ you should also include a destructor in the class, but not sure if necessary on an MCU which will most likely loop forever anyway.
Very nice tutorial! The explanation speed was perfect since it allowed me to think deeply about what you were saying. I subscribed to your channel too. Thanks a lot!
@@RalphBacon this is definitely the best arduino library tutorial so far on UA-cam and it's nice to see you answering peoples question on your older videos. i'll keep eye on for second part. Love from Finland👍
It has been many years since I have done it, but if you break the source code file into different files according to the different methods in the class, GCC will include only the functions called in the final binary. It will do this process during the linking process. An example is the standard libraries. If you examine the libraries they are an agglomeration of separate object files per standard function.
Yes, you're right of course Uzi, the compiler/linker is intelligent enough, thank goodness, to only include code that is actually called! Just as well, given the limited space in an Arduino Uno. For us Arduinites that have created their own 'Utilities' library (a collection of 'useful methods') it means that not all the library is included each time, so it doesn't really matter how many methods you place in it (within reason, we don't want a huge monolith of unrelated functions!).
Again relying on memory, The procedure of separating the functions or methods is tedious and you have to pay attention to the separate source files, edssentially treating them as a separate project each.
If you are new to my channel, Joel, you may not realise that Benny writes most of the C++ code. If he does deign to let me have a go he then monitors everything I write with a beady eye. He is a hard taskmaster. Of course, if you have watched more of my videos than you already know this and the fact that he sometimes sneaks into my workshop at night and corrects all my syntax mistakes, recompiles everything and uploads it all to the µcontroller board I'm using. I'd be lost without him.
Hi, Ralph. You explained this quite well. However, I'd like to share a convention I've used in C++, PHP and several other languages. When writing a class, I will always add a private variable (as a programming flag) named 'debug', along with a setDebug() function. Throughout the code of the class, I test for this value to determine whether to display generalized debug messages, much like you did with the _msg variable you used here. Then, from the main "sketch", I call object.setDebug(true); while developing, and object.setDebug(false); when all is working. Another thing I include in every class is a public function named ReportSelf(); This function reports every variable name and value the class contains. I find these practices to be quite useful, and in fact use them a *lot*.
Hi there chopzuki! Your points are well made and should probably be standard when creating a class (oops, I said that word again, I've just lost 50% of the viewers reading this post!). Seriously, though, when using classes such things become much easier and abstracted away from the main sketch. You've probably noticed my use of a templated global debug function in my other scripts which beginner Arduinites might not have fully understood but at least grasped its usefulness. At least it stops the dreaded if(debug) Serial.print.... littered throughout the code! Glad you visited, I hope you stay, and thanks for that excellent point in your post, most appreciated by me and others reading this :)
The usefulness of this approach is two-fold: First, the _debug flag is quite useful during class development. Second, even when the _debug flag is set to false, the ReportSelf() function is especially useful when working with database records to help ensure data is being handled correctly.
This is a great suggestion and is very helpful during development. The only caveat to this approach is that unlike general computers, microcontrollers have very limited amounts of memory for code and stack variables. A better approach would be to use a preprocessor directive to remove any debug code that you can during builds for "production". I'll try to build some example code and post it up in the next few days.
The reason why the constructor (ctor) behaves differently to other methods is because it is a very different animal. Methods (other than the ctor or destructor (~classname)) are stored differently. They are in fact static code stored in the code. This affects the 'lifetime' of the methods. Yes, there is a difference from other static methods and functions and that is 'this'. 'this' is a hidden parameter to all non-static methods. The parameter is in fact the first in the parameter list; such is the case even if there are no declared parameters (i.e. classname::foo (void);). this is a pointer to this instance of the object. Now the constructor has a very short lifetime only surviving as long as the object is instatiating; as such the constructor can only be accessed when a variable of the objects type is declared. or new is used. A call to a serial method shares the cycles with your code (unless it is blocked by, say delay(100). So if one watched code such as [serialPrint('Test)'; digitalWrite(13, HIGH); ] on a logic analyser, one will observe that the TX pin becomes active AFTER pin 13 goes high. Now, if that behaviour is repeated when calling serial from a constructor, that temporary string created in the parameter of the call, may no longer exist. As serial accesses the string character by character, later characters cease to exist before the message is sent. Arduino doesn't support new or destructors (because no libc functions accessing dynamic memory are supported). Constructors are partially supported but only for access to the object's variables.
BTW I am confident that Ralph is fully cognizant of 'this' etc. I just mentioned those aspects of the constructor problem for his other disciples who, like me, are lesser mortals.
I think, Michael, you underestimate your already considerable skills on OOP, given your posting above, nicely put. What you have described belongs in the "advanced" Arduinite class, of course, and I should have remembered (or at least understood) why there are difficulties in putting that Serial.print in the class' constructor. What is clear to me is that most writers of libraries (and therefore classes) do already understand the above and therefore that is why they suggest the addition of a begin() function; it cleans it all up rather nicely as well as using a well-established pattern that beginners can grasp very easily. Thanks for the excellent explanation above; if nothing else it makes it clear why I had that issue, like most things in computing there's *always* a reason for a computer's behaviour even if we don't understand *why* at that time! Great to hear from you and I hope you enjoy the other videos on my channel :)
I enjoyed this video, as I have with all your presentations. It is always a joy to look down my list of subscriptions and see that you have submitted a new submission. I couldn't agree more on your comments on libraries and their valuable facilitation of code re-use. You are right to encourage your viewers to gain confidence in developing their own libraries. We are all beginners in this environment that is changing so quickly. Rapid change makes books poor resources for all but the most fundamental aspects of embedded development. However, all that your viewers have already learnt from your and their projects could fill a library (of books). The more we share with each other the better the technology will be. Thank you for enabling this process.
The reason the call to Serial.begin() in your ctor doesn't work is because in C++, all static objects are constructed before main(), which means the application owned objects are not necessarily fully initialized yet. You can see in arduino/core/main.cpp that USB.attach() is called in main() before the call to setup() (which is the call into your sketch's setup function), so USB (and therefore Serial) is not ready for your use until your setup function is called. In C++ you don't want any static object function calls (e.g. ctors) to call into any other static objects before main() because they many not be fully initialized yet. The order that static objects are initialized is not guaranteed to be knowable. That is why many libraries have setup/begin calls that need to be called in your setup function, after all static objects have been constructed. Otherwise, ctors are not particularly different that any other code - all code is stored in PROGMEM. There are a few caveats with ctors/dtors, mostly related to inheritance and virtual functions.
True, Dr. Jones, true. Or is it the linker? Whatever it is, I think we are now all in agreement that unused functions and/or libraries are not included in the final, downloaded hex file, just as well! Thanks for the confirmation and posting.
Great video Ralph. Oop for newbs is a hard topic to teach. When I went to university they were just defining the standard for oop in c/c++ so I missed out because I stopped coding from 20 years. I had a fun time learning all the arduino basics because it all came back to me. It woke something in me so I took an advanced pointers course, data management and then I took the course for oop and made like ten fake entities then wrote code based on the classed I created. Haha You make the complex make sense very well my friend.
It sounds like your interest in OOP programming is still strong. Those developers that put in the effort to learn how to make a class will make better programs for sure.
Actually, the last software house I worked in for five years built software for their own company but it was used (implemented) throughout the UK. 22,000 clients. Tricky stuff!
It's more an introduction of OOP/C++, the function doesn't need a whole class, simply putting the function in the .cpp and making a .h file, would work too. You can even use only an .h file, because of the preprocessor… and there is the possibility to use more .ino files too.
Hey AltMarc, great to hear from you! You are of course correct in your observations, but if you notice I steered well clear of mentioning OOP hardly at all as there's nothing better to deter beginners of C++. A large proportion of Arduinites expect (and can understand) procedural code (like VB Basic 6, perhaps!) but as soon as classes are mentioned, along with overrides, polymorphism, inheritance, templates and what have you they will go back to the 'safety' of their standard procedural code. So I was hoping that putting a very simple function into a library class might get them using a bit of OOP (even though it didn't really require it) and so not be put off. And, of course, it might actually encourage some developers to put their code into a library so they can concentrate on new stuff they are building. There's no easy way of learning C++ OOP without doing it - ideally doing it without realising you're doing it. Hence the video! Did I succeed, that is the question? Great to hear from you, always keen to get my viewers' perspective on things, and I appreciate you took the time and trouble to post here.
Hi Ralph. I found the video to be clear and helpful, and I will be definitely looking at your others. But I think you should have left the OOP out of this. I know it confused me. In fact, I only scrolled down to find this message because my research so far into creating a library led me to believe no OOP is necessary, and I wanted to check if that was true by seeing if anyone had commented to that effect. OOP doesn't bother me, I've done mountains of it in Delphi, but I'm new to C++ and I just want to learn how move some code into a library, and not have the process complicated by unrelated concepts if not needed. I haven't yet learned how to write classes in C++, and I didn't come here to learn that now - I came here to learn how to make a library. Only after success in that, would I want to convert it to OOP where appropriate. The video as it sits, leaves the new library writer with the notion that a library MUST involve classes, which (from what I have gathered) is simply not true. I can imagine someone with a large chunk of code involving a bunch of interrelated functions and data that they want to wrap into a library, getting into all sorts of bother trying to make them into classes when they don't actually need to (even though they probably should). If I had watched only your video, I know this would have happened to me. In essence I'm saying that as libraries and classes are distinct concepts, they should be taught as such. Confusing them in the teaching, confuses them in the student. I can see that you are concerned with OOP being a deterrent to some people. But I think introducing it "by stealth" where not required is the wrong approach. I would address that by a separate video about classes. (which would include an admonishment to those afraid of OOP to stop being such little girls) I hope you see my criticism as constructive, and thanks again for making these videos.
Ralph, great tutorial. I now have some idea what I'm looking at when I poke around in library files. More like this please - a debug library would be ideal. Regards Alan
Hey Alan! I was going to include my debug routine in the library video but found that my code was "too advanced" for the compiler to figure out how to use it! Seriously! It's a limitation of the compiler but as always, there are workarounds but it just made it a bit messy and not really for a "first time" video - but I will include it (or upload it) with a future video. At least you now have a better understanding of how the libraries hang together and can appreciate the work some of the authors have gone to just to give us Arduinites an easy way of interfacing with bits of hardware. And of course, you could create your own libraries just to make things easier to work with. A nice cold Saturday afternoon project, perhaps? Thanks for the feedback and suggestion, great to hear from you.
Indeed you are correct, Steve, that was your starter for 10. Now, what does .ino stand for? Previously known as .pde, which stands for? Finally, why did Arduino.cc change it all? Why not just keep to one name for everything, ideally, .cpp? More questions than answers, I'll be bound. You're not allowed to Google the answers, either!
@@RalphBacon Not sure what .ino stands for for .pde is an extension from the Processing language which Arduino and the Arduino IDE is based upon. I think They changed it to .ino to make it clear that the file is an Arduino file instead of a .pde (Processing) file. If they did not do that many noobs would run into issues.
Excellent, Ricky, start small and work up. And look at other libraries to see whether there are any other techniques you might use. Great to hear from you.
Thanks Ralph. Great info! I'm used to C, not C++, but I will definitely switch over. Then I can put my common useful functions in a library instead of re-copying them into various ino sketches(and which one has the latest modified version?). I saw that I can also create a subfolder in ../libraries/TestLibrary/examples/LibraryExample1/LibraryExample1.ino so that it is visible from the Arduino ide files/examples. GREAT STUFF! Made my day!
When I was doing C back in the days of Borland C, cpp was brought in as I understand in programs to differentiate C code (vanilla) from C++ cpp = c plus plus
Actually, Arduino now admits they made a mistake with their Serial.flush implementation. It _usually_ means "clear down any outstanding characters in the output buffer" but they implemented it as "wait until the buffer has been naturally cleared by being sent out the UART". I suspect that curtailed message was because the Serial.begin() was in the wrong place, but whatever the reason I've always had it work just fine since!
Hello Arduinite! I'm currently on vacation 5,000 miles away from home so I'll have to be brief with these comments until my return, mid-July. Glad you found it useful, John, I like comments which contain the words "brilliant tutorial"! It's not so hard once you get to grips with the fundamentals. Thanks for posting.
Afternoon Ralph - Thanks for the video. Just spent ages scratching my head over the following error message error: abstract declarator '' used as declaration In the end the answer was simple; I had the 'usual' pairing to guard double including the header by deine and test... #ifndef Sensors #define Sensors and began my class with... class Sensors complete with constructors, methods etc. The lesson is the compiler preprcessor followed my instruction to define Sensors as an "empty string", it went on to replace every occurrence of Sensors with ""; so giving a class without name. I hope I've learnt to make my double inclusion guard #define xxxxx_h so my class can be class xxxxx. I am not the first, nor will I be the last but hope the comment will also help others avoid this NOOBS trap.
Phew! Sherlock Holmes would be proud of your investigative powers there, Michael, glad you found it (and learned something along the way). I've done similar, as have countless others, just as you say. Thanks for posting.
It is a requirement with British engineering, that anything unknown during the development phase shall be named "Fred". I expect RJ Mitchell referred to the Spitfire as "Fred" in the early days.
Thanks for your post, Ammar Syafiq Sabaahul Ahmad, good to hear from you.
3 роки тому
Hi Ralph, thank you for explaining. Unfortunately, I have one question. What if I need (I don't know, how to say it correctly) some class variable, that is shared across all instances. For real example. I have a few moisture soil meters and I have decided, that I will write library for them. There are some instance variables, unique for each instance like "pump_relay_pin" or "moisture_limit". But I need one shared variable for the whole class. It's called "vcc_moisture_pin" and its value is same for all possible created instances, because it's shared pin, which turn vcc of all sensors on. It doesn't matter how many there are. So, I need this "class variable", which I can set directly via class name in main program, not via instance name. This variable I want to use only in library cpp file afterwards. Yes, I can use this variable as instance one, but I don't like it. I think, it is not programmerly correct. What I can use now H file class MyLib public: MyLib(); byte vcc_pin; INO file MyLib Inst1; Inst1.vcc_pin = 2; What I want to use H file class MyLib byte vcc_pin; // I don't know, where to put this declaration public: MyLib(); INO file MyLib.vcc_pin = 2; and then, every instance gets this vcc_pin variable with value 2, but I need to set this value in main program, not in library, because I want it versatile. Is there any option, how to do this? Could you please help me? Thanks a lot :)
It sounds like you need to write a public function in the class that updates that variable (which should be private, not public). Another function to read it back. But that gives you that value for the class instance you are addressing, it's not global across all instances. You could accomplish that by creating another instance that you call globalMylib (or whatever) and use those functions I mentioned wherever you need to update or read it. What you really need is a singleton, or static class, but I only know this from C# not C++ - would have to check that out (or you could).
I think it important to keep the names consistent here. TestLibrary is a good name for the sketch and header, but I'm not writing that out every time so *tl* it became. You can choose whatever name you like for the class but it should still be consistent and not confusing for the compiler.
Thanks you!, very clean explication i like your style, only a note that could be tricky: in the #ifndef statement we can't use the same name of the library, this could be confussing because the declaration of the files .h .cpp and the constructor needs to be namend equal.
Indeed, you are correct, the common practice is to use a name in capitals or with underscores after the name or both - you get the idea! Pity that I used a lower case two character name called tl (for test library) but then again this was just a demo)! Thanks for the advice, good to hear from you.
Ralph: How do you find out what functions a library includes and what there parameters are? I want to use the AccelStepper library but I don't know what functions it includes or how to use them. Thanks
Most libraries are on GitHub. The GitHub for a particular library should have documentation (or a pointer to the Wiki for it). This will tell you everything you need to know. Secondly, if you look at the library, in particular the library headers (files ending in ".h") these will provide the PUBLIC functions you can call. From there you can find the relevant function in the associated c++ file (ending in ".cpp") and read it, to see whether it's documented enough. Also the GitHub will probably contain an "Examples" folder with some simple get-you-going sketches. Another source of gold to beginners.
Hi Ralph
Many thanks for such an informative video, I have a question, is it possible to open the *.h and *.cpp files in the Arduino IDE, sorry if I missed something in your video which explains this I have watched it three times. You stated in the video that we could play around with these files and if we made a mess of them we just download them again, from that I thought you meant we can alter things in all three of the files.
Many thanks
Graham
Hi Graham! THREE times you say? You probably know it word for word by now! Yes, you most certainly CAN open the .h (header) and .cpp (c plus plus) files using the Arduino IDE. There are some caveats:
1. To CREATE a new file (which will reside in the same folder as your sketch) click the small triangle at right hand side of the toolbar (containing the sketch tab). You will then be prompted to enter a name (eg myheader.h). The prompt appears at the bottom of the code window (!)
2. To OPEN an existing library file, copy both the .h and .cpp files to your sketch folder, then open your sketch. The additional files will appear as separate tabs next to your sketch's tab.
3. To include a library file in your sketch, when the library file header resides in the same folder as your sketch, use the format #include "mylibrary.h" *not* #include as the latter format is used when you want the Arduino IDE to search your libraries folder (and elsewhere) to find a library.
4. If you muck up the .h or .cpp files you can just re-copy them over to your sketch folder again whilst you experiment. If you enhance the library, and want to keep the changes MOVE the files back to the libraries folder (but do take a backup of the original files first, just append .old to the filename or something). Then refer to that library in the usual way with the standard #include again.
I guess I should have clarified this in the video better, but maybe this comment will be read by gazillions of viewers too.
Thanks for posting this question, it will benefit others wondering this.
Hi Ralph! Many thanks for the quick reply, Item 2 answers my question and works fine, I now have all three files together so I can play with them.
Please keep up the great work, very interesting content, I am also going to watch more of you videos.
Regards
Graham
@@RalphBacon Well, I don't know about gazillions... but I've definitely read it. Comments can hold vast amounts of additional information and are worth reading.
@@RalphBacon Thanks for the informative video.
As for #2, it would seem that you're opening a copy of the library that you're using via , not the actual library that it's compiling? That there's not an easier way to view libraries with the IDE is a bit of an annoyance (not your fault, obviously). Seems like Notepad++ or similar is a good way to take a peak at them to figure out what functions etc are available, but that's not perfect either.
arduino noob here... after months and months and months of studying, watching videos... its the first time i see how to collapse sets of codes... my gosh, so many tutorials and this is the only one that explains that! thank you!
Glad I could help! Funny what you find at unexpected moments!
thanks for this lesson with detail explanations on each lines and resons. I picked up many knowledge not known before as I was trying to make my own library.
Glad it was helpful!
I very much like the way you teach. It is as if I was sitting down with a friend or colleague who wants me to understand something, but wants it to be a pleasant experience.
Nice of you to say, thank you 😉
Ralph, I came across this video (#71) a few months back, and am now proud to say that I have written my first Arduino library. I've a lot of work to do on the code, but I have built a class with methods, and it is likable into a users sketch. I am now working to configure it to allow easy importing into the IDE and compliance with Github standards.
So many thanks for your inspiring and instructive videos.
Fantastic! And by writing the library your understanding of Object Oriented Programming has taken a giant leap for Dale-kind! Really happy about this!
@@RalphBacon Yes and thanks to your tutelage, I have now written and tested a Python class. This could become addictive 😁
Wow thank you so much. Some people are complaining about how long this video is but its was great because you not only created a library live in front of us but also explained the background of whats happening. Great Video!!
Complaining? About MY video lengths! Actually, Aldrick, I gave up trying to make shorter videos some time ago and now just make them whatever length they need to be, usually around the 30-minute mark. It's about the right length if we're going to discuss stuff in the correct level of detail, don't you think? Well, it seems you do! Thanks for posting!
Thank you Ralph. I hesitated to start a 38 minute video tutorial, but it was worth it just for the calm Pommy accent and absence of duffa duffa music! I am an old veteran since the 70s of programming assembler on bare metal for embedded realtime controls, and only just in retirement wrapping my head around C/CPP. Some of the syntax conventions really "get" me, and I have to remind myself I am dealing with a very simplistic one-pass compiler that needs lots of cues in order to work.
The work flow from multiple tabs / project folder to files in the library folder was very helpful.
Glad you found it useful, David. All my videos are a bit long but watch them at 1.25 speed and it shaves many minutes off the length. And I don't sound like a chipmunk on helium either!
I never thought I would understand such a complicated subject but you made it so understandable. Thank you so much! You have a special 'teaching gift'...
Glad it was helpful!
Beautiful, non ambiguous, simple example... Clear and pleasant to listen presentation...
Glad you liked it!
Great informative video. This has helped me to no end.
Thank you 😀👍🏻
Thank you, Harry, for your supportive words. I'm glad it's helped you (and hopefully others too!). Once you've done it a couple of times it gets quite automatic to move stuff into a library. Good to hear from you.
I do programming for past 4 years and this was like the best tutorial which Ive ever seen. Thanks!
High praise indeed, Mibra, thank you for that and for posting here.
Hi Ralph,
Your videos are wonderful. Very instructive and very easy to understand. I have written my first library using your video and just wanted to say thanks and keep it up!
Thank you very much Timothy, I'm glad I'm being of some use! Like most things, once you're shown how (and, possibly, why) then the mystery disappears and you think "Is that it then?" I hope you create many more libraries (I must admit to cheating whilst developing and just stuffing items into a .h file until I'm ready but don't tell anyone!). Thanks for posting, much appreciated.
Omg this is so good... I learned a lot today for me to try write a code to sniff the LIN bus protocol. going to use this way of clean setup and also make it easy for me to reference to other codes available. now I can connect the dots a lot better.
Glad it was helpful!
Totally brilliant ! Thank you so much for explaining that ... and at a good pace: neither too fast or too slow, and in an accent that my ancient ears can cope with!
You are most welcome James Hardiman, I'm glad you like the video. Nice to hear from you.
Thanks Ralph. A straightforward explanation that has stopped me binning my Uno! I have 18 switch x inputs to pick up and three sensors
Glad it helped!
Binning you uno! I am deeply offended. Joking, but glad it helped.
Oh, and ... thanks to Benny for helping you. Here in Cirencester Sammy and Morgan were helping me to absorb the knowledge.
Benny says that you are most welcome too, and sends his regards to Sammy & Morgan who are probably experts in Arduino C++ now (cats learn fast apparently). 😺
Thanks for this walkthrough, Ralph. I'm coming from other programming languages (primarily web dev), and this was a great overview of the idiosyncrasies of c++ when it comes to object oriented code and including local libraries.
I had been reading through articles and posts that explain the same thing, but none of them were as clear and well presented as this video :)
Thanks for taking the time to make this and for posting a link to the code. It's much appreciated :D
Well, thank you, cschmitz, for your kind words! I'm glad to have helped. I, too, have taken many paths in coding, from µProcessor assembler through various BASIC dialects, C#, JavaScript, and C++. I think once you have a programmer's way of thinking then the language is secondary to what you want to do, so you (as a web developer) are well placed to mastering this very quickly. Thanks for posting and good luck in creating your own libraries!
great and clear lesson ... needed to refresh classes... need to refresh everything to be honest.:) thanks a lot Mr R.B.
You're welcome!
I forgot how good this video is. I think the grammar of classes are what make them seem intimidating. The textbook jargon like instantiate, constructors, deconstructors, self.label type stuff. But if people let go of the jargon like you're showing then people understand it better. When I started, and I'm no expert but the 'self.' Stuff got me confused the worst because all the constructor variables were just stated above. Haha
When I created this video, Joey, I was very careful to _not_ mention anything OOP-related as I knew it would put viewers off! Talking about polymorphic inheritance might be a bit off-putting (just a wild guess). 😁
Thank you so very much. One of the best tutorials on C++ code that I have seen. It helped me a lot. You are the best.
You're very welcome!
You are a king. In 1.5x it is the perfect introduction to Arduino. Thank you so much
I suppose I could speak slower, that would confuse you! Glad you liked it, thanks for posting.
Ralph many thanks for a very clear explanation of how to create an Arduino library. Apart from tidying up the sketch I would say the other main reason to create a library is for code that you tend to find yourself using in several projects. Once it's been debugged then you can forget about the dirty details and simply use it every time you need those methods. BTW I never knew about the IDE being able to collapse or 'fold' code so thanks also for that insight!
You've grasped the real use of a library completely, Philip. TBH even if you don't use the code elsewhere it's still good to 'modularise' the sketch this way as you quite rightly say you can forget about it. Glad you now know about code folding, it's quite useful. Thanks for your supportive words, appreciated.
Thank you. I really liked the way you explained everything without rushing :)
Well thank you Goldichan92, I appreciate that you took the time and trouble to post that. Unless my Arduinite viewers tell me how I'm doing I have to guess which is not the best way to build up an audience. So thanks again, and keep watching! And don't forget, if you like what you see, consider subscribing! :)
Superb explain on how to make a library. Thank you sir.
You are most welcome!
You are the man, I could not figure out how to use the serial port in my cpp file. I tried everything until you showed the method to - begin serial. Like you said, there just isn't any useful online documentation available for this - JOLLY GOOD SHOW !
Glad this video helped you, Jeff, nice to hear from you.
very helpful!
I also had forgotten the semi-colon at the end of the class declaration. Luckily, it was the first thing I randomly landed on when I was flipping through the video to check if it was any good.
I'm glad it helped, Jason, thanks for posting.
Many thanks Ralph, have just written my first library. Excellent resource!
Awesome, Bernebeer! Congratulations on having done this. Now you have started you can progress to more complex libraries. Perhaps one day I will be using a library that you created, who knows. Thanks for letting me know, great post.
Hello Ralph, very many thanks for the great overview within 30'. Well done ! - All the Best, Franz-Juergen
Glad you liked it, Franz-Juergen, ziemlich einfach, gel? Now that you have some knowledge you can create your own libraries, but start slowly, as there are some 'gotchas' as they get more complicated. Thanks for posting.
Extremely interesting and useful. Wish I had found it a couple of months ago when I was just getting started with Arduino. I'll have to watch it a couple of more times as I'm a slow learner.
I have to watch my own videos sometimes to see what I said!
Thank you for this great video .I must watch again
Please do!
Hi Ralph
Thanks for this clear explanation ! I created my first library files and ... it works !! :)
You sound surprised! Yes, once you have written one library you can progress and learn all about classes, objects, private, protected and public functions and variables... the list goes on. Well done!
The reason why the text does not come out correctly while the "void setup() {...}" is not called, is very simple.
The "void setup() {...}" is just part of a basic library framework library that sets up stuff like buffers, timers and so on. While the "void setup() {...}" was not called already, the text written makes the serial-out-buffer overflowing and from the most characters, apart from those that had gone into the hardware fifo from the USART hardware, are lost. So it is a pre-initialization issue, since in the first version the constructor was already called at the "TestLib testlib(true);", before ever entering "void setup() {...}".
By the way, putting serial initialization routines in classes is very bad style, since having more classes then just your gives the problem that they might all try to intialize serial, one after another when called trough out constructors/methods.
So your "serial.begin(...)" to put once into your "setup()" is certainly the better way to go, because then it does not get out of control if, when and how many times this is issued.
Spot on, I realised this belatedly, but as it was more about how a library is constructed I kept it going. The whole serial thing is a bit of a mess - I traced the code (the Arduino.cc written code) and it really is a bit convoluted, to say the least. Definitely not the best thing to put into a library example. I hope you still consider there is still value in the video though for others to learn about OOP.
Of course it is usefull, expscially for beginners into C/C++ along with Arduino, to see how Libraries could be done, instead of having endless spagetti code like looking source files. So I think your video is very good to take a look into the Libs aspect of Arduino developments.
Incredible explanation and pace
Glad you liked it!
very helpful. I have done a lot of programming but never really took the time to sit down and do that library stuff (eventhough I started a few times) .
Will do again with help of your video.
Oops, Sorry, I forgot I already commented on this video. Must be my age. Anyway, extra proof I like the video
I think you have just proven that you REALLY like this video! I'm happy with that! Constructing library classes is not magic, voodoo or only for "experienced" programmers. It's a series of steps and concepts that can make your programs "better" (oh, dear, red rag to a bull I know). Best thing is to try it with a really, really simple function (as per my demo) and get that working - then build on that. Thanks for reiterating your love of this video, I hope others feel the same way :)
indeed. I am no stranger to making 'classes' but wrapping it in the
library files is something I just haven't taken enough time for yet to
be able to do it fluently. Enjoy yr weekend
Yep, DRY, good work.
So glad I found this. Thank you for your efforts.
Glad you liked it, Dick, thanks for posting.
Thank you very much for your clear and rich explanation.
Glad it was helpful!
The most high quality thing, thank you
Glad you think so!
.cpp is C++ as that is what the Arduino is written in, and that is what you actually code in (Well C and C++)
Yup, I think we got that sorted now!
Great video Ralph. This steps it up a gear for anyone who wants to understand object oriented programming. Once you 'Get It' the concepts are then only language specific. C++ is a bit unwieldy with its header files and you explained the concepts really well. The only thing , (and could be difficult for beginners), is Scope, the :: syntax.
Really good Ralph, excellent mental workout following the code, cheers Alan
Ha ha, I'm glad your brain got a good mental workout trying to follow my meanderings through class construction!
But the point you make about 'getting' the concepts is spot on. Once you have that lightbulb moment all else is 'just typing'. I'm hoping enough people take my example, break it, fix it, break it again and basically get a good grasp on how libraries work and in doing so understand how classes work too in the (semi-) object oriented world of Arduino C++.
Thanks for your kind words about me explaining it well. I don't normally watch my videos all the way through (after a couple of hours of editing I've usually had enough of my own voice) but I felt this time I had to make sure it all hung together properly and I think it does provide a good starting point for Arduinites expanding their wings, so to speak.
Thanks for posting Alan, always good to get constructive feedback.
Thanks for a great tutorial it has helped me on my Arduino journey as it’s time to really understand what some libraries do and the place to start is making your own.
Glad it helped!
Thanks for a very clear and informative video. I had wondered what the cpp and .h files were for - now I know. Not sure I like OOP, it just adds another level of complexity.
Many thanks for sharing this.
Best wishes
Arthur
Hi Arthur! I'm glad you enjoyed the video, but what's all this about "adding complexity"? :)
OK, it IS something different but simple classes in Arduino can lead to better programming. Mmm, perhaps I need to do an introductory video into classes (well, OOP) for Arduino! Maybe. Lots of other stuff to cover first.
Anyway, glad you liked it and thanks for posting, great to hear from you.
I have subscribed and looking forward to more videos - I have a lot to learn!
Thanks again for another very useful tutorial. Can't wait to write my own library in my next project.
Yes do try, Bob (Yoda: there is do or not do, there is no try), it's not difficult but start small and work your way up! Thanks for posting here, nice to hear from you. (I hope you got the Yoda reference)
“PATIENCE YOU MUST HAVE my young padawan”
Very good. Note: the Github TestLibrary example has #include instead of #include "TestLibrary.h". It does not compile as #include .
Ah! An anomaly for the Arduino IDE then. Strictly speaking, quotes around a library simply mean "look in the sketch folder _FIRST_ then in the usual place(s)". But without the quotes it won't look in the sketch folder at all, it seems. I shall be aware of that in the future.
Thank you for your time and effort in making this video, i was able to follow along in real time recreating the sketch while modifying various attributes of it. Very good tutorial highly recommended.
Thanks Chris! You did exactly what I hoped other viewers would do. It's only by actually doing that you learn things. Thanks very much for posting.
@@RalphBacon Not a trouble I always leave a like. Don't suppose you fancy making a video about using other libraries with a library.
Got square eyes trying to figure out how to include the wtv20sd16p library in my library. 😅
You should be able to just #include the library.h you want within your library in the standard way. What's the problem?
@@RalphBacon I did figure it out in the end but it's surprising how scattered the info is, I couldn't figure out where to instance the object correctly to use it throughout the library.
I actually found two methods one used pointers which I no longer use but Google hot to use a library in a library and there is no definitive guide or tutorial on the do's and don'ts thanks for your reply though.
Thanks much Ralph!
Here's where I get into stall mode.
For instance if I wanted to output an instantiation message to another device apart from a serial port or output to another library function ie. write to an SD card then things get confusing.
I know that your code is just an example and that any 'portable' library wouldn't open a serial port regardless, but further
thinking brings on many complex options.
Great example nonetheless!
Hi ya Phil, interesting comment there!
If you wanted to output serial data to another device, when we have already used it for our debugging window (Serial Monitor), you could always use the Software Serial library which allows any pin to use serial data. I've used it many times and it works well and stops you being restricted to pins 0 & 1.
But as you say, this was but an example showing how to put a library together (rather than concentrating on the functionality) and I'm glad you liked the example. Good to hear from you.
Thanks for the video Ralph - yes I know it's mature. Lovely to see Benny again. I think the reason you cant put Serial.begin in a constructor is that Serial is a static class, it's a single resource. That's to say you can't really create another Serial for each instance of your class. I created a Ping)) class with OTT features including limiting the time pulseIn will wait based on a user decided maximum distance of interest. I wanted to check the maths with a debug method; in that method I simply use if (Serial) { print lovely stuff}.
A good workaround you have there. Another solution is to try a singleton for the Serial.begin but I suspect that might not work either. Probably just better is the user sets up the Serial interface anyway, as it might be Serial1 on another device.
Great stuff. Revisited this video today when I actually needed the information.
Don't tell anyone, Pekka, but I do the same when I need some (good) advice, heh heh! I guess as long as you know there is a video with information here then it's perfect that you returned and watched it when you needed it. Thanks for getting in touch, good to hear from you.
Excellent video, simple and easy to follow. My wife also liked your cat. Regards
I feel sure I would also like your wife, as anyone who is a cat-lover is a friend of mine (and Benny). Glad yo liked the video, thanks for posting.
Nice job explaining what can be somewhat daunting for those learning. One thing, when coding in C/C++ you should also include a destructor in the class, but not sure if necessary on an MCU which will most likely loop forever anyway.
Destructors can be included if there is ever a need to destroy the object, good point, thanks for mentioning it.
Very nice tutorial! The explanation speed was perfect since it allowed me to think deeply about what you were saying. I subscribed to your channel too. Thanks a lot!
Thanks for your post, Gabriele Fugazzi, I'm glad you enjoyed the video. Good to hear from you.
Love this about making libraries.
Plz make another video of making libraries.
Thanks for your post, Hans Sandberg, I'll think about making another. Good to hear from you.
@@RalphBacon this is definitely the best arduino library tutorial so far on UA-cam and it's nice to see you answering peoples question on your older videos. i'll keep eye on for second part. Love from Finland👍
It has been many years since I have done it, but if you break the source code file into different files according to the different methods in the class, GCC will include only the functions called in the final binary. It will do this process during the linking process. An example is the standard libraries. If you examine the libraries they are an agglomeration of separate object files per standard function.
Yes, you're right of course Uzi, the compiler/linker is intelligent enough, thank goodness, to only include code that is actually called! Just as well, given the limited space in an Arduino Uno. For us Arduinites that have created their own 'Utilities' library (a collection of 'useful methods') it means that not all the library is included each time, so it doesn't really matter how many methods you place in it (within reason, we don't want a huge monolith of unrelated functions!).
Again relying on memory, The procedure of separating the functions or methods is tedious and you have to pay attention to the separate source files, edssentially treating them as a separate project each.
Hi Ralph!
Thank you for this amazing vidro, made it realy easy!
You're very welcome!
Oh! Good man for showing me the option to collapse code!
Happy to help! It's the little things that can make a big difference!
Very helpful information for sure. Thanks much for taking the time to explain this.
Thanks for that, gene guru1, nice to hear from you.
I QUEST ALWAYS BENNY IS HELPING OUT! VERY GOOD PRESENTATION RALPH
Thanks for your post, demetrios demetriou, good to hear from you. Benny is pleased too!
But first I must feed Benny!!! LMAO :) Love it
If you are new to my channel, Joel, you may not realise that Benny writes most of the C++ code. If he does deign to let me have a go he then monitors everything I write with a beady eye. He is a hard taskmaster.
Of course, if you have watched more of my videos than you already know this and the fact that he sometimes sneaks into my workshop at night and corrects all my syntax mistakes, recompiles everything and uploads it all to the µcontroller board I'm using. I'd be lost without him.
RIP Benny
Fantastic explanation! Thank you very much.
Glad it was helpful!
Hi, Ralph.
You explained this quite well. However, I'd like to share a convention I've used in C++, PHP and several other languages.
When writing a class, I will always add a private variable (as a programming flag) named 'debug', along with a setDebug() function. Throughout the code of the class, I test for this value to determine whether to display generalized debug messages, much like you did with the _msg variable you used here. Then, from the main "sketch", I call object.setDebug(true); while developing, and object.setDebug(false); when all is working.
Another thing I include in every class is a public function named ReportSelf();
This function reports every variable name and value the class contains.
I find these practices to be quite useful, and in fact use them a *lot*.
Hi there chopzuki! Your points are well made and should probably be standard when creating a class (oops, I said that word again, I've just lost 50% of the viewers reading this post!). Seriously, though, when using classes such things become much easier and abstracted away from the main sketch.
You've probably noticed my use of a templated global debug function in my other scripts which beginner Arduinites might not have fully understood but at least grasped its usefulness. At least it stops the dreaded if(debug) Serial.print.... littered throughout the code!
Glad you visited, I hope you stay, and thanks for that excellent point in your post, most appreciated by me and others reading this :)
The usefulness of this approach is two-fold:
First, the _debug flag is quite useful during class development.
Second, even when the _debug flag is set to false, the ReportSelf() function is especially useful when working with database records to help ensure data is being handled correctly.
This is a great suggestion and is very helpful during development. The only caveat to this approach is that unlike general computers, microcontrollers have very limited amounts of memory for code and stack variables. A better approach would be to use a preprocessor directive to remove any debug code that you can during builds for "production". I'll try to build some example code and post it up in the next few days.
The reason why the constructor (ctor) behaves differently to other methods is because it is a very different animal. Methods (other than the ctor or destructor (~classname)) are stored differently. They are in fact static code stored in the code. This affects the 'lifetime' of the methods. Yes, there is a difference from other static methods and functions and that is 'this'. 'this' is a hidden parameter to all non-static methods. The parameter is in fact the first in the parameter list; such is the case even if there are no declared parameters (i.e. classname::foo (void);). this is a pointer to this instance of the object. Now the constructor has a very short lifetime only surviving as long as the object is instatiating; as such the constructor can only be accessed when a variable of the objects type is declared. or new is used. A call to a serial method shares the cycles with your code (unless it is blocked by, say delay(100). So if one watched code such as [serialPrint('Test)'; digitalWrite(13, HIGH); ] on a logic analyser, one will observe that the TX pin becomes active AFTER pin 13 goes high. Now, if that behaviour is repeated when calling serial from a constructor, that temporary string created in the parameter of the call, may no longer exist. As serial accesses the string character by character, later characters cease to exist before the message is sent. Arduino doesn't support new or destructors (because no libc functions accessing dynamic memory are supported). Constructors are partially supported but only for access to the object's variables.
BTW I am confident that Ralph is fully cognizant of 'this' etc. I just mentioned those aspects of the constructor problem for his other disciples who, like me, are lesser mortals.
I think, Michael, you underestimate your already considerable skills on OOP, given your posting above, nicely put. What you have described belongs in the "advanced" Arduinite class, of course, and I should have remembered (or at least understood) why there are difficulties in putting that Serial.print in the class' constructor.
What is clear to me is that most writers of libraries (and therefore classes) do already understand the above and therefore that is why they suggest the addition of a begin() function; it cleans it all up rather nicely as well as using a well-established pattern that beginners can grasp very easily.
Thanks for the excellent explanation above; if nothing else it makes it clear why I had that issue, like most things in computing there's *always* a reason for a computer's behaviour even if we don't understand *why* at that time! Great to hear from you and I hope you enjoy the other videos on my channel :)
I enjoyed this video, as I have with all your presentations. It is always a joy to look down my list of subscriptions and see that you have submitted a new submission.
I couldn't agree more on your comments on libraries and their valuable facilitation of code re-use. You are right to encourage your viewers to gain confidence in developing their own libraries. We are all beginners in this environment that is changing so quickly. Rapid change makes books poor resources for all but the most fundamental aspects of embedded development. However, all that your viewers have already learnt from your and their projects could fill a library (of books). The more we share with each other the better the technology will be.
Thank you for enabling this process.
The reason the call to Serial.begin() in your ctor doesn't work is because in C++, all static objects are constructed before main(), which means the application owned objects are not necessarily fully initialized yet. You can see in arduino/core/main.cpp that USB.attach() is called in main() before the call to setup() (which is the call into your sketch's setup function), so USB (and therefore Serial) is not ready for your use until your setup function is called. In C++ you don't want any static object function calls (e.g. ctors) to call into any other static objects before main() because they many not be fully initialized yet. The order that static objects are initialized is not guaranteed to be knowable. That is why many libraries have setup/begin calls that need to be called in your setup function, after all static objects have been constructed. Otherwise, ctors are not particularly different that any other code - all code is stored in PROGMEM. There are a few caveats with ctors/dtors, mostly related to inheritance and virtual functions.
Great video helped me a lot with my project! Keep up the good work!
I'm pleased to hear that Davis, excellent! Thanks for posting.
Hi Ralph. This video helps me a lot. Congratulations!!!
Thanks for your post, emilio zelione, good to hear from you.
the compiler is smart enough to know which functions are usend and just compile the ones you use in your code ;)
True, Dr. Jones, true. Or is it the linker? Whatever it is, I think we are now all in agreement that unused functions and/or libraries are not included in the final, downloaded hex file, just as well! Thanks for the confirmation and posting.
Ralph S Bacon thank you for the tutorial ;) you could do a second part and show how to add example sketches and library properties :)
That's a good suggestion, I shall add it to the list. Thanks for posting.
Thanks a lot for the clear explanation. I hope your cat did not hide any components or knock anything off the table
Benny is always hiding components from me!
Great video Ralph. Oop for newbs is a hard topic to teach. When I went to university they were just defining the standard for oop in c/c++ so I missed out because I stopped coding from 20 years. I had a fun time learning all the arduino basics because it all came back to me. It woke something in me so I took an advanced pointers course, data management and then I took the course for oop and made like ten fake entities then wrote code based on the classed I created. Haha
You make the complex make sense very well my friend.
It sounds like your interest in OOP programming is still strong. Those developers that put in the effort to learn how to make a class will make better programs for sure.
@@RalphBacon what language do you use at work? I think I asked you this before. I apologize if I did.
At work I used C# in a dot Net full-stack environment: JavaScript, Dapper, SQL server, HTML... the list goes on.
@@RalphBacon you build end to end software for other companies ehh
Actually, the last software house I worked in for five years built software for their own company but it was used (implemented) throughout the UK. 22,000 clients. Tricky stuff!
Great tutorial! Would you be able to do a tutorial on how to deploy library’s so that others can use them and find them in the library manager?
Great suggestion! I'll have to look at that, Douglas, as I've never released a library into the wild other than on my GitHub.
It's more an introduction of OOP/C++, the function doesn't need a whole class, simply putting the function in the .cpp and making a .h file, would work too. You can even use only an .h file, because of the preprocessor… and there is the possibility to use more .ino files too.
Hey AltMarc, great to hear from you! You are of course correct in your observations, but if you notice I steered well clear of mentioning OOP hardly at all as there's nothing better to deter beginners of C++.
A large proportion of Arduinites expect (and can understand) procedural code (like VB Basic 6, perhaps!) but as soon as classes are mentioned, along with overrides, polymorphism, inheritance, templates and what have you they will go back to the 'safety' of their standard procedural code.
So I was hoping that putting a very simple function into a library class might get them using a bit of OOP (even though it didn't really require it) and so not be put off. And, of course, it might actually encourage some developers to put their code into a library so they can concentrate on new stuff they are building.
There's no easy way of learning C++ OOP without doing it - ideally doing it without realising you're doing it. Hence the video! Did I succeed, that is the question?
Great to hear from you, always keen to get my viewers' perspective on things, and I appreciate you took the time and trouble to post here.
Hi Ralph. I found the video to be clear and helpful, and I will be definitely looking at your others.
But I think you should have left the OOP out of this. I know it confused me. In fact, I only scrolled down to find this message because my research so far into creating a library led me to believe no OOP is necessary, and I wanted to check if that was true by seeing if anyone had commented to that effect.
OOP doesn't bother me, I've done mountains of it in Delphi, but I'm new to C++ and I just want to learn how move some code into a library, and not have the process complicated by unrelated concepts if not needed. I haven't yet learned how to write classes in C++, and I didn't come here to learn that now - I came here to learn how to make a library. Only after success in that, would I want to convert it to OOP where appropriate.
The video as it sits, leaves the new library writer with the notion that a library MUST involve classes, which (from what I have gathered) is simply not true. I can imagine someone with a large chunk of code involving a bunch of interrelated functions and data that they want to wrap into a library, getting into all sorts of bother trying to make them into classes when they don't actually need to (even though they probably should). If I had watched only your video, I know this would have happened to me.
In essence I'm saying that as libraries and classes are distinct concepts, they should be taught as such. Confusing them in the teaching, confuses them in the student.
I can see that you are concerned with OOP being a deterrent to some people. But I think introducing it "by stealth" where not required is the wrong approach. I would address that by a separate video about classes. (which would include an admonishment to those afraid of OOP to stop being such little girls)
I hope you see my criticism as constructive, and thanks again for making these videos.
And again a great video. I learn a lot and it saves a lot of problems
Glad you liked it, kees 7777, it's not so difficult once you're shown how to do it.
Very nice tutorial. Good content explained in a nice and relaxed way.
You found yourself a new subscriber.
Thanks for your post, Zeedijk Mike, thanks for subscribing, too. Good to hear from you.
Brilliant Video. Thank you so very much.
Glad it was helpful!
Ralph, great tutorial. I now have some idea what I'm looking at when I poke around in library files. More like this please - a debug library would be ideal.
Regards Alan
Hey Alan! I was going to include my debug routine in the library video but found that my code was "too advanced" for the compiler to figure out how to use it! Seriously! It's a limitation of the compiler but as always, there are workarounds but it just made it a bit messy and not really for a "first time" video - but I will include it (or upload it) with a future video.
At least you now have a better understanding of how the libraries hang together and can appreciate the work some of the authors have gone to just to give us Arduinites an easy way of interfacing with bits of hardware. And of course, you could create your own libraries just to make things easier to work with. A nice cold Saturday afternoon project, perhaps?
Thanks for the feedback and suggestion, great to hear from you.
you had me at "first thing to do....let the cat out" lol
Ha ha! Benny must have demanded to be let out of my office!
.cpp just means "C++ (C plus plus)" file
Indeed you are correct, Steve, that was your starter for 10. Now, what does .ino stand for? Previously known as .pde, which stands for? Finally, why did Arduino.cc change it all? Why not just keep to one name for everything, ideally, .cpp? More questions than answers, I'll be bound. You're not allowed to Google the answers, either!
Ralph S Bacon lol
@@RalphBacon Not sure what .ino stands for for .pde is an extension from the Processing language which Arduino and the Arduino IDE is based upon. I think They changed it to .ino to make it clear that the file is an Arduino file instead of a .pde (Processing) file. If they did not do that many noobs would run into issues.
@@RalphBacon I guess the .ino is just ardu*ino*
Nathan Villicaña-Shaw I remember this happened to the noob typing. 😂
Beautiful Benny...
Thank you kindly. Benny has now been gone for 8 months or so and very greatly missed.
@@RalphBacon Oh.... so sorry...
watching old ones, waiting for new ones. those library cards are some distance apart.
New videos are there now, Lez, a couple at least in the last two weeks!
@@RalphBacon your library cards still puzzle. There not Exactly next door to each other
Oh I'm going to use this info for sure. Thank you sir
Excellent, Ricky, start small and work up. And look at other libraries to see whether there are any other techniques you might use. Great to hear from you.
Thanks Ralph. Great info! I'm used to C, not C++, but I will definitely switch over. Then I can put my common useful functions in a library instead of re-copying them into various ino sketches(and which one has the latest modified version?). I saw that I can also create a subfolder in ../libraries/TestLibrary/examples/LibraryExample1/LibraryExample1.ino so that it is visible from the Arduino ide files/examples.
GREAT STUFF!
Made my day!
If you know C you will pick up C++ very quickly (but you will also confuse the two I'm sure)! I'm glad this video helped you though!
This helped me a lot.
Great! Glad it helped!
Really good work and explanation, you have a new subscriber, thank you
Thanks, Dean, glad you found it useful and thanks for subscribing!
When I was doing C back in the days of Borland C, cpp was brought in as I understand in programs to differentiate C code (vanilla) from C++ cpp = c plus plus
Yes, cpp is really the object oriented capable platform, although much of the syntax is the same as pure C.
Hi Ralph. At 21:16 in your video, it's only print "Te". You must to write this line after the Serial.println("The blabla...'); :: Serial.flush(); 😉
Actually, Arduino now admits they made a mistake with their Serial.flush implementation. It _usually_ means "clear down any outstanding characters in the output buffer" but they implemented it as "wait until the buffer has been naturally cleared by being sent out the UART".
I suspect that curtailed message was because the Serial.begin() was in the wrong place, but whatever the reason I've always had it work just fine since!
Very helpful, thanks!
Glad it was helpful!
Very nice explanation, thanks!
Glad you liked it, thanks for posting.
brilliant tutorial , explained so well thanks
Hello Arduinite! I'm currently on vacation 5,000 miles away from home so I'll have to be brief with these comments until my return, mid-July.
Glad you found it useful, John, I like comments which contain the words "brilliant tutorial"! It's not so hard once you get to grips with the fundamentals. Thanks for posting.
thak you
you are the best in youtube
Very kind of you to say!
Brilliant ! I'm sure you have discovered by now that .cpp does indeed mean "c++".
Yes, I have! It's a pity that Arduino decided to "brand" their "sketches" by having the "ino" suffix but I guess that's their call.
Excellent video. Thank you!
You are most welcome Dan M, I'm glad you like the video. Nice to hear from you.
Amazing stuff! Subscribed. Cheers!
Thanks, Daniel, glad you liked the video and thanks for the sub!
Thank you, sir. You helped me a lot.
I'm happy about that, Ryan, keep going!
best tutorial on libs. thanks.
Thanks for your post, iceberg789, good to hear from you.
Afternoon Ralph - Thanks for the video. Just spent ages scratching my head over the following error message
error: abstract declarator '' used as declaration
In the end the answer was simple; I had the 'usual' pairing to guard double including the header by deine and test...
#ifndef Sensors
#define Sensors
and began my class with...
class Sensors
complete with constructors, methods etc.
The lesson is the compiler preprcessor followed my instruction to define Sensors as an "empty string", it went on to replace every occurrence of Sensors with ""; so giving a class without name.
I hope I've learnt to make my double inclusion guard #define xxxxx_h so my class can be class xxxxx. I am not the first, nor will I be the last but hope the comment will also help others avoid this NOOBS trap.
Phew! Sherlock Holmes would be proud of your investigative powers there, Michael, glad you found it (and learned something along the way). I've done similar, as have countless others, just as you say. Thanks for posting.
It is a requirement with British engineering, that anything unknown during the development phase shall be named "Fred". I expect RJ Mitchell referred to the Spitfire as "Fred" in the early days.
Oh dear, most of the things on my workbench are therefore called "Fred"!
@@RalphBacon "Bill" can also be brought into play if there are multiple items 😂
I'll need Jock, Jerry and Will too!
it is better to follow his video and at the same time write the code as in the video so that you are able to keep track of the learning.
Thanks for your post, Ammar Syafiq Sabaahul Ahmad, good to hear from you.
Hi Ralph,
thank you for explaining. Unfortunately, I have one question. What if I need (I don't know, how to say it correctly) some class variable, that is shared across all instances.
For real example. I have a few moisture soil meters and I have decided, that I will write library for them. There are some instance variables, unique for each instance like "pump_relay_pin" or "moisture_limit". But I need one shared variable for the whole class. It's called "vcc_moisture_pin" and its value is same for all possible created instances, because it's shared pin, which turn vcc of all sensors on. It doesn't matter how many there are.
So, I need this "class variable", which I can set directly via class name in main program, not via instance name. This variable I want to use only in library cpp file afterwards.
Yes, I can use this variable as instance one, but I don't like it. I think, it is not programmerly correct.
What I can use now
H file
class MyLib
public:
MyLib();
byte vcc_pin;
INO file
MyLib Inst1;
Inst1.vcc_pin = 2;
What I want to use
H file
class MyLib
byte vcc_pin; // I don't know, where to put this declaration
public:
MyLib();
INO file
MyLib.vcc_pin = 2;
and then, every instance gets this vcc_pin variable with value 2, but I need to set this value in main program, not in library, because I want it versatile.
Is there any option, how to do this?
Could you please help me? Thanks a lot :)
It sounds like you need to write a public function in the class that updates that variable (which should be private, not public). Another function to read it back. But that gives you that value for the class instance you are addressing, it's not global across all instances.
You could accomplish that by creating another instance that you call globalMylib (or whatever) and use those functions I mentioned wherever you need to update or read it. What you really need is a singleton, or static class, but I only know this from C# not C++ - would have to check that out (or you could).
Great tutorial, thanks very much!
Glad you liked it Austin! And you're most welcome. Thanks so much for posting.
Great explanation!
Hey Ravindra, I'm glad you liked the explanation. Always good to hear that my videos are giving my Arduinite viewers some value.
I'm sure having TestLibrary.h, TestLibrary.cpp, TestLib, testLib & tl will all become clear and distinct with practice.
I think it important to keep the names consistent here. TestLibrary is a good name for the sketch and header, but I'm not writing that out every time so *tl* it became. You can choose whatever name you like for the class but it should still be consistent and not confusing for the compiler.
Thanks you!, very clean explication i like your style, only a note that could be tricky: in the #ifndef statement we can't use the same name of the library, this could be confussing because the declaration of the files .h .cpp and the constructor needs to be namend equal.
Indeed, you are correct, the common practice is to use a name in capitals or with underscores after the name or both - you get the idea! Pity that I used a lower case two character name called tl (for test library) but then again this was just a demo)! Thanks for the advice, good to hear from you.
Ralph: How do you find out what functions a library includes and what there parameters are? I want to use the AccelStepper library but I don't know what functions it includes or how to use them. Thanks
Most libraries are on GitHub. The GitHub for a particular library should have documentation (or a pointer to the Wiki for it). This will tell you everything you need to know.
Secondly, if you look at the library, in particular the library headers (files ending in ".h") these will provide the PUBLIC functions you can call. From there you can find the relevant function in the associated c++ file (ending in ".cpp") and read it, to see whether it's documented enough.
Also the GitHub will probably contain an "Examples" folder with some simple get-you-going sketches. Another source of gold to beginners.
Thanks Ralph!
Thanks for that, NeXus, nice to hear from you.