Winter 2024 Course Review: EECS 373


Course Title: Introduction to Embedded System Design

Rating: 3.5/5

Instructors (Robert Dick & Matthew Smith)

Robert Dick is ridiculously tall and uses a Panasonic Toughbook running openSUSE. He's the lecturer of this course.


  • FOSS advocate
  • Is happy to discuss "what if" scenarios
  • Shares stories of real startups (including his own)


  • Too much of "here's the thing, learn it" versus "so here's how they came up with the thing"
  • Sometimes too eager to share the insides of a thing (it's useful though)

Matthew Smith is our lab instructor who oversees all lab equipment and material purchases. He's a really nice guy, but I sometimes worry about his health.


  • Is willing to talk about any idea
  • Knows everything in the lab


  • He'll talk with a student for a long time, which may be good or bad depending on you happen to be that student or waiting behind them

Course topics

The course covered a pool of loosely-related topics, all relevant to embedded systems but divergent. I categorized them:

  • Microcontroller low-level
    • ARMv7-M Thumb ISA
    • ABI (registers, stacks and stuff)
    • Interrupts (with preemption)
    • Timers (hardware and virtual)
    • PWM with timers
    • MMIO (including GPIO)
  • Buses
    • APB (advanced peripheral bus, an ARM feature)
    • UART
    • I²C
    • SPI
  • Analog
    • ADC
    • DAC
    • RC filters
    • Op-amps
  • Things you can put a circuit on and how to put a circuit on them
    • Breadboard
    • Protoboard
    • PCB (intro)
    • Soldering and desoldering
  • Other peripherals
    • Memory (EEPROM, flash etc)
    • Motors and other things that move
    • Shaft encoders
    • Antennas (and wireless communication)
  • Power
    • Integrity
    • Battery life estimate
    • Just Add Another Capacitor™
    • AC-AC transformers
    • AC-DC rectifiers
    • DC-DC converters
  • Meta
    • How to pick a project to e.g. start a company for
    • How to debug a complex system (spoiler: you take it apart)

Of these, the topic I learned the most from is interrupts. I had used interrupts in my previous Byseekel project, to wake up the AVR MCU from sleep mode. But now I know what actually happens is the MCU switches to interrupt mode and switches back to normal mode once the interrupt handler is done running.

The most boring topic, on the other hand, is APB. It just floated into the slides for no reason. I've never heard of it, and it doesn't seem all that essential other than to illustrate a point that you can interface with an FPGA or something that speaks the same protocol if you want.

The reason why the range of topics is so wide is because we had wildly different projects. But first let's talk about labs.


We have seven labs, covering different topics. All of them were done on a Nucleo board, and some of them required a Tang Nano, which is a cute Arduino Nano-esque FPGA.

The worst part about labs is how long the documents were. The longest one was 41 pages. It's full of images, yes, but it's hard not to be intimidated. In hindsight, though, it wasn't the worst lab imaginable, so I must have overthought.

Labs were done in groups of two. I often came to the lab (which is open 24/7) before our session to work ahead, so we don't run out of time. Once I discovered that I accidentally did most of the lab all on my own. So for the sake of fairness, but in a questionable and kinda condescending manner, I told my lab partner on the lab that I did most of the work but I'm gonna let him do it again anyway. So I let him take the keyboard and watched him do the lab, providing help every other minute. I still have no idea if I did the right thing.


In the final month of the semester, lectures and labs were over, and the focus shifted to the project. We didn't even have a final exam, only two midterms.

At the beginning I was looking forward to the project — it was the first time I had the chance to make something tangible at UMich. And at the end, though everyone suffered, many teams made something that's at least fun. Not us. Not us in the least bit.

If you are reading this article for academic guidance, please keep in mind that this is personal opinion and personal experience. It is 100% honest but does NOT represent the project outcome. My experience is more than one sigma lower than average. If you weren't an egoistic idiot like me, you'll do better.

Or just skip to Verdict.

I hate this project so much. If you are my teammate and you're reading this, please don't take this personally. I redacted your names (and mine as well). It's about this course and this course only.

This part has no constructive purpose. It's a long story and it's painful even to write about it, but I'm glad it's over. Let me start from the beginning.

I made the right decision to keep a project log. It grew to be 15 pages long. It's extremely helpful when I'm trying to get my shit together in this blogpost.


Last semester, three friends of mine were thinking about enrolling in 373 and asked if I wanted to be their teammate. I said sure. Later, two of them dropped, so the one left asked me if we should find our own teams, or invite two more. I chose the latter. It cannot be said whether the alternative would have been the better choice, but it might.

So one day after lecture, we sat down at a table in Pierpont to discuss our team project idea. Everyone brought along three proposals, as required by Robert. This brings a total of 12 proposals. Mine were:

  • "Blinkensleeves": MkIII of the bicycle blinker project, but instead of having a switch, the cyclist can blink the LEDs simply by lifting their arm. The LEDs are worn on, you guessed it, their sleeves.
  • "Optophone": An optical turntable where you encode MIDI in a circular barcode-ish pattern, print on paper, and spin under a light sensor to play it back
  • "Bookmargotchi": A bookmark with a Tamagotchi-like character that you must feed every day by reading the book for an amount of time

(Short note: before I discussed them with my team I talked with Matt Smith about my ideas. He was oh so patient.)

Other proposals included

  • Kibble dispenser for stray cats (we have no stray cats here)
  • Automatic garbage can (that ties up a full bag and open a new one. I need it)
  • Thing that warns you when a pot is boiling to the brim (helpful but we can't actually boil things in the lab)
  • Shoe dryer (extremely useful in snowy Michigan weather but seems infeasible)

I felt "smart" and suggested that we settle this with a vote, where everyone gives each proposal a rating from 1 to 5, indicating how much they want to do it, not how feasible it seems. Then we sum up the ratings for every project.

And my bicycle blinker project won. Later I recounted the votes with a quota on how many total votes everyone has, but my project was still in the lead. And I could see that my teammates trusted me, because I showed them my previous iteration. We thought it was a safe bet.

Brief tangent: other people's ideas & fedi interview

Because everyone dropped their files to a single google drive folder, everyone can see everyone's ideas. When I read some of them I thought, huh, it's already invented, why you gonna reinvent it?

Things someone wanted to reinvent:

  • Panic button
  • Tuner
  • Automatic door
  • Guitar pedal

Some proposed projects just because they could. They did admit the market for the product is next to none. My turntable proposal is one of them.

Robert Dick made a great deal out of market research and how to run a successful startup. He said it was helpful to interview strangers, so I did on fedi, targeting specifically the cyclists (fedi is never short of cyclists). I asked:

cyclists of the fediverse: is there any kind of device that does not yet exist, but you wish existed, that would improve your cycling experience/safety?

would be cool if a team of undergrads could make it in two months for an embedded system course (we're brainstorming)

boosts welcome

#cycling #embedded #electronics

Part of the fedi crowd brought up a variant of the blinker idea without me even mentioning, so it's definitely one of the more common things a cyclist could ask for. Others proposed:

  • Car-detecting radar
  • Accelerometer-based brake light

So I thought it would be a good idea to combine these three ideas and not add more to avoid making a overcomplex device nobody asked for that might not even work.

It turns out Robert's advice was for people who actually wanted to make money, not those who are just doing a course project. The market research is actually of no importance in the grading.

There's also project proposals that address real unsolved problems, but there's a reason they were unsolved.

Some projects are both novel and useful, but they don't have to be embedded. It could run as a regular computer application.

Now that the course's ended, I found that it's ok to reinvent something for a course project. There is a very narrow window of ideas that are both novel and useful. So it's ok to be only one of them.

My failure begins here.

Stupid thing #1: unrealistic idealism and wanting my project to be both novel and useful

So what were we actually gonna build?

In our project proposal, we wrote (excerpt):

Customer: Cyclists who wish to improve safety with little extra effort.

Value: Cycling is a significant source of accidents in the US [1]. Our product increases visibility of the cyclist with LEDs, detects passing vehicles from behind, and alerts both the cyclist and driver.

The cyclist can control the LEDs either by raising their arm or by activating a switch near the handlebars. The LEDs can be mounted under the bicycle saddle, on the front tube, or fastened to cycling apparel. They can light up in different patterns (e.g. blink left, blink right, brake, flash, etc) to alert vehicles […]

Our product can also detect vehicles approaching the cyclist from behind. When the cyclist is at risk, it flashes LEDs as a warning to the vehicle and activates the buzzer to alert the cyclist.

Similar products exist on the market [2]. Ours is more modular. For example, the cyclist may choose to remove the arm position sensors, relying on switch control entirely.

Approach: Our product is modular. The user can hot-plug different modules to a hub. There are two hubs in a typical installation: front and back. The front hub is to be installed on the handlebar, and the back hub may be mounted on the bicycle facing backward, or clipped to the cyclist’s back. Each hub has a Bluetooth Low Energy-capable MCU, likely an ESP32. The hubs communicate with each other to ensure consistent output.

Each module below can be hot-plugged to the front hub, back hub, or both:

  • Switch module: front.
  • Accelerometer module: back. Is a pair of accelerometers physically attached to cyclist’s sleeves.
  • Radar module: back. Consists of doppler radar sensor and buzzer.
  • LED module: both. Consists of a light sensor and LEDs. Form factors of LEDs may vary but pinouts are compatible.


Do you see the problem? I was way too idealistic. I falsely assumed I had the ability to build something out of a startup. Not with $200 budget. Not with two more EECS courses I was taking this semester. I went too far into thinking about so-called "user experience" up front, without the fundamental safety check that the basic functionalities work. I was so keen on the idea of building something that's not like other groups: robots, screens, cliché smart-X, just smack a couple Adafruit breakouts together on a breadboard like a high school STEM 101. I wanted to make something that, at the demo day, stood out among the others for its incredible simplicity, beauty and reliability. I wanted to make something that doesn't look like a 373 project. Something that I would use. That people would use. Of course that didn't happen.

The primary mistake of our team is that we did not form a feedback loop. Throughout the project, it seemed like I was the one dumping all the ideas into a pool, and failed to ask for enough input to mold them into unambiguous targets we could set milestones for. It's like saying "hey let's cook something" but not specifying what we even want to eat. So we had different ideas of what the project is about.

I named my proposal "Blinkensleeves" because I had envisioned LED strips taped to jacket sleeves; it did not happen. Instead we just slapped them on a boring box. I forgot when we abandoned the sleeve idea, but it was not my decision, but my compromise. (Our project would have sucked anyway. Also, we named our project "BicycLED" instead)

I did ask for their opinions; but since it was the early stage of the course, we could not tell what is good enough for the course. Picture this: You tell your teammates you once built X, and you are gonna build X II. You have an idea that you're 50% sure will work. You ask your teammates for ideas or alternative. The room falls silent. What happened? Is it:

  • They agree with you?
  • They can't come up with anything else?
  • They don't understand what you said?
  • They are insecure and internally rejected their potentially better ideas?
  • They think you're a fucking idiot and are just being polite?

I was too good at persuading people that my ideas work. Of course, I presented them because I thought they do work. Somehow I have deterred the rest of my team from contributing.

Stupid thing #2: Not being specific enough about project goals.

The root cause is that the project was too personal. Having had the idea since 2021, I couldn't tolerate a product that deviates from my idealistic model. This more or less alienated my teammates, and pressured us all in the end.

Despite a "complexity point" requirement in the rubric, I refused to add unnecessary features such as a screen. My argumet was that screens on a "safety" device is counter-effective. Sure, that may be the case, but you're designing a course project. Not a fucking body cares, idiot! Just add a 1604 LCD and you could stop worrying about those stupid points in the final weeks!

Stupid thing #3: Rejecting a screen.

We did not use ESP32s

You may have noticed that we mentioned ESP32s in our initial proposal, but we did not end up using any. Initially I considered the ESP32 because it had integrated Bluetooth Low Energy (BLE). But two reasons stopped me:

  • The BLE protocol is horribly complex and I didn't understand any of the boilerplate code
  • It seemed we had to use the Nucleo board because that's what the course was about

So I admitted my first defeat and went for the Nucleo. Wireless was done over the XBee module, which is a breakout board you talk to via UART and it would transmit/receive your payload over 802.15.4. It's just like connecting the two MCUs with UART wires. I love it. And it turned out to be the part that I worried about the least in the later part.

However I had a brainfart when I first configured them. I had to use a program that the XBee company made to flash the firmware, and I needed to give each XBee the serial number (like a MAC address but not quite) of its peer, but the program only allowed me to touch one XBee at a time. So I just typed the serial numbers in a text file. But I made a typo, and confused 0xc4db with 0xc4bd. This led to probably an hour of wasted time (which will turn out to be not the worst).

Using a Nucleo is the best decision. I have no idea what demon would unfold if I insisted on the ESP32. I could possibly be the one doing all the work, because to my knowledge, my teammates had no prior experience with MCUs, so it'd be unrealistic for them to learn yet another tech stack (ESP-IDF). And I've never used it either.

Buying stuff (and getting stuff from the lab)

Now that I'm about to bring up technical names, it may be helpful to present an annotated photo of our final product, just so that you know what I'm talking about.

Assembled PCB with an XBee, Nucleo, radar, LDR, expander, NFETs, and

▲ Back hub

Similar PCB with no radar but an extra buzzer screwed on the

▲ Front hub

(Oh, the PCB, you ask? I designed it. It's the direct source of agony later on.)

We had a budget of $50 per person (or $200 for our team of 4). Earlier Matt had suggested buying a Doppler radar to realize the vehicle detection, partly because he never used one and wanted to see how it was.

Doppler radars (the red spoon-shaped board) are microwave devices, which means two things:

  • They are more penetrative than light and propagates through thin non-conductive planes like plastic, which makes it possible to keep it inside the enclosure for better water-proofing
  • They're black magic

We asked Matt to buy one on Mouser for maybe $30 or 40.

We got (I got) these tiny Nucleo devkits (L432KC) from the lab. I asked for two but neither of the first batch worked. So I asked for two more. Matt just gave me two brand new boards. Thanks Matt!

We got (I got) the XBees from the lab. Instead of 2.54mm pitch headers they got 2mm ones (I don't understand why), so we got (I got) two adaptor boards so we could tack them in the breadboard.

Later we ordered the buzzer because I was dissatisfied about how quiet (and how useless as a horn) the 3V piezo buzzer was. This one? It'll blow your ears off!

Early optimism & state synchronization over XBees

I was like "yea im gonna absolutely nail this shit" and did extensive research. The idea was to have two "hubs" with an MCU in each. Then, you would wire up your LEDs to them. The two hubs communicate wirelessly.

How the hubs communicate to synchronize their states took a bit of thinking. I personally think it's the most demanding part of the project software-wise.

The essential idea is that each of the two hubs (or MCUs to be precise) maintain two states: its own, and its peer's. An input change (e.g. user lifted arm) directly changes its own state, not the output. The output is determined by both its own state and the peer state. Synchronization happens whenever a hub changes its own state, and involves an exchange of state over the air.

Imagine two hubs: A and B. All blinkers are off, until user signals left on Hub A. Hub A transmits Message 1: ack=0, peripheral=blink, state=left. (actually this is encoded in a single byte as a bitfield)

Hub B receives Message 1 and takes note that the left blinker of Hub A is on. Then it transmits Message 2: ack=1, peripheral=blink, state=off, which is Hub B's own state. The ack stands for acknowledgement; it means no reply is necessary. Before I implemented this, the two hubs would keep replying to each other forever.

Hub A receives Message 2 and takes note of Hub B's state. At this point the state synchronization is complete, and each hub knows both states. (They are stored in global variables; our project is full of them. Without mutexes or semaphores. Living dangerously.)

Inside each hub, the output function checks both states, and sees that one of them wants to turn on the left blinker; so it turns it on. Effectively, we can turn on both left blinkers by controlling one side.

Turning off is the same but with left replaced with off.

One potential issue is, we can't reasonably decide what to do if the user gives conflicting commands, like left on Hub A and right on Hub B. Our compromise is to just blink both ways, and hopefully the user will notice.

Another interesting thing is that, hubs receive messages in interrupt mode, which means it can carry on doing other stuff while waiting for a message in the background. We wrote (I wrote) a callback function that runs every time we receive something over the XBee. We have a certain amount of polling for the switch and stuff, but it's inside of a timer interrupt handler. So it's the first embedded project I ever (co-)wrote with an empty loop inside of main().

Checkpoint 1: March 15

It was great to see your prototype working on a breadboard. We managed to control some LEDs with a switch in front of the instructors. They asked us what we planned to do with the accelerometers. We said (I said) we would detect the angle it is held up to relative to ground to trigger the blinkers, and deceleration along the "road" axis to trigger the brake light. Robert said we managed to eliminate most of the complexity of using an IMU (i.e. accelerometer). I asked if it's a good thing or bad thing; he said good.

We expressed (I expressed) concerns about us running out of GPIOs on these tiny Nucleo boards. Matt replied that we had so-called GPIO expanders, so we got one later. It's a PCF8574, running on I²C, which allow multiplexing. We use I²C for the accelerometers anyway, so that means 8 extra pins for free. I noticed that it's pretty unconventional in that there's no input/output mode selection; it's kinda scary actually.

Because the output we need are mostly PWM, which is high-frequency, we only read GPIO inputs through the expander. This simplifies our driver code a lot. (The expander driver, which is 12 lines of code in the most permissive definition of code, is one of the few parts in the project not authored by me.)

When we left their office, I felt content with our progress. I said: "We're gonna make this so even an idiot can use it." Upon which Robert replied, "oh, good, so even I can."

A moderate amount of self-deprecation is a healthy communication trick, but my arrogance wasn't, especially when it led to me writing this whole fucking self-deprecating blogpost. Because you'll see the idiot, in fact, is me myself, and I can barely operate the device.

We ordered some light sensors which arrived that day, but later the bag containing them was gone, so we ended up replacing them with LDRs (light dependent resistors) that did basically the same thing, and arguably better on a PCB.

Anna the Wasp Savior

On 2024-03-17, a wasp got loose in the 373 lab (which may or may not have a causal relationship with the presense of a bunch of boy/girl scouts in the EECS atrium). I, like many others, was briefly terrified, but calmed down to think about a countermeasure.

Anna Huang, the IA, stepped up in a heroic fashion to capture it. She grabbed a plastic cup and trapped it against a big box. I offered my clipboard and she managed to confine the wasp between it and the cup. We walked down the stairs, where I learned that she wasn't about to kill it, but to release it. When I asked her where, she initially considered in the atrium toward the scouts, but changed her mind and released it outdoors.

She also asked me to take a photo and share it with her, which I did. In my final PCB design, I credited her as "IA & Wasp Savior: Anna Huang".

First Big Mad moment

On 2024-03-17, I wrote the following on the project log.

Got stuck for 2 hours because

  • Amazon says the accelerometer is “LIS3DSH”
  • The PCB says “LIS3DH”
  • The chip is marked “DSH”
  • LIS3DH accepts I2C addresses 0x18 and 0x19
  • LIS3DSH accepts 0x1d and 0x1e
  • The chip responds to 0x1d and 0x1e
  • There is a read-only register on the chip called “WHO_AM_I” that’s supposed to be 0x33 on DH and 0x3f on DSH
  • I read it
  • It’s fucking 0x3b


18:05: OK this is fucked up

On the datasheet it says you’d append 0 to the I2C address if you’re writing and 1 if reading


I just flipped these and it fuckijng worked

[in huge font size] FUCK YOU ST

In case the text above didn't make enough visual impact, here's what it looks like:

A page of text ending with a giant "FUCK YOU

Enclosure & connectors

My teammate and I took a moment to discuss how we wanted to assemble our product, and especially how it looks from the outside. I proposed that we expose two sockets, on the left & right, for the accelerometers. I forgot how the rest of the conversation went, but it involved searching the whole lab for vernier calipers. There was none. We ended up using a one-meter-long blackboard ruler for a fucking 7x10 cm board.

Earlier in our proposal we mentioned a modular design, where everything is hot-pluggable. Halfway through the project, this target began to seem unattainable, so we had to make some of them, like the radar and buzzer, integrated on the circuit board, be it protoboard or PCB.

3D printing was never my forte, so my teammate is resposible for modeling and printing. She did an impeccable job. One problem was that the PLA they printed our enclosure with was yellow. Our LEDs are also yellow.

She was like "it's ok, we can tape over the front surface" and she was right.

She also laser-cut acrylic with screw holes to hold our circuit boards in place.

I planned to use dupont sockets for the accelerometers. STUPID FUCKING IDEA. Dupong sockets are good for prototyping, and that's it. There's a REASON why you don't see them everywhere. There's a REASON we have different cables.

Stupid thing #4: Not using a proper connector.

Buying more stuff & putting them together

We bought some more stuff.

  • Reflective jacket w/ two armbands
  • Velcro
  • Superglue (despite lab rules technically banning them due to insufficient ventilation i dunno bro we got solder irons running full blast here i could inhale this all day (I did inhale this all day later))

In a genius supernova, my teammate(s?) discovered the art of velcro on everything. We attached (they attached) the accelerometers to the armbands with velcro. It worked fine (mostly).

Fire alarm!!

On 2024-04-03, at precisely 13:11, the alarm went off so I packed and left. Went for a much-needed lunch.

Two days later I bought a bicycle, partly because of this project. Spoiler: it wasn't that much useful.

We also demo'd checkpoint two to an IA. We were behind schedule but I didn't think it was a big deal. It was a big deal.

LDR, stupid thing #5, and brainfart #2

My teammate worked on the LDR. Its resistance depended on ambient brightness and all you need to do to read it is to wire it up in series with a fixed resistor and ADC the voltage between them. We had a lab for that.

I found a problem with the implementation: it slowed down the blinking considerably. It was because the Nucleo would do an ADC every time we enter the output function, which runs every millisecond, and each blink is 400 ms. ADC takes time and they add up. At this point I knew what problem we had. I focused on writing code on my own, without explaining to my teammates what I intend to design it. Of course, it led to relatively clean code, but it was worthless if nobody understood it.

There are two states of team project code that are acceptable to me:

  • Tightly coupled monolith, but everyone understands every line
  • Each person is responsible for one part only, but interface is clearly defined

Our project was neither. It was tightly coupled and almost completely authored by a single person. In hindsight, this was catastrophic. It meant that in the later part of the project, when time is running out, I was the only one who could make software fixes. The core reason is the lack of regular team meetups. I sometimes see all four or at least three members of certain teams in the lab or in the basement of the Duderstadt. Our team, on the other hand, has never had a meeting where everyone was present except the brainstorm discussion, the presentation, the evening before the demo, and the demo.

I should have motivated my teammates to meet up at least once every week. I should have had the motivation to motivate my teammates.

Stupid thing #5: Not meeting regularly.

When did this blog become a landmine of stupidity to embarrass my future self? Anyway.

I had a brainfart again. The LDR had higher resistance when it's dark, and if we tie one end to VCC and the other end through a 2.2k fixed resistor to GND, then less light would give us a lower ADC reading, and if so we decrease the brightness of LEDs. Problem was, if the LDR disconnects from the circuit (which may happen on a bumpy road), the ADC drops close to 0, even if it's the middle of the day. My teammate's workaround is to detect if the ADC drops below a certain threshold, at which point we assume the LDR dropped out, and fallback to maximum brightness.

My smartass was like, why this complicated? Just reverse the LDR and the 2.2k, problem solved!

She was like, no…? If I reversed them, then the ADC reading would also be upside down, because LDR dropped out == infinite resistance, which would be naïvely interpreted as no light either way. So I admitted I was wrong.


A minor part of the project is a presentation, comprised of a pitch that's no longer than 30 seconds, and two minutes of slides per person. I skipped a lecture to meet with my teammates. A lack of tables prompted us to go outside near the swings. It seemed impossible to read the pitch in 30 seconds so I cut some sentences. I was very much not stressed at all.

Robert used a D4 to randomly pick a person to do the pitch, and he rolled a 1, which happened to be me, who stood on the left hand side of the classroom. I did it in probably 20 seconds. Nice.

The presentation was quite successful; I did at least one joke about how breadboards on bikes make your distributed system a very distributed system.


On 2024-04-07, according to the project log, I would "now begin working on a pcb." A week later, on 2024-04-14, the PCB was "taking shape". The next day, I finished and ordered it from PCBWay. But it was already too late.

I have no idea why I did not finish the PCB sooner. It's just plain stupid. I should never have trusted the "3-4" days shipping. Production took probably one day and a half; shipping was another story. I was too optimistic about global shipping. I modeled it as a sphere on an ideal, frictionless plane. In reality it's stuck in Shenzhen, stuck in Cincinnati, stuck in Romulus.

DHL shipment updates

I needed it for demo day; I got it the afternoon after demo day.

Stupid thing #6: Not ordering the PCB sooner.

But at least I had fun designing the PCB, so let's talk about it.

Front and back of PCB, rendered in KiCad

The board shape features a notch, just because we can. Take that Apple!

The screw holes align with those on the acrylic my teammate laser cut.

To avoid interfering with microwave black magic, I intentionally shoved the antenna part of the radar over the board edge.

We added a couple NFETs in the power paths of some components, including the expander and the radar, because they have a criminal record of freezing for no reason, rescued only with a hard power cycle.

The silkscreen features two memes:

  • "This side toward enemy", stolen from meme below

An AT&T network interface device, scribbled "this side toward enemy" in
all caps with a chisel-end

  • PCBWay, adapted from a meme I made long ago (🎜 just like the hearse you died to get in again 🎜)

Photo of Gerard Way on a PCB silkscreen, with a blurry "PCBWay" logo
below for full meme effect

Additionally it features the name of everyone in our team, our instructors, GSI, and IAs. I feel it is necessary to pay credit to everyone who helped. Also you paid for silkscreen you gotta use silkscreen

In terms of timing, I fucked up.

In terms of design, I regret nothing.

Protoboard (NOTE: avoid at all costs!)

I would pick soldering ten PCBs over one single protoboard. It's just PCBs with all the pain and none of the benefits.

Parts? Manual. Wires? Manual. I would NOT like to remember it, no thank you. The last time I ever touched a protoboard was in 2022, so I apparently forgot how painful it was. A PCB was definitely worth it. So why did we solder the protoboard anyway? Well, see stupid thing #6. fml

If I had done the PCB sooner, I could have avoided the protoboard. If I just committed to the protoboard (bad idea), I could have avoided the PCB work (and money; I hope it can be reimbursed). But I missed the chance, and now I had to do both.

Incidentally, this coincided with my obsession with OK Computer (1999), notably the track "Let Down".

Project log, 2024-04-19 10:52:

Woke up to DHL’s email that the ETA of the PCB is Tuesday by end of day. ffs really reconsidering the point of living at this point. Day ruined

Backup plan: I’m gonna head to the lab these days and solder up the protoboard with pin sockets, so all the expensive shit are removable.

Devastated, I told my teammates what I did. I was the one who fucked up, so I had to take full responsibility. I sat in the lab with my Pinecil, and soldered up one (1) board.

Project log, 2024-04-19 22:53:

God is dead and it was I who killed him with my Pinecil® soldering iron running on 65W USB-PD as I soldered BicycLED on the protoboard

This is the worst shit imaginable. Imagine being late by exactly one day and having to devote 2x more work and endure 10x more stress than a PCB.

I have to take full responsibility of the PCB not arriving on time, and I am paying the toll with probably one year of my life expectancy for the lead and rosin inhaled today. At my funeral, in lieu of flowers, send fume extractors.

My teammate (the one who did the 3D printing) joined me. I can't thank her enough. We spent entire evenings in the lab, just working our asses off. The worst part is that, our work is of no worth other than to not miss demo day.

Those nights I had really bad insomnia. Like three hours of dread and horror. Pressure did not kill me, but I wished it had.

This was the result:

Protoboard with a bunch of parts soldered on

The back side. Bunch of wires, real

Fuck it

How the fuck have I written 6k words already?? This is way too long for a blogpost. If you're still reading you should go for a glass of water or something.


On 2024-04-11, we were working on the lab computer and found a bug where it doesn't regenrate template code when we modify the configs. This led to the second fuck you in our project log.

[W]e moved the buzzer to TIM16. But the TIM_HandleTypeDef htim16 wasn’t showing up, and the GPIO macros for BUZZER remained unchanged. I restarted the IDE, but it refuses to update code no matter how many times I hit “generate code”.

I zipped the project and imported it into my machine. It worked instantly.

[in huge font] FUCK YOU ST

On 2024-04-21, we were honored to present the third fuck you.

[Redacted] and I went ahead and soldered the second board with insurmountable pain. But the PCF8574P we got last time did not work. When we hooked up a logic analyzer, it never acks.

I noticed that the two chips we have are different. The first one that works is TI; the other is NXP. However, their datasheets are practically the same.

I wrote a loop to iterate I2C addresses from 0x20 to 0x80. It replied to 0x38. According to the datasheet, this address belongs to PCF8574A, but the chip we have is marked PCF8574P, the DIP-16 package of PCF8574, without the A.

[in huge font and bold face] FUCK YOU NXP

oh wow I went full linus mode

Final evenings

Things that happened the evening two days before demo day:

  • All four of us showed up (surprise surprise)
  • We attempted to power the circuit with 12V on VIN
  • Why is it so hot??

Stupid thing #7: Not testing power earlier

  • It turns out if you power the Nucleo with 12V (max voltage), the MCU gets really hot which shouldn't happen if you have a good voltage regulator
  • We tried USB VBUS on the 5V pin next to VIN
  • The MCU just straight out doesn't work
  • ????????
  • Quick, get a buck converter
  • It's bulky
  • Teammate: Fuck it, just power it over USB!
  • Me: No… ok fine
  • Uh oh, we have to make a hole in the lid

Things that happened the evening just before demo day:

  • Teammate: Hey here's a lid with a hole I just laser cut
  • Oh look a perfect fit
  • OK we did it!
  • Me: Let's install it on my bike!
  • [I bring my teammates to my bike and attract a raccoon]
  • We install stuff
  • It kinda works but wonky
  • Fuck it let's not
  • Take everything off, decide to present them on a table instead
  • What about the poster?
  • Teammate: Oh yeah the poster. It's at my apartment. There's a blank space called "assembled product" which we can finally patch
  • Me: yeah let's print it
  • [We go to the color printer at the Duderstadt and print the pictures]
  • Me: hey let's print the project log it's got three big fuck yous it's funy
  • [I did not wait for their approval]
  • The cover:

BicycLED project log. Warning: explicit language. (parental advisory
explicit content sticker typically seen on

The bicycle:

Two clunky boxes barely holding on
a bicycle

Demo day. Fucking finally

We were glad it was over. We're just… so done, literally and metaphorically. Not sure about how other teams were doing, but we were dying of boredom.

I got there early and tested out the stuff we had. The accelerometers were… still wonky. Then a few wires came off after we set up the table. Never would have happend if I had used a proper connector that stays in place. Glad I took my Pinecil with me. The faithful iron fixed like three faulty wirings. Truly the MVP of the day.

I skipped two lectures for the demo. The professor whose lecture I was supposed to be at (💀) showed up and was one of the first to check out all the exhibits. He's my 311 (analog circuits) professor. "There's BJTs in here. You would be proud," I said.

"I'm already proud of you," he replied.

Then it was time to do two things:

  • Avoid attracting attention, and in the case we failed, explain to the curious person what our project does (spoiler: not a lot)
  • The graded demo

We missed a chance to do the graded demo once, because I was fixing the wires. Once we got the chance to get the GSI back, we demo'd all the shit we did. He was like "huh cool" and scribbled some notes on his clipboard.

Later the instructors came and to our horror the accelerometers failed. (tbf they intermittently failed regardless of who we're presenting to.) I pressed the reset button a few times hoping they didn't notice, and it finally worked once (probably a false positive). Then Matt grew interested in the Doppler radar. He tried to trigger it by moving his body in the vicinity of the radar. We had set the threshold to the highest possible to prevent false positives (it was still sensitive af), to the point the buzzer only honks if you're moving within a few centimeters away from the radar. We figured as long as it's for a demo, it'd be fine. And it was fine. It didn't honk all the time. It honked some of the time. And that's good enough.

Like, the project was a failure, so what? There's nothing I could do at this point. I really hope we didn't disappoint the instructors. Not as much as I disappointed myself.

I was so done with everything. I pulled up the 473 (advanced embedded systems) slides and read them to pull me out of this torture.

We wrapped up all our stuff at 14:00 at the first convenience so we can say goodbye to this crap.

PCB (the sequel)

The moment I came back home, I saw the PCB lying at my door.

The next day I went to the lab… I soldered it with my teammate… Then a few days later I demo'd it to Matt. I made an excuse that the accelerometers were fried (they probably were, but I was too lazy to check). He sent Robert an email that the PCB in our report is a real thing that exists.

Then we took (I took) the project apart and returned the public assets back into their respective bins. You won't believe how many USB cables we used for the Nucleos, logic analyzers, XBee configuration dongles, etc.

Then it's just a matter of submitting a bunch of end-of-project stuff like our code and my PCB design files. And the report. In the report we're asked to estimate our complexity points. The goal is 4 (1 for every person). Here's our estimate (based on a reference the instructors gave us early on):

  • Accelerometers: 0.67
  • Light sensor: 0.25
  • Doppler radar: 0.25
  • XBee: 0.50
  • Synchronization protocol: 0.50
  • PWM + Transistor: 0.25
  • PCF8574P/AP: 0.50
  • 3D printing & laser cutting: 0.50
  • PCB & protoboard: 0.67
  • Total: 4.09

This was based on my teammate's estimate, and I adjusted it while keeping the sum over 4. The Doppler radar doesn't actually deserve that much complexity; it's just two GPIOs. Infineon did all the analog magic for us (which disappointed Matt, who thought it would at least expose some of the non-microwave signals for us to do some Fourier with).

The PCFs weren't this complex either. Probably 0.33 at best.

Oh, yeah, and my insomnia is healed.

Mistakes (again)

I finally dumped everything I want to say about this cursed project of ours. Now, let us recap my mistakes.

  • I am a poor collaborator
  • Taking too many time-consuming courses
  • I did not ask my team to reach a consensus before beginning work
  • An incorrect, idealistic idea about course projects
  • Not using a proper connector
  • Not synchronizing progress with teammates often
  • Not testing power and heat dissipation early on
  • Designed and ordered PCBs too late

So, to address the problems, all I need to do is:

  • Design everything early
  • Don't take more than 2 EECS courses per semester
  • Meet with majority of team once per week
  • Discuss project goals
  • Clarify every detail about project goal; when in doubt, leave a note or mark as TODO
  • Use a proper connector for everything
  • Test in real environments as soon as possible

Final word on project

I take the L.

That said, I still sulk over this course. I feel that I did not release my full potential. Indeed, it is hard to compete with other teams of four in a team of an effective size of 2.5. But only losers blame teammates. Victors blame themselves, fengshui, and the phase of moon. I believe the solar eclipse may be part of the conspiracy.


Good course, but don't take it with 482. Useful if you want an extensive set of knowledge, so that when you need to make some hardware you know where to start. The course is not enough to make anything that would instantly sell though. That would require expert knowledge in industrial operation, market touching, and probably a lot of money.

I re-emphasize that my experience with the project is not representative of the typical 373 experience.


Halfway through writing this blogpost, I tooted

tfw you fucked up a project so bad you're writing a blogpost about the mistakes you made and you're at the 6,458 words mark

the #1 advice to not fuck up projects is to not do projects. thanks for coming to my ted talk

that said i voluntarily signed up for a project very similar in logistics next semester because i have a habit ofovercompensating [sic]

Yes, I enrolled in 473. I only plan to take a maximum of 15 credits next semester, and will drop 3 if my IA application is accepted. This should make workload reasonable.

Mark Brehob will be teaching 473, with Matt Smith still being lab instructor, which is great news because they're both great and I know both of them. But probably everyone does.

And now that I have a bicycle, I can ride to north campus whenever I want.

I already have like two ideas brewing in my head. I will look for teammates myself based on project interest this time. I really hope it doesn't bust again.

Damn it, "Let Down" just came on again. Better wrap this up before the sad part.