I'm writing this guide more for myself, to document and capture my own journey as of September 2022 and share it with y'all! Over the experience that I've been fortunate to grab during my time in University, all I've really learned is how big the field of embedded is. I once remember fearing that there was nothing there to embedded past writing device drivers for eons, but that could not be further from the truth - if there's one thing I've truly learned, it's that I have a lot left to learn about embedded software.
Where I'm at as I write this?
Currently on internship at Skydio (https://skydio.com) writing embedded software!
2B/3A limbo at UWaterloo Mechatronics
My resume at the time of writing:
Grade School
For the longest time, my parents always encouraged me to play with hobby electronics kits and fostered a love for robotics and code. I got my first Arduino kit around grade 6 and started infrequently coding on it. My parents also got me a nerdkit, which actually used the same family of chips (AVR) as an Arduino but without the Arduino framework. I managed to make a temperature sensor and LCD driver with the nerdkit by somehow mashing together a tutorial on their site which actually required me to script-kiddy my way into writing C and bash (and promptly forgot). That'll come back later.
At the time, I didn't realize that different languages were meant for different things and how they were used - to me, code was code. I had actually learned to code in Lua courtesy of Roblox as my very first language, and then C, followed by Javascript and Swift 3. In high school, I learned Java due to my FIRST robotics team, and somewhere along the way C++, though I can't remember how (I suspect Arduino's, though). Reflecting on this, my relatively varied experience of programming languages gave me a good foundation on code as a system rather than a specific language, something that would come in handy very shortly...
Medvita
It's March 13, 2020. COVID meant that high school was cancelled for the remainder of the year, and my friend had invited me to become part of a startup called Medvita, a telehealth company determined to make a wireless stethoscope. Though we were all university students, we somehow got an investment offer at the end of the summer. I took on the role of developing the software for the stethoscope module as we were using an AVR chip and had the most amount of experience developing for it, but promptly realized I forgot everything there was to C, bash, and everything else in between. Luckily, YouTube was here to the rescue.
It was at this moment I'd say my journey into embedded began, and in hindsight, AVR was an excellent teacher. Unlike many of the more modern microcontrollers I have since used, Atmel did not provide a code generator for their Atmega series of microcontrollers, which meant I had to do everything the old-style way, bit-banging my way through registers and protocols. As such, it forced me to become comfortable with reading datasheets (something I had rarely done before) and doing it all from scratch, rather than clicking on a few buttons to generate peripheral code. I learned about how ADCs work, how to implement polling device drivers, and got exposed to the UART protocol which made me very comfortable with bitwise manipulations. At the time, we were implementing the main logic on breadboards to eventually become PCBA's, which meant a lot of my previous prototyping experience started to come in handy when wiring up boards from schematics. I also got to touch an oscilloscope for the first time and had a lot of fun eating pizza with friends.
I still kept the code around as a testament to how far I've come regarding how I write code now: GitHub Repo.
First Year University
2 key design teams would come into play for skyrocketing my knowledge of embedded - the first was WARG, where I joined as a firmware team member and got exposed to 'industry-grade' firmware. I started to learn about STM32s, heard the word 'design patterns' for the first time, and learned a lot about peripherals and protocols. My first task on the team was designing a state machine for our attitude manager with a mentor who strongly encouraged me to use test-driven-development (TDD). A lot of the stuff I was being taught wouldn't make sense until later, though, when I had a more solid foundation.
The other design team was UWRT, where I joined the electrical team and learned schematic capture and PCBA design. While I eventually discovered later that hardcore EE is not what I enjoyed (I much prefer software to hardware), the knowledge I gained in being able to bring up boards from boxes to a turnkey solution with software has proved invaluable many times over. Embedded software is, in my opinion, all about software interacting with hardware - having the fundamentals of EE down in a practical and theoretical sense made me a much better programmer, as I now started to think at a systems level and could resolve differences about whether something should be in hardware, software, and create a product from scratch.
A key part of my tech stack is my Python knowledge - it has come up plenty of times and is quite useful as an embedded software developer as a lot of tooling is in Python. Ironically enough, I learned this by making a discord bot for my class that did verifications and other stuff.
By this point, my code style had improved a bit, and I had enough knowledge to attempt to make combined EE and FW projects. The first one I made (and also flopped) was my motor controller.
First Firmware Internship
Throughout my first internship, I got exposed to a lot of "real" code and received a lot of good mentorship about how to write good, safe embedded code. Among the things I picked up included the MISRA C ruleset, which continues to drive my coding patterns and how I think of firmware. I also got to work with FreeRTOS and LwIP for an internal IoT-type product, which gave me a deeper appreciation for interfacing with libraries and helped me understand what 'real-time' actually meant. Other things I picked up included a lot of knowledge surrounding DevOps, specifically build systems and CI/CD pipelines. My Linux skills also improved as I had a Linux laptop and was forced to learn the associated commands.
Second Year
By this point, I felt I had a lot of good fundamental embedded software knowledge, and started to go out and self-learn through other design projects. Among the projects I made included a soil moisture sensor and more importantly, a bootloader with application-update capability from a tutorial. Both of these allowed me to put to use a lot of my embedded knowledge and learn quite a bit about how these systems work. While I was also active with UWRT, I ended up leaving the team in October of 2021. I ended off by completing a Wifi-enabled drivetrain control system that the team used for ROS2 experimentation, which taught me more about why I shouldn't write control software in Python and why TCP/IP exists...
From here on out, my learning has been mainly self-taught and seeking opportunities to be exposed to new types of code, whether that be ROS, new microcontrollers/families (PIC, TI, NXP), and new languages (I learned typescript and rust along the way, none of which have come in useful yet, but each language has something cool). I like to keep a list of terms that I hear and see how I can work them into a project I'm using - an example is my robotic HID project, where I wanted to use USB 2.0 and design a bootloader + application. On my list of stuff to learn right now includes things like Ethernet, embedded Linux (getting to do a bit of this right now), ROS (again), and improving my knowledge of system architecture. I've recognized
Mentorship from co-op helped significantly in learning where I can look for the next big thing, as well as giving me a framework that forced me to learn certain skills that I simply wouldn't have known about otherwise.
My recommendations for getting into embedded software
Though I'm biased with the path I took, I feel like Arduino gave me a lot of really good practical EE knowledge that comes very handy when debugging (i.e. pullups/pulldowns, wiring diagrams, etc). I would recommend someone new to start out here and do a few projects with Arduino and master the basics of C++ and breadboarding. C is important, but I'm not sure of any good resources to learn it online. CodeCademy is how I generally pick up a new language, and C++ is on there now!
After getting comfy with those, I'd recommend swapping out the Arduino for an STM32 dev kit/Nucleo and using the STM32CubeMX software to autogenerate peripheral code. It's a bit of a step up, but tutorials and a semi-decent interface help make projects come to life. I'd recommend trying to do a project that was intended for Arduino but using an STM32 Nucleo as it will expose you to peripheral drivers, protocols, and having to understand the implications of setting parameters and learning how to debug without using print statements. Along the way, try playing around with making code unit-testable (lots of resources on embedded testing with STM32) and writing unit tests for your work.
Some tooling to play around with when debugging includes a logic analyzer and/or oscilloscope, as well as a variable power supply - these tools are quite helpful.
After STM32 nucleos, I'd recommend now to challenge yourself not to use the HAL, and instead use the datasheet in place of the HAL, and make abstractions.
コメント