Maybe you’ve decided to break away from the relative cosiness of the Arduino framework and decided to write your own driver for an lcd or maybe i2c. It should be simple right? These are common as.
So, armed with a sense of adventure, you write some code and it doesn’t work. Where to go to from here? Off to the forums we go. The usual response you get from the crusty old denizens (ie me) is “why don’t you just use some known good code?”. This is sensible advice - why re-invent the same wheel that has been solved centuries ago? Your response is “but I want to learn!”. If this is you, then here’s some tips at solving your problem and more importantly learning some useful techniques that you can carry forward. Otherwise, if you just want to get something working pronto, then stay with the Arduino framework - thousands have most likely used the same library/feature so there’s a good chance it works out of the box.
Ok, you’ve got to here, so I’ll assume you want some tips.
1. Firstly understand the challenge you face. You’re dealing with a little machine that does millions of operations per second. The smallest error can cause your creation to sit there doing nothing.
2. In your code, wiring etc, you've made a number of decisions. Some of these may be right or horribly wrong. Every line of code, every wire - count them. Let’s say there’s 100 of them - if you hazard a guess that 7% of them are wrong then you need to find 7 errors out of 100. How do we tip the odds in our favour to zero in on these defects?
3. Ask yourself “how many problems do I want to solve at once”? The answer should be one. Trying to solve more than one problem at a time is a recipe for failure. As a beginner with microcontrollers, these are very complex devices. You need a degree in electronic engineering to understand how to wire one of these things up. Sure you can do it by throwing some wires together, but expect to make mistakes. There’s plenty of tutorials out there, but many of these are done by people with similar experience to yourself - it ‘worked’ for them. The suggestion here is to start with known good hardware or software. Limit the potential for problems. Frequently on the forums we see dodgy hardware along with dodgy software - no wonder the problem is intractable. The advice is: start from a known point - you can get cheap Arduino boards for a couple of dollars. Apart from the dubious quality of the very cheap clones, this gives you a stable platform to work from. The Arduino boards are basically the bare minimum hardware you need to make the micro controller work reliably and to load code onto them.
4. Armed with a stable platform you can concentrate on the problem at hand. As well, you can use known setups to test your hardware configuration with (hopefully) known good examples. That’s the beauty of the Arduino ecosystem. Stack the odds in your favour - work from a known position.
5. Start small, work up. If you’re a raw beginner, the usual first project is to flash an led. The idea here, is if you can’t get the led to flash, then anything else more complex is less likely to work. As well, the led can serve as a powerful diagnostic tool for later.
6. Ok, back to the problem at hand - how do we identify the defects? Again, it’s all about stacking the odds in our favour - what works and what doesn’t work? You have 100 lines of code - one or more lines might have defects.
7. What can you test? The best tests are simple and conclusive. The micro controller is buzzing away at millions of operations per second running your code - the problem is we can’t see exactly what it is doing and where it goes wrong, so how do we narrow down the problem space? For many micro controller problems, the code is reading inputs and turning outputs on and off. Is your code writing to the correct pin? Test it. Make the led flash. This simple test will verify that you are talking to the correct hardware pins. Is the input working? Write some simple code to read the input and make the less turn on or off.
8. Work logically. Sounds easy, but remember to solve one problem at a time. Keep asking the question “does this work?” yes or no. How can you prove it? Don’t assume anything! So many times a potential problem gets overlooked because ‘it can’t be possibly wrong!” - unless you can say “I did this test and got this result” to prove an assumption. Most of the work in debugging is proving what isn’t wrong - eventually you end up with what is wrong.
9. Write your code so that it is easy to test - one function should do one thing properly. If all your code is in one lump that does ten things - how are you going to test it? Break it up into simple functions - test each function. You’ll be surprised how you’ll narrow down a problem quickly using this technique. Again, the mantra - “solve one problem at a time”.
10. In order to do a test, you need to observe a result. I’ve suggested one method using an led. It may be impractical to make an led flash as it may impact the operation of the code thus making any test invalid. Other techniques might be having a number of leds - each one gets lit on a specific condition. That way you can determine if a certain part of the code is operating and maybe if a specific value is reached or exceeded. Sort of like ‘breadcrumbs’.
11. Slowly but surely, using a simple and logical technique you will determine what works and what doesn’t. The conclusion is that you identify and eliminate the defect. At the very least, you will narrow down the possibilities and then you can use a forum to ask a very specific question and be able to provide evidence - this should make for a quick solution. Frequently on forums someone posts a page of code and says ‘it doesn’t work’. Sometimes the defect is obvious, other times the problem isn’t in the code or there could be multiple problems. It is going to take a while to sort through all the issues.
Debugging is a skill - there are basic techniques. Once you apply these techniques in a structured way, you can solve very complex problems. Debugging is harder than programming - don’t write code you can’t debug!
Experience helps, but experience is no substitute for good technique.