So you want to write a library to go with some nice fancy piece of hardware you've created. Excellent.
Before you do, please try not to embarrass yourself.
I have seen many libraries that have been written by Arduino users, and I am not going to point any fingers or name any names, but there have been some shocking pieces of code written.
So, before you start writing your library, please check through this list of dos and don'ts so you can make a library that won't make you look a fool.
Don't:
Don't put all your code in one header file. C code goes in .cpp files, and header information goes in .h files. I have seen a number of libraries which consist of one single .h file which is packed with C code. This is very very bad practice. If your sketch involves more than one file, and you include this header file in each file of your sketch, you will be duplicating the code within that header file. This will not only waste space, but will duplicate any objects and variables defined by the code. The only time it is acceptable to have code in a .h file is when defining a macro. Header files should only contain references to external entities (variables and function defined in C files), class definitions (not their function code - just the definitions) and macro definitions.
Do:
Do include or inherit from other people's libraries. There is no point in inventing the wheel. If your library does the same job as someone else's but with a few differences, just inherit their class and overload the relevant functions. This can be done with system objects, like the Serial object, or the SPI object, for instance. Also, if you are using facilities in your library that are provided by another library, don't duplicate what that library does. Just include that library in your code. A good example is the SPI library. I have often seen libraries which duplicate a lot of the code that the SPI library provides, just because the device the library supports is an SPI based device. This makes libraries very non-portable. There are a wealth of devices around now which use the Arduino (wiring) environment, and they aren't all AVR based. Porting libraries to these platforms is far easier if they don't use any processor specific facilities. Porting the "core" libraries should be enough to then allow other libraries to operate with no changes.
Don't:
Don't re-invent the wheel. If there is an existing library which does a similar job to yours, but with, for example, different hardware, try and match the interface of that library. It makes it far easier for other users to adopt your library if it is basically a drop-in replacement for another library. If you know the interface (function calls, class methods, etc) to one, you know the interface to the other. There is very little more to learn.
Do:
Document your library. In the header file document what each function does, what it expects to be provided with, and what it should return. Also document all the #define macros and how they affect the program, and what effect changing them will have. If your library requires the user to include other libraries in their code (like the SPI library) then make this obvious right at the top of the header file. Also, if possible, write a manual to go with it detailing all the functions and methods and what they all do. Provide some example code to show how to use the different functions.
Don't:
Don't be messy. Code indenting exists for a reason. Make sure that your code is easy for others to read and follow. Don't be afraid of using long variable names that show exactly what they are. Function names should be descriptive and easy to remember.
Do:
Overload system functions. If your library provides some functions that do a similar job to a built-in function, such as analogRead(), or digitalWrite(), overload the system functions but using your own structures as parameters to keep them unique. This way people can continue to use the existing functions they already know. You can #define some symbols to equate to your own structure based variables so they don't have to know about that - something like:
struct myAnalogDevicePin {
int number
};
#define EXT_A0 (struct myAnalogDevicePin){0}
unsigned int analogRead(struct myAnalogDevicePin pin)
{
return myClass.readAnalogValue(pin.number);
}
// ...
myReading = analogRead(EXT_A0);
Don't:
Don't be afraid to suggest other best practices, or lambast the ones I have listed here. These are really my own personal opinion, but one built up from many years of programming - both as a hobby and as a job.