Well there may not be an algorithm but there are some ideas to keep in mind:
- perturb the system and see how it reacts, i.e. make one small change (see next principle) that should produce a different output and see if it does
- only change one parameter/setting/etc at a time and see if it makes a difference, be systematic and track all changes
- try doing the simplest thing and keep that as a baseline, e.g. if you are trying to get something to work that will have changing settings/configurations, get a basic working version with 1 set of values that you can always test with when the more complex version is not working as expected
- always double check connections and soldering
- try and examine your assumptions and see if they hold. I recently found a compiler limitation with global variable names. I found it by proving that the global name being set in the subroutine wasn't keeping it's value outside of the subroutine even though that should be impossible and no errors/warnings were thrown. I changed the name of the variable ( perturbed the system) to a unique name that was shorter and it suddenly worked.
- undo your last change if it broke something and check to be sure you are back to the working situation, keep unwinding until you find the fault
- always keep backup versions of your working software, preferably with source code control
-RTFM, yes, RTFM if you don't know what this means look it up
- google, google, google
- learn to read and understand assembly code, as one of the few people who can utilize assembly on the various development teams that I have been on I have an extra tool in my toolbox that other developers with high level language expertise only cannot effectively apply. Don't need it often, but when you need it your REALLY need it.
These are all principles that help me almost every day in figuring things out
I'm sure that others can chime in with some good ones as well.