I graduated in January 2014 – one of the coldest winter months in Denmark. At the time of writing this article, that was a little over 6 years ago. I graduated with good grades, and was somewhat confident that I was ready for whatever the world had to offer. Or so I thought.
I was 26 at the time, and even though I had graduated with a B.Eng. in Electrical & Electronics Engineering, I wasn’t quite sure what I wanted to do. With a degree like that, there were literally a million things I could do. But what? I had no idea. What I knew for sure was this – I loved to code. For my bachelor project/thesis, I developed an Arduino-based semi-automatic guitar tuner together with 2 other classmates. I wrote the entire code for that project.
Now and then, I occasionally read my thesis code, and can’t help but laugh my ass off and even face-palm myself. If I were to grade the code now (if someone else had written it), I would give it a big fat F!! In hindsight, It was crap. Mind you, it worked (mostly), but it was crap – if I’m being completely honest with myself.
A few weeks after I graduated, I mustered all the courage I had and spent the next 4 months sending out job applications. I was one of the very lucky ones – graduated in January, and landed my first job in July that year.
I remember feeling excited and overwhelmed on my first day. I freaked out when I saw the code – it was a lot of code. I had never seen so much code in one place. It was truly overwhelming, I tell you. I was assigned a mentor to show me the ropes, and I’ll say this – it was one of the best things that happened in my career. I had someone to show me the right and wrong way of doing things, especially coding.
My mentor’s name was Kent, and he was one of the seasoned developers at the company. He was very particular about doing things the right way. I remember how he would scrutinize every single line of code I wrote, and how I would get mildly annoyed whenever he pointed out something that I considered trivial.
I came to understand and appreciate Kent’s mindset after I left the company almost 4 years later. Thinking back and reflecting on all I’ve experienced, I admire and appreciate Kent more than ever. Looking back, I realized he was an amazing mentor.
The biggest lessons I learned from Kent (and I hope you learn it too):
- Always code to handle the worst case scenarios. Anyone can write “sunny day” code. Being able to write code to handle failures is the mark of a mature engineer.
- Always be critical of your own code. As you code, ask yourself continuously “is there a flaw in this logic“? Make it a habit to always, as much as possible, assess the flaws in your logic. It’s a habit that will potentially save you hours of debugging.
- Be open to criticism – others will always review your code and you should expect both positive and negative comments.
- Always have the mindset to do things the right way. This is probably the most important! It’s easy to hide behind the excuse of “I am under pressure”, or “it’s fine as long as it works”. In my experience, hacking your way out of problems will come back to haunt you – 99.9% of the time. It’s fine if you’re making a hobby project, but in a professional environment – avoid hacks at all cost! Even if you are faced with an impossible situation and are forced to make a hack solution, please make a mental (or actual) note to come back to that hack and do it properly when you have time. You’ll be a better engineer for it.
- Test, test. and test!!! You can never test enough. My advice – setup testing from day one in your project. The longer you delay setting up tests, the more difficult it becomes to integrate, and you’re less inclined to do it.
- Never make assumptions! You’re just shooting yourself in the foot if you do so. It is critical that you are honest about your work, skills, strengths, weaknesses and expectations. It’s okay to say “no”, “I don’t know” or “I’m not sure, I’ll look into it”.
- Take responsibility, and never make excuses! My absolute personal favorite excuse: “it worked yesterday”. Don’t ever say that! It’s just downright embarrassing! (I should know – I’ve given the same excuse a few times in my early days). Live and learn, eh?
These lessons built my mindset and helped me become a better engineer. Now, what about technical skills? As an embedded software engineer, you are expected to have quite an array of skills at your disposal. My advice to all young embedded software engineers out there – find a good mentor, and at the very minimum, learn how to:
- Write decent code in C (C++ too, but I’d personally advise you to concentrate on C). C++ and even Python are slowly but gradually emerging in the embedded world. Keep an eye on those two languages. Learn the tricks of the language. This will help you write robust, maintainable code. Understand how to use pointers. They are powerful but can spell disaster if not used properly! Pointers! Pointers! Pointers!
- Have a decent understanding of software design patterns – you need to learn to use the right design pattern for specific projects.
- Use at least one embedded OS – I’d recommend FreeRTOS to begin with. Learn to understand when to write bare-metal code or multi-threaded code.
- Use an oscilloscope/logic analyzer – this is vital in seeing signals in real time and debugging your code WHEN things go wrong. Always expect things to go wrong.
- Understand the hardware. It is essential that you understand microcontroller architectures and communication protocols/interfaces (UART, SPI, I2C, bit-banging), and other vital microcontroller components like ADC, PWM, Timers, Watchdog Timers, etc. Learn these protocols and components! Try playing with microcontrollers from different vendors – Nordic, ST, Renesas, Texas Instruments, Microchip, Atmel, etc. These are some of the most popular vendors in the industry. Learn their products and hardware architectures.
- Use SDKs: Virtually every microcontroller vendor has created SDKs to accelerate development. These SDKs are essentially abstraction layers that shield you from all the nasty low level details, and let you focus on the higher level details of your application. For any SDK you choose to use, make sure you understand how it’s organized and learn to use it properly.
- Read and understand a datasheet. Datasheets can range from anywhere between a few pages to thousands of pages. It is important that you develop the skill of reading datasheets, and knowing how to extract necessary information.
- Write test code, especially in Python. Most SDK vendors create APIs that allow you to communicate with your microcontroller via DLLs, which are wrapped in python packages/libraries. Learn to use python to test your code. More importantly, develop a tester’s mindset.
- Use software version control tools (Git is probably the defacto standard for version control these days). Learn to use Git.
- Document code. Make it a habit to document your code as you go along. Your code is essentially a reflection of your mind and thought processes. The best way for others to understand your mind (at least in this case) is to document your code. The longer you postpone documentation, the more annoying it gets. It’s a tedious chore, trust me, but a very, very necessary one. Learn to use Doxygen!
- Automate repeated tasks. Develop the habit of automating repeated tasks. For example bash/bat scripts to build your code, run tests, etc.
Several years into my career, I’ll say this: I’ve learned a lot, and I’m certainly looking forward to learning so much more. I can also honestly say that embedded software development is not for the faint of heart. You will spend the rest of your career making mistakes, learning new ways of doing things (and maybe losing a little bit of your hair). Learn to love the process – that’s the best part for me.
Recent Comments