Words of wisdom


  • Put a value on your time. I used to make my own circuit boards using the toner transfer method or pre-sensitised UV boards. Although the results were satisfactory even with 0.5mm pitch TQFP parts, making circuit boards is a tedious process. It also limits the design: you can't easily put vias under components with DIY PCBs. These days I just wait until I've got enough designs to make into a panel, and get them made in China. It's not as expensive as you might think, they do a good job, and the places I've dealt with have knowledgeable staff with good customer service. Professionally PCBs also are more reliable, are way easier to solder components to, and look much nicer.
  • Don't re-invent the wheel. Or if you have to, think hard about why you are doing so. Admittedly, I am guilty of re-inventing the wheel. Often, my reason is to save a few bucks (at the expense of my time), but I also do believe that every project that you go through makes you better. I also think it is good to have experience in both the low and high level stuff. If you are constantly creating sensors from components, you will probably end up doing so, rather than developing an awesome robot / whatever that uses sensors you could have bought off the shelf.
  • If you are a programmer, but have grown up using Windows, give Linux a try. Sure, it is a lot of work and difficult to get the hang of at first. But you'll find that gradually you'll get the hang of it and you'll become a more proficient programmer. Building and installing programs from source can be tricky and frustrating. One useful tool on Ubuntu to have is apt-file, and when the project you're building from source fails because a header is missing, simply look up and install a package that has that file in it. I have also become rather fond of doing things through the command line. You might not initially agree, but it is actually quicker to do things via a prompt or shell interface. I usually dual boot Windows with Ubuntu, and am now setting up my Windows system like my Ubuntu one, and prefer doing things in a prompt/shell rather than using a GUI. Saying you use Linux also increases your awesomeness and nerdiness a couple of fold, and the respect that your peers will have for you! 
  • MS Word and OpenOffice handle small documents well. However, I advise you not to ever write a thesis or any other large complex document in Word or OpenOffice. LaTeX is much more suited to this task. Although I wrote my Master's thesis in LaTeX, before this I used to write large documents in Word. A lot of energy was expended on formatting rather than the content, and entering maths equations via a GUI is painful. LaTeX is not for the faint hearted. Since it is a programming language, expect to have to put in bit of learning, but it is well worth the investment. Since LaTeX handles the formatting for you, creating sub-standard formatting is quite tricky, and in that case you might be best off with Word or OpenOffice.   
  • Failure is the mother of success! From the projects I have listed on this website you may deduce that things have always turned out well for me. I can assure you that this far from the case, and I have been through many failed projects. Maybe I'll write up a section about such projects, what I learnt from them, and what I now look for to avoid failing in a similar situation...
  • Many of us are perfectionists. For those others like me, you'll agree that this trait is both a blessing and a curse. To avoid the 'while(!perfect) {do work; }' loop that I often get into, I try to also add in another factor. This factor is to estimate the cost of opportunity lost when I spend more time on a certain task. That is, there is always a limit where improving something beyond what is absolutely necessary is wasteful. Well, at least I try to remember this. As I become increasingly lazier and more impatient, I think this helps to get me out of this state. While I enjoy dabbling in projects, from now on I'll probably choose my projects more carefully and engage in ones with high output/gain/benefit-to-effort ratios. 

Circuit board development

  • Always put in debug LEDs, even if you are confident with your design. You don't have to populate them, however, it is much easier to do so if there is already space on the board. As an added bonus, blinking LEDs often impress the layperson, despite being a trivial component of your design. Test pads are also useful.
  • There should be at least one decoupling capacitor per VCC pin for each IC. Put them as close as possible to the power pin. If they are too far away, they do not provide docoupling and may have been left off the board.
  • Ensure you have a quality, unbroken ground plane. When laying out my PCBs, I often route all non-power tracks first (but while envisaging space for them). Finally, the power planes are added by using a polygon pour. Making an unbroken ground plane can be tricky on a two layer board, but it often can be done by making tracks as short as possible on the ground plane side (at the the expense of having more vias).
  • There are several ways to make laying out a design easier. One approach that I have found to be very effective, particularly with circuits with programmable logic (e.g., microcontrollers), is to swap pins. Firstly, lay out most of the non-swappable pin traces (the ones that require a specific pin, e.g., hardware PWM, input capture, external interrupt, ...). Then, adjust the GPIO pin allocation to minimise potential track cross-overs.
  • Cleverly use and allocate the peripherals of a microcontroller. Sure, you can bit-bash a PWM signal easy enough, but implementing an I2C slave interface in software is probably harder than using the device's I2C hardware module. If you have problems with getting a peripheral to run, then you can resort to a software-based approach.
  • Have separate ground planes for analog, digital, and power. If you have motor drivers on the same PCB as a microcontroller or a sensor(s), noise will be injected into the digital and analog ground. To mitigate this, connect these planes through a few points. I often use a small zero ohm resistor for this.
  • Think about the return current path. Current carrying traces should be thicker, and ideally as short as possible (i.e., have the battery connector, motor driver, and output terminals close to close to each other). Also pay attention to current carrying traces that go through vias. Are the vias adequately sized? Improve the current capacity of small vias by adding a bunch more of them.
  • Tented and small vias make a PCB look much nicer. So do tracks that are layed out nicely, with 45 degree bends. Accute angled tracks look ugly but are also are less mechanically robust.
  • If two adacent pins on an IC are to be bridged, connect them by a trace that goes out of the pin, turns around, then comes back into the other pin. If you connect them with the shortest possible track, during assembly it is possible for solder to flow right up to the IC's pins. This can create can confusion, particularly for someone else who assembles your design, as the pins may look like they have been bridged accidently.

Embedded systems

  • Without a doubt, today's 32-bit microcontrollers are very powerful. Often, they are under-utilized in an application. This is fine if you plan to expand your system, but consider whether a simplier 8-bit microcontroller could also provide enough head room. It may come as no surprise that 32-bit microcontrollers are also a lot harder to develop with. For instance, putting an ATmega into hibernation is quite easy, while doing the same task on an ARM takes a lot more effort. Grunter microcontrollers tend to have more complicated and difficult to use libraries. I use a variety of micrcontrollers, but the ones I use the most are ATmegas, PIC32s, and STM32s. A easy to use library for ATmegas is Pascal Stang's AVRLib. The Microchip libraries for the PIC32 are reasonably straight forward to use, while the STM32 has numerious top quality libraries for it as a result of open source projects (i.e., OpenPilot). 
  • Choose a microcontroller that is widely used by others and has active support forums. Also look at the existing libraries people have developed for a particular microcontroller. Some microcontrollers lack decent libraries, quality toolchains and/or IDEs.
  • I advise having a dedicated UART port that is reserved for printing debug messages. Flashing LEDs can only convey so much information. Although there are often not enough UART ports on a microcontroller, it is annoying having to constantly enable and disable debug messages when the port is shared with another device. On my more complicated designs I've started to make a USB endpoint as a VCP that is used for debug messages only.  
  • Debugging drivers is hard work without a debugger. If your design involves a lot of work on making drivers, take the time to familiarise yourself with the process of stepping through code with a debugger.
  • Buy an oscilloscope! For me, an oscilloscope is like the hammer in a carpenter's toolbox. It's that simple. Really good stand alone units can cost upwards of $5K, but you can get some pretty decent USB-based CRO's brand new off ebay that do a great job (I have a DSO-2250, which is 100MSps, two channels, external triggerable, and bought for a mere $250 a while ago).


  • Do as much software development natively on the computer as possible. It is a lot faster and easier to develop algorithms on a PC, than cross-compiling, flashing, then testing on an embedded system.
  • Testing many robotic related applications in real time is over-rated. A lot of time is often wasted on conducting the tests, and contending with issues with hardware. You can rapidly speed up development by replaying back logged data through your system, and solving problems as they arise with offline data.
  • Depending on the complexity of your application, it may be worth while sussing out a simulation environment. In the case of my Masters project, the time to test the navigation system would have been magnitudes more had I not had a robotics simulator.
  • Modularise your code! And don't stick it all in the 'main' function. It is also useful to stick to programming conventions for a particular language. In C, for instance, it is a good idea to put preprocessor definitions as full capitals. I also like prefixing the public functions of a module with the name of the file it resides in. 
  • Use an appropriate language for a particular programming language. Chances are you are limited to C for microcontroller applications, but it would be silly to use C for front-end PC applications that have a GUI (as Python is much better suited to those sorts of tasks). Matlab is also much better suited to number crunching applications, and when using it, make sure to vectorize your operations.
  • Software developers are always making tradeoffs. Do we implement a routine in a simple and clean manner so that later down the track it is maintainable by someone else? Or do we optimize it to squeeze out every bit of performance we can get. Obviously you'll choose an approach that is most suitable for a particular task within a program. Still, with the availability of cheap hardware, it may be worth to choose to develop clean and maintainable code that runs fine on a more powerful system. However, there are always exceptions. Consider developing a RSA encryption implementation, which involves creating very large prime numbers. It would be silly to find these primes using the method you probably learnt about in primary school. Instead you would use a random number generator to create a proposal, and use Euler's criterion N times to probabilistically classify it as a prime or non-prime. This scheme, although significantly more complex, is astronomically more efficient, and would otherwise require out of this world computing power to run a simple and naive prime number generator to match it (and thus it would be best to develop a simple interface to the complex algorithm).
  • Use version control on your code. I use are SVN and Git.  

Share |