Beginners love Arduino coding because there is so much of it available to just copy, load and go without too much thinking required.
Then they find that one thing they want to do is in one sketch and another in a second sketch. All they need to do is combine these sketches! This can be a big hurdle the first time it happens and many fail to get a satisfactorily working product.
There is a systematic approach to this that helps to ensure that things work.
Step 1 – Understand the sketches
An obvious point is to make sure that the individual sketches do what you expect them to do. This gives you a solid foundation for any debugging you need to do later, as the cause is likely to be within the changes you made rather than the original code.
It is also really useful to keep in mind what you want to combined code to do. This will help you start to think about the changes needed as you inspect the code.
In this step, the most important thing is to review the code to understand the flow and structure of the separate sketches, as this knowledge is needed in each of the next steps.
As you read the code, note what resources (pins and other hardware) the code needs. Making a list for each sketch is useful, and don’t forget to check out any non-standard libraries included in the sketch.
Step 2 – Clean up the sketches
Once you understand the code’s what and how, it is time to ‘clean up’ the code. How much of this needs to be done depends on how well the code is written in the first place.
Eliminate any ‘magic’ numbers that appear in the code (a common one is pin numbers repeated all over the place). All of these numbers should be made into constants or #defines so that they can be changed or reassigned from one place. This step is best done before the merge process to avoid confusion with duplicate values that are functionally different.
Rationalise the hardware requirements between the two sketches. This applies to I/O pins, internal timers, interrupts, etc., used by the code and any non-standard libraries. In this step you should ensure that any necessary changes preserve any special capabilities (for example, PWM pins).
Resolve duplicate function and global variable names. This can be done before or after combining the code, but I find it easier to make and test these changes before combining to make sure the ‘right’ duplicate function is called.
It is useful to test each sketch after this step to make sure it still works as expected.
Step 3 – Make the sketches non-blocking
In order for the combined sketches to work well together, each sketch should be non-blocking. Additionally, each pass through the loop() function should take a short amount of time.
Long delay() statements are a sure sign that the code needs to be modified, but also look out for other potential ‘busy’ loops waiting for events to happen. The techniques for making code non-blocking are covered in my previous articles about Finite State Machine Programming Basics (part 1 here and part 2 here).
If the sketch has complex code in loop(), move that to a separate function and call that new function from loop(). This will make merging the loop() code much easier in the next step.
Once again, test the standalone sketch after this step to make sure it still works as expected.
Step 3 – Merge the code into one file
The final, and by now the easiest, step is to merge the code into one sketch. This is largely a mechanical process that consists of the following basic steps:
- Ensure all the required header files are included in the combined file.
- Move all the global variables and #defines to the beginning of the file, under the #includes.
- Move all the separate functions into file.
- Combine the code in setup() and loop().
At this stage you should be able to test that the combined code base performs the independent functions if all the included sketches. Once this is established you have a really good basis from which to start modifying and adding the functionality to make the code do exactly what you want.
All this may seem to be a lot for just combining some code. However, as you gain proficiency in reading and editing other people’s code, some of the steps above will become automatic and you will start to build the final code by cherry-picking parts and combining components along the way.
In the meantime, following a process will help you build up your skills and experience with less frustration and more consistent results.