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!
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.
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.
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!
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.
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 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!
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.
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.
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!
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). 😺
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 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 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.
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.
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!
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.
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! :)
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 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). 😁
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.
@@RalphBacon this is definitely the best arduino library tutorial so far on TH-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👍
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)
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.
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.
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.
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!
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.
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
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.
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.
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.
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.
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.
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.
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!
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!
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!
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.
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).
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.
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.
Hi Ralph I`ve enjoyed your many videos over the years, thank you. I have a question how to create a custom library in PlatformIO, there seem to be various issues with this, having read various forums and trying to implement your code within PlatformIO making this way above my pay grade intellectually and was hoping for an insight to point me in the right direction. Many thanks And keep up the good work Andrew
Creating a custom library in PlatformIO is very similar to when using the Arduino IDE, Andrew. You still need the ".cpp" file and the ".h" header files which you can create in the "lib" folder and #include "lib.h" (whatever you called it) into your "main.cpp" sketch (which resides in the "src" folder, of course). Then, to test the library out (probably as you're writing it) compile your "main.cpp" sketch and see what errors you get! Best to do this incrementally, by defining some (public) functions in the header file of your library and put in some placeholders into the supporting .cpp file that do nothing except display a message that you've called that function. The good thing about PlatformIO is that you can use the "lib" folder for libraries that never, ever change (or that you don't ever want to update for a particular sketch) or you can use the "include" folder but tell the PlatformIO system that you will only accept updates up to a certain revision point, such as accepting all revisions to version 2 but you won't accept new version 3 for this particular sketch. This ensures that future enhancements to a library won't break your sketch some distant time in the future (which happens all the time in the Arduino IDE). However, all that is once your library is written and tested, so have a go with that part first.
Dear Ralph, Great video, thanks! Explained exactly what I am trying to create at the moment. And I still have a questions.. One thing I did probably wrong is that I put all the functions inside *.h file, did not made and *.cpp file. It somehow works, but let me change it and see it working again. In my project (remote control tank) I am going to use GPS module and GSM module (and some others as well), so I really do not need that additional code into my main code, just a results, e.g. GPS coordinates, so library is excellent solution.
Technically speaking, Valters, putting all your code in the header file (whilst punishable by watching the BLINK program for several hours) _should_ work. But, as you are aware, it's just not done that way so do split them as you have outlined - and let us know how you get on.
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.
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.
Thanks Ralph - very informative. Do you know if it is possible to inherit a more complex type like HttpClient and create a custom library wrapping HttpClients functions in the class?
Yes, absolutely, Robert. Include the library you want to wrap, and in the class constructor inherit the underlying class. For example, if you wanted to inherit the "Print" class so you could "print" characters to a new LCD screen you could inherit that (but remember to define all underlying virtual members): #include class myLCDPrinter: public Print { public: virtual size_t write(uint8_t); etc using Print :: write; } This then gives you access to ALL the underlying print functions (you don't need to define each one individually). Your class must now declare this method: size_t myLCDPrinter :: write(uint8_t value) { send(value); return true; } The method you write to do the "send" will be declared as "private" in your class: void myLCDPrinter::send(uint8_t value) { // your code here to do whatever you need to do to get the value // onto the LCD screen } As you already seem to know about inheritance I guess this is enough to get you started with the HttpClient!
@@RalphBacon Thanks Ralph Yes and know on the inheritance most of my recent experience (last 15-20 years) is C# so syntactically a little different :-) I copied the HttpClient virutal methods into my header class (as you can see by the comments with the exception of endOfStream() and completed() they were all inherited from Print and Client, I'm not sure if I should have included them?) My header class looks like this. class SparkfunWifi : public HttpClient { public: // Contructor SparkfunWifi(Client& client, char* serverName, char* port, char* ssid, char* pass);
// Methods /** Connect to the server and start to send a GET request. @return true if connection successful */ bool connectWifi(); /** Sends HTTP weather POST to weather.api. @return 200 if successful response from api. */ int sendWeather(); // Inherited from HttpClient which inherited them from Print // Note: 1st call to these indicates the user is sending the body, so if need // Note: be we should finish the header first virtual size_t write(uint8_t aByte) { if (iState < eRequestSent) { finishHeaders(); }; return iClient-> write(aByte); }; virtual size_t write(const uint8_t *aBuffer, size_t aSize) { if (iState < eRequestSent) { finishHeaders(); }; return iClient->write(aBuffer, aSize); }; // Inherited from Stream virtual int available(); /** Read the next byte from the server. @return Byte read or -1 if there are no bytes available. */ virtual int read(); virtual int read(uint8_t *buf, size_t size); virtual int peek() { return iClient->peek(); }; virtual void flush() { iClient->flush(); }; // Inherited from Client virtual int connect(IPAddress ip, uint16_t port) { return iClient->connect(ip, port); }; virtual int connect(const char *host, uint16_t port) { return iClient->connect(host, port); }; virtual void stop(); virtual uint8_t connected() { return iClient->connected(); }; virtual operator bool() { return bool(iClient); }; virtual uint32_t httpResponseTimeout() { return iHttpResponseTimeout; }; virtual void setHttpResponseTimeout(uint32_t timeout) { iHttpResponseTimeout = timeout; };
private: int _serverName; int _status; char* _ssid; char* _pass; }; My .cpp constructor is as follows. // inlcludes #include "arduino.h" #include "SparkfunWifi.h" // constructor SparkfunWifi::SparkfunWifi(Client& client, char* serverName, int port, char* ssid, char* pass) : client(client), serverName(serverName), serverAddress(), serverPort(port), iConnectionClose(true), iSendDefaultRequestHeaders(true) { _ssid = ssid; _pass = pass; _status != WL_CONNECTED; } The error I get when I compile my sketch is: SparkfunWifi.cpp:6:1: error: prototype for 'SparkfunWifi::SparkfunWifi(arduino::Client&, char*, int, char*, char*)' does not match any in class 'SparkfunWifi' SparkfunWifi::SparkfunWifi(Client& client, char* serverName, int port, char* ssid, char* pass) ^~~~~~~~~~~~ In file included from sketch\SparkfunWifi.cpp:3:0: SparkfunWifi.h:13:7: error: candidates are: SparkfunWifi::SparkfunWifi(SparkfunWifi&&) class SparkfunWifi : public HttpClient { ^~~~~~~~~~~~ SparkfunWifi.h:13:7: error: SparkfunWifi::SparkfunWifi(const SparkfunWifi&) SparkfunWifi.h:24:5: error: SparkfunWifi::SparkfunWifi(arduino::Client&, char*, char*, char*, char*) SparkfunWifi(Client& client, char* serverName, char* port, char* ssid, char* pass); ^~~~~~~~~~~~ sketch\SparkfunWifi.cpp: In member function 'int SparkfunWifi::sendWeather()': SparkfunWifi.cpp:48:5: error: 'client' was not declared in this scope client.beginRequest(); ^~~~~~ sketch\SparkfunWifi.cpp:48:5: note: suggested alternative: 'Client' client.beginRequest(); ^~~~~~ Client exit status 1 [Error] Exit with code=1 Thanks again for your assistance & I look forward to watching more of your videos. Cheers Rob
Whether you need to include libraries is easy enough to test; just comment out the #include and see if you get a gazillion errors! In the line "SparkfunWifi::SparkfunWifi(Client& client" how is the Client being instantiated? Make sure you have the "Client" object in your class or reference it in some way. The compiler doesn't know this is HttpClient. Write a simple sketch to invoke all this first and you might see how to include it in your class. And use PlatformIO or Eclipse as they give you Intellisense that can _really_ help when doing this sort of thing. From one C# developer (.Net in my case) keep going. Sometimes it can take a while (and a few hours Googling) but eventually the solution will be found.
@@RalphBacon Hi Ralph - I did persist and was able to get my custom class to compile - sort of - at least sorted out the inheritance side. I can get my library to send formatted JSON out the serial port and connect but when I try to serialize my JSON it the compiler complains when I uncomment serializeJsonPretty(doc, iClient); Thanks for all your help. I'll keep working on this last hurdle. Regards Rob
Thank you so much for sharing this great information ...... but I have a question... how can I include some sketch examples within the library? and again thank you so much !
Hey Baraa, glad you liked the video. But I don't quite understand your question. Do you mean how to include your library into a new sketch? Or something else? If you could clarify that would be great.
Hello Ralph. So I created a coupla Arduino libraries that were very useful for me. Maybe they're useful for others. I tend to share my knowledge with others as they have shared theirs with me. Is there a procedure to follow for proposing them to the Arduino community? 1. Are they useful for others? 2. If yes, how do I propose them to the community for review? 3. If acceptable, how do I add them to the Arduino library manager index? Thanks
Your best bet to sharing libraries is to create a (free) GitHub account. See how others have shared their libraries (including a Readme and licence) and follow the pattern. Build and they will come, apparently.
Hey Ralph Another great tutorial, BUT (there is always is one ain't there) is that watching the video, everything was great until it came time to ACTUALLY make my "magic" code into a library. I think it would perhaps have been helpful to clarify that all you actually have to do is to move the .h and .cpp (.ino) file to the libraries folder under a folder name EXACTLY the same as the CPP (.ino) files. ?? That is after all, the crucial part of accessing any library, so users need to be clear how they need to "extract them" from their project and have access to the as a library ?
Hi Ian, good to hear from you! Now, in respect of making a library, remember that whilst the .h and .cpp files reside in the same folder as your sketch (as you develop them) all will work as you might expect (as long as you #include them using quotes, not angle brackets). When you move the .h and .cpp out of that sketch folder into the libraries folder, in a folder name of your choosing (it doesn't have to be the same as your .cpp or .h file, although convention for smaller libraries does follow this) then you change the #include to use angle brackets (not quotes). The Arduino IDE will search for the actual .h file and find it wherever it is! I'm not totally sure if that's what you mean above but that is the way it generally works, so I regret causing any confusion, doubt or uncertainty in my video, smack on my wrist and I promise to be clearer in the future, really. But I do appreciate your post because others might be wondering about this too, so I hope this clarifies things. If there is anything still left uncovered please do repost. At least you keep me on my toes, which is as it should be!
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.
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.
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 Thanks for doing all these great videoes! They are simple to understand and easy to use. I have refered some of my students to use them - hope that's ok? 😊 Have you tried to hook more pcf8574 up with i/o's? How do you easily scan let's say 4 units? BR Tomas
Glad you like these videos, Thomas, and certainly direct your students to them. But if they fail whatever course it is that they are studying I take no responsibility! For the PCF8574 look at my video #49 MORE PINS PLEASE! PCF8574 Arduino Pin Extender (Easy), I'm spoiling you now!
You would't? ☺️ Of course it's their own responsibility. I teach electronics on technical college. Yes, I have seen the #49 video. It's really easy to understand and use, but what I'm asking is, if you also have an easy way to handle inputs and outputs when daisy chaining more pcf8574's? I do have a way of doing so, but perhaps your way was easier?
Thanks for this , it has given me a chance to try and debunk some previous written software ( ble for arduinos) . A question , how do we best debunk what are the available commands ( methods ) within a defined class and their uses ?
Debugging code for an Arduino is somewhat crude. It involves using the Serial.print() method to write out to the Serial Monitor (aka debugging window) messages that might help you understand what is going on or wrong. And judicious use of the delay() statement to slow things down a bit so we can see what is happening in slow motion. Newer versions of some µControllers (including the MKR boards from Arduino) allow hardware debugging but that's for the future - for now you're stuck with Serial.print(), I'm afraid.
Thanks for this amazing video!!! your explanation is very easy to understand for me as a beginner! But i have a question about what if you include a library that isn't within the same files, the memory will get lesser or still the same?
Although everything gets COMPILED when the LINKER decides what to include then anything not required is dropped so your output file remains small. Clever, yes?
Its been a long time since I checked in with you. It was sad to hear about Benny. I hope all is well with your eyes and that drama is over. Great presentation as always. What are your thoughts on copying the header and cpp files into tabs and then edit out any thing not used within the sketch. This would lighten the load on the Arduino while still taking advantage of the great libraries out there. of course, all due referencing to the original creator.
Nice to hear from you, Adrian, it's been a while. Also nice that you thought of Benny. Coincidentally it has been 8 months to the day since he was taken from us and it's still a raw wound. 😿 Regarding your thoughts on removing portions of libraries to "lighten the load" would only reduce the footprint. Additionally, the compiler/linker is quite smart and will remove functions that are not actually called. But it can make the library simpler and easier to follow. Give it a go with a simple one first!
@@RalphBacon Thanks. I am having fun with this and have so far made a simple library to blink 'SOS'. Bay steps forward but forward none the less. Cheers
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.
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.
TWO thumbs up? Wow! Actually, just the one is awesome as it tells Google that viewers are appreciating my videos. Thanks for posting golanramati11, great to hear from you.
if I can add something that you didnt cover in the video: I wrote a library to create an instance of some object and another library that creates an object consisting of an array of the first object. in the both original librarys I included standart librarys (looked like the right thing to do, thing like servo.h) but it wouldnt compile, the error said the first object does not name a type. after a long time of asking aroung and pulling hairs, I removed the standard included librarys from the second library and included only the first library I wrote and theat seemed to solve the problem. thought it could help somebody
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
Ralph, sorry this comments probably in the wrong place, could not find an e-mail for you, are you able to do a presentation on Json ?? I.E. what its useful for how to write it etc
Hmm. In these days of IoT I'm sure JSON is used more and more. I even use it in my Home Alone project sending data to and from _ThingSpeak_ . OK, I'll add it to the list!
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!
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 😉
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!
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!
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 😁
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!
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!
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.
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.
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.
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!
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!
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.
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!
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). 😺
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.
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.
great and clear lesson ... needed to refresh classes... need to refresh everything to be honest.:) thanks a lot Mr R.B.
You're welcome!
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.
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.
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!
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.
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.
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! :)
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!
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). 😁
Superb explain on how to make a library. Thank you sir.
You are most welcome!
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.
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.
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 TH-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👍
Incredible explanation and pace
Glad you liked it!
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”
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.
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.
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!
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.
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.
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.
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.
Thank you very much for your clear and rich explanation.
Glad it was helpful!
Hi Ralph. This video helps me a lot. Congratulations!!!
Thanks for your post, emilio zelione, good to hear from you.
Thank you for this great video .I must watch again
Please do!
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.
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!
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.
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!
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.
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.
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.
.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!
The most high quality thing, thank you
Glad you think so!
Very helpful information for sure. Thanks much for taking the time to explain this.
Thanks for that, gene guru1, nice to hear from you.
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.
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!
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.
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.
Fantastic explanation! Thank you very much.
Glad it was helpful!
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!
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.
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).
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!
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.
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.
Hi Ralph
I`ve enjoyed your many videos over the years, thank you.
I have a question how to create a custom library in PlatformIO, there seem to be various issues with this, having read various forums and trying to implement your code within PlatformIO making this way above my pay grade intellectually and was hoping for an insight to point me in the right direction.
Many thanks
And keep up the good work
Andrew
Creating a custom library in PlatformIO is very similar to when using the Arduino IDE, Andrew.
You still need the ".cpp" file and the ".h" header files which you can create in the "lib" folder and #include "lib.h" (whatever you called it) into your "main.cpp" sketch (which resides in the "src" folder, of course).
Then, to test the library out (probably as you're writing it) compile your "main.cpp" sketch and see what errors you get! Best to do this incrementally, by defining some (public) functions in the header file of your library and put in some placeholders into the supporting .cpp file that do nothing except display a message that you've called that function.
The good thing about PlatformIO is that you can use the "lib" folder for libraries that never, ever change (or that you don't ever want to update for a particular sketch) or you can use the "include" folder but tell the PlatformIO system that you will only accept updates up to a certain revision point, such as accepting all revisions to version 2 but you won't accept new version 3 for this particular sketch. This ensures that future enhancements to a library won't break your sketch some distant time in the future (which happens all the time in the Arduino IDE).
However, all that is once your library is written and tested, so have a go with that part first.
Really good work and explanation, you have a new subscriber, thank you
Thanks, Dean, glad you found it useful and thanks for subscribing!
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.
Dear Ralph,
Great video, thanks! Explained exactly what I am trying to create at the moment. And I still have a questions.. One thing I did probably wrong is that I put all the functions inside *.h file, did not made and *.cpp file. It somehow works, but let me change it and see it working again. In my project (remote control tank) I am going to use GPS module and GSM module (and some others as well), so I really do not need that additional code into my main code, just a results, e.g. GPS coordinates, so library is excellent solution.
Technically speaking, Valters, putting all your code in the header file (whilst punishable by watching the BLINK program for several hours) _should_ work. But, as you are aware, it's just not done that way so do split them as you have outlined - and let us know how you get on.
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.
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.
Thanks Ralph - very informative. Do you know if it is possible to inherit a more complex type like HttpClient and create a custom library wrapping HttpClients functions in the class?
Yes, absolutely, Robert.
Include the library you want to wrap, and in the class constructor inherit the underlying class.
For example, if you wanted to inherit the "Print" class so you could "print" characters to a new LCD screen you could inherit that (but remember to define all underlying virtual members):
#include
class myLCDPrinter: public Print {
public:
virtual size_t write(uint8_t);
etc
using Print :: write;
}
This then gives you access to ALL the underlying print functions (you don't need to define each one individually). Your class must now declare this method:
size_t myLCDPrinter :: write(uint8_t value) {
send(value);
return true;
}
The method you write to do the "send" will be declared as "private" in your class:
void myLCDPrinter::send(uint8_t value) {
// your code here to do whatever you need to do to get the value
// onto the LCD screen
}
As you already seem to know about inheritance I guess this is enough to get you started with the HttpClient!
@@RalphBacon
Thanks Ralph
Yes and know on the inheritance most of my recent experience (last 15-20 years) is C# so syntactically a little different :-)
I copied the HttpClient virutal methods into my header class (as you can see by the comments with the exception of endOfStream() and completed() they were all inherited from Print and Client, I'm not sure if I should have included them?)
My header class looks like this.
class SparkfunWifi : public HttpClient {
public:
// Contructor
SparkfunWifi(Client& client, char* serverName, char* port, char* ssid, char* pass);
// Methods
/** Connect to the server and start to send a GET request.
@return true if connection successful
*/
bool connectWifi();
/** Sends HTTP weather POST to weather.api.
@return 200 if successful response from api.
*/
int sendWeather();
// Inherited from HttpClient which inherited them from Print
// Note: 1st call to these indicates the user is sending the body, so if need
// Note: be we should finish the header first
virtual size_t write(uint8_t aByte) { if (iState < eRequestSent) { finishHeaders(); }; return iClient-> write(aByte); };
virtual size_t write(const uint8_t *aBuffer, size_t aSize) { if (iState < eRequestSent) { finishHeaders(); }; return iClient->write(aBuffer, aSize); };
// Inherited from Stream
virtual int available();
/** Read the next byte from the server.
@return Byte read or -1 if there are no bytes available.
*/
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek() { return iClient->peek(); };
virtual void flush() { iClient->flush(); };
// Inherited from Client
virtual int connect(IPAddress ip, uint16_t port) { return iClient->connect(ip, port); };
virtual int connect(const char *host, uint16_t port) { return iClient->connect(host, port); };
virtual void stop();
virtual uint8_t connected() { return iClient->connected(); };
virtual operator bool() { return bool(iClient); };
virtual uint32_t httpResponseTimeout() { return iHttpResponseTimeout; };
virtual void setHttpResponseTimeout(uint32_t timeout) { iHttpResponseTimeout = timeout; };
private:
int _serverName;
int _status;
char* _ssid;
char* _pass;
};
My .cpp constructor is as follows.
// inlcludes
#include "arduino.h"
#include "SparkfunWifi.h"
// constructor
SparkfunWifi::SparkfunWifi(Client& client, char* serverName, int port, char* ssid, char* pass)
: client(client), serverName(serverName), serverAddress(), serverPort(port),
iConnectionClose(true), iSendDefaultRequestHeaders(true)
{
_ssid = ssid;
_pass = pass;
_status != WL_CONNECTED;
}
The error I get when I compile my sketch is:
SparkfunWifi.cpp:6:1: error: prototype for 'SparkfunWifi::SparkfunWifi(arduino::Client&, char*, int, char*, char*)' does not match any in class 'SparkfunWifi'
SparkfunWifi::SparkfunWifi(Client& client, char* serverName, int port, char* ssid, char* pass)
^~~~~~~~~~~~
In file included from sketch\SparkfunWifi.cpp:3:0:
SparkfunWifi.h:13:7: error: candidates are: SparkfunWifi::SparkfunWifi(SparkfunWifi&&)
class SparkfunWifi : public HttpClient {
^~~~~~~~~~~~
SparkfunWifi.h:13:7: error: SparkfunWifi::SparkfunWifi(const SparkfunWifi&)
SparkfunWifi.h:24:5: error: SparkfunWifi::SparkfunWifi(arduino::Client&, char*, char*, char*, char*)
SparkfunWifi(Client& client, char* serverName, char* port, char* ssid, char* pass);
^~~~~~~~~~~~
sketch\SparkfunWifi.cpp: In member function 'int SparkfunWifi::sendWeather()':
SparkfunWifi.cpp:48:5: error: 'client' was not declared in this scope
client.beginRequest();
^~~~~~
sketch\SparkfunWifi.cpp:48:5: note: suggested alternative: 'Client'
client.beginRequest();
^~~~~~
Client
exit status 1
[Error] Exit with code=1
Thanks again for your assistance & I look forward to watching more of your videos.
Cheers
Rob
Whether you need to include libraries is easy enough to test; just comment out the #include and see if you get a gazillion errors!
In the line "SparkfunWifi::SparkfunWifi(Client& client" how is the Client being instantiated? Make sure you have the "Client" object in your class or reference it in some way. The compiler doesn't know this is HttpClient. Write a simple sketch to invoke all this first and you might see how to include it in your class. And use PlatformIO or Eclipse as they give you Intellisense that can _really_ help when doing this sort of thing.
From one C# developer (.Net in my case) keep going. Sometimes it can take a while (and a few hours Googling) but eventually the solution will be found.
@@RalphBacon Hi Ralph - I did persist and was able to get my custom class to compile - sort of - at least sorted out the inheritance side. I can get my library to send formatted JSON out the serial port and connect but when I try to serialize my JSON it the compiler complains when I uncomment serializeJsonPretty(doc, iClient); Thanks for all your help. I'll keep working on this last hurdle. Regards Rob
Thank you so much for sharing this great information ......
but I have a question... how can I include some sketch examples within the library?
and again thank you so much !
Hey Baraa, glad you liked the video. But I don't quite understand your question. Do you mean how to include your library into a new sketch? Or something else? If you could clarify that would be great.
Brilliant Video. Thank you so very much.
Glad it was helpful!
Hello Ralph. So I created a coupla Arduino libraries that were very useful for me. Maybe they're useful for others. I tend to share my knowledge with others as they have shared theirs with me. Is there a procedure to follow for proposing them to the Arduino community?
1. Are they useful for others?
2. If yes, how do I propose them to the community for review?
3. If acceptable, how do I add them to the Arduino library manager index?
Thanks
Your best bet to sharing libraries is to create a (free) GitHub account. See how others have shared their libraries (including a Readme and licence) and follow the pattern. Build and they will come, apparently.
@@RalphBacon ok!
Beautiful Benny...
Thank you kindly. Benny has now been gone for 8 months or so and very greatly missed.
@@RalphBacon Oh.... so sorry...
Hey Ralph
Another great tutorial, BUT (there is always is one ain't there) is that watching the video, everything was great until it came time to ACTUALLY make my "magic" code into a library. I think it would perhaps have been helpful to clarify that all you actually have to do is to move the .h and .cpp (.ino) file to the libraries folder under a folder name EXACTLY the same as the CPP (.ino) files. ??
That is after all, the crucial part of accessing any library, so users need to be clear how they need to "extract them" from their project and have access to the as a library ?
Hi Ian, good to hear from you! Now, in respect of making a library, remember that whilst the .h and .cpp files reside in the same folder as your sketch (as you develop them) all will work as you might expect (as long as you #include them using quotes, not angle brackets).
When you move the .h and .cpp out of that sketch folder into the libraries folder, in a folder name of your choosing (it doesn't have to be the same as your .cpp or .h file, although convention for smaller libraries does follow this) then you change the #include to use angle brackets (not quotes). The Arduino IDE will search for the actual .h file and find it wherever it is!
I'm not totally sure if that's what you mean above but that is the way it generally works, so I regret causing any confusion, doubt or uncertainty in my video, smack on my wrist and I promise to be clearer in the future, really. But I do appreciate your post because others might be wondering about this too, so I hope this clarifies things. If there is anything still left uncovered please do repost. At least you keep me on my toes, which is as it should be!
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.
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.
Very nice explanation, thanks!
Glad you liked it, thanks for posting.
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
Hi Ralph
Thanks for doing all these great videoes! They are simple to understand and easy to use. I have refered some of my students to use them - hope that's ok? 😊
Have you tried to hook more pcf8574 up with i/o's? How do you easily scan let's say 4 units?
BR
Tomas
Glad you like these videos, Thomas, and certainly direct your students to them. But if they fail whatever course it is that they are studying I take no responsibility! For the PCF8574 look at my video #49 MORE PINS PLEASE! PCF8574 Arduino Pin Extender (Easy), I'm spoiling you now!
You would't? ☺️ Of course it's their own responsibility. I teach electronics on technical college.
Yes, I have seen the #49 video. It's really easy to understand and use, but what I'm asking is, if you also have an easy way to handle inputs and outputs when daisy chaining more pcf8574's? I do have a way of doing so, but perhaps your way was easier?
Thanks for this , it has given me a chance to try and debunk some previous written software ( ble for arduinos) . A question , how do we best debunk what are the available commands ( methods ) within a defined class and their uses ?
Debugging code for an Arduino is somewhat crude. It involves using the Serial.print() method to write out to the Serial Monitor (aka debugging window) messages that might help you understand what is going on or wrong. And judicious use of the delay() statement to slow things down a bit so we can see what is happening in slow motion. Newer versions of some µControllers (including the MKR boards from Arduino) allow hardware debugging but that's for the future - for now you're stuck with Serial.print(), I'm afraid.
Thanks for this amazing video!!! your explanation is very easy to understand for me as a beginner!
But i have a question about what if you include a library that isn't within the same files, the memory will get lesser or still the same?
Although everything gets COMPILED when the LINKER decides what to include then anything not required is dropped so your output file remains small. Clever, yes?
best tutorial on libs. thanks.
Thanks for your post, iceberg789, good to hear from you.
Its been a long time since I checked in with you. It was sad to hear about Benny. I hope all is well with your eyes and that drama is over.
Great presentation as always.
What are your thoughts on copying the header and cpp files into tabs and then edit out any thing not used within the sketch. This would lighten the load on the Arduino while still taking advantage of the great libraries out there. of course, all due referencing to the original creator.
Nice to hear from you, Adrian, it's been a while. Also nice that you thought of Benny. Coincidentally it has been 8 months to the day since he was taken from us and it's still a raw wound. 😿
Regarding your thoughts on removing portions of libraries to "lighten the load" would only reduce the footprint. Additionally, the compiler/linker is quite smart and will remove functions that are not actually called. But it can make the library simpler and easier to follow. Give it a go with a simple one first!
@@RalphBacon Thanks. I am having fun with this and have so far made a simple library to blink 'SOS'. Bay steps forward but forward none the less. Cheers
This helped me a lot.
Great! Glad it helped!
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.
.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. 😂
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.
Hi Ralph. .cpp is the C++ file extension.
Yes, it is, Henri, I think a figured that out now!
great video, very informative. I wish I could give it two thumbs up.
the explanation in the arduino website was missing a few things...
TWO thumbs up? Wow! Actually, just the one is awesome as it tells Google that viewers are appreciating my videos. Thanks for posting golanramati11, great to hear from you.
if I can add something that you didnt cover in the video:
I wrote a library to create an instance of some object and another library that creates an object consisting of an array of the first object.
in the both original librarys I included standart librarys (looked like the right thing to do, thing like servo.h) but it wouldnt compile, the error said the first object does not name a type.
after a long time of asking aroung and pulling hairs, I removed the standard included librarys from the second library and included only the first library I wrote and theat seemed to solve the problem.
thought it could help somebody
Thanks for that, golanramati11, always good to share experiences like this to hope others. Nice to hear from you.
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.
Ralph, sorry this comments probably in the wrong place, could not find an e-mail for you, are you able to do a presentation on Json ?? I.E. what its useful for how to write it etc
Hmm. In these days of IoT I'm sure JSON is used more and more. I even use it in my Home Alone project sending data to and from _ThingSpeak_ . OK, I'll add it to the list!
Excellent video. Thank you!
You are most welcome Dan M, I'm glad you like the video. Nice to hear from you.