diff options
29 files changed, 1876 insertions, 0 deletions
diff --git a/docs/random/2024-04-05.md b/docs/random/2024-04-05.md index be1919f..fe62e55 100644 --- a/docs/random/2024-04-05.md +++ b/docs/random/2024-04-05.md @@ -239,6 +239,9 @@ of that. Dallon casually admitted to sampling a car horn in the ending track, "iDIOTS OF Oz". We have achieved peak [xkcd #780](https://xkcd.com/780/). +Over the duration of the show, Dallon threw two picks, but neither was in +my range. + ### The cringeworthy story of my PCBs Warning: this story is cringe. If we ever meet in person, even if we're diff --git a/docs/umich/img/w24_wrapup/311_bad_apple.jpg b/docs/umich/img/w24_wrapup/311_bad_apple.jpg Binary files differnew file mode 100644 index 0000000..8de5d1e --- /dev/null +++ b/docs/umich/img/w24_wrapup/311_bad_apple.jpg diff --git a/docs/umich/img/w24_wrapup/311_hp_4155b.jpg b/docs/umich/img/w24_wrapup/311_hp_4155b.jpg Binary files differnew file mode 100644 index 0000000..f26c6b2 --- /dev/null +++ b/docs/umich/img/w24_wrapup/311_hp_4155b.jpg diff --git a/docs/umich/img/w24_wrapup/311_latex.png b/docs/umich/img/w24_wrapup/311_latex.png Binary files differnew file mode 100644 index 0000000..d5d4561 --- /dev/null +++ b/docs/umich/img/w24_wrapup/311_latex.png diff --git a/docs/umich/img/w24_wrapup/373_bike.jpg b/docs/umich/img/w24_wrapup/373_bike.jpg Binary files differnew file mode 100644 index 0000000..3b81690 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_bike.jpg diff --git a/docs/umich/img/w24_wrapup/373_dhl.png b/docs/umich/img/w24_wrapup/373_dhl.png Binary files differnew file mode 100644 index 0000000..b9d818b --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_dhl.png diff --git a/docs/umich/img/w24_wrapup/373_fuck_you_st.png b/docs/umich/img/w24_wrapup/373_fuck_you_st.png Binary files differnew file mode 100644 index 0000000..831776a --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_fuck_you_st.png diff --git a/docs/umich/img/w24_wrapup/373_log_cover.png b/docs/umich/img/w24_wrapup/373_log_cover.png Binary files differnew file mode 100644 index 0000000..01278af --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_log_cover.png diff --git a/docs/umich/img/w24_wrapup/373_pcb.png b/docs/umich/img/w24_wrapup/373_pcb.png Binary files differnew file mode 100644 index 0000000..bd1da09 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_pcb.png diff --git a/docs/umich/img/w24_wrapup/373_pcb_back.jpg b/docs/umich/img/w24_wrapup/373_pcb_back.jpg Binary files differnew file mode 100644 index 0000000..23d80bf --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_pcb_back.jpg diff --git a/docs/umich/img/w24_wrapup/373_pcb_front.jpg b/docs/umich/img/w24_wrapup/373_pcb_front.jpg Binary files differnew file mode 100644 index 0000000..1f5ee4d --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_pcb_front.jpg diff --git a/docs/umich/img/w24_wrapup/373_pcbway_meme.png b/docs/umich/img/w24_wrapup/373_pcbway_meme.png Binary files differnew file mode 100644 index 0000000..07811a1 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_pcbway_meme.png diff --git a/docs/umich/img/w24_wrapup/373_protoboard_parts.jpg b/docs/umich/img/w24_wrapup/373_protoboard_parts.jpg Binary files differnew file mode 100644 index 0000000..9503393 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_protoboard_parts.jpg diff --git a/docs/umich/img/w24_wrapup/373_protoboard_wires.jpg b/docs/umich/img/w24_wrapup/373_protoboard_wires.jpg Binary files differnew file mode 100644 index 0000000..1216cd0 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_protoboard_wires.jpg diff --git a/docs/umich/img/w24_wrapup/373_this_side_toward_enemy.jpg b/docs/umich/img/w24_wrapup/373_this_side_toward_enemy.jpg Binary files differnew file mode 100644 index 0000000..ca95d03 --- /dev/null +++ b/docs/umich/img/w24_wrapup/373_this_side_toward_enemy.jpg diff --git a/docs/umich/img/w24_wrapup/482_submission.png b/docs/umich/img/w24_wrapup/482_submission.png Binary files differnew file mode 100644 index 0000000..969a11a --- /dev/null +++ b/docs/umich/img/w24_wrapup/482_submission.png diff --git a/docs/umich/img/w24_wrapup/482_website.png b/docs/umich/img/w24_wrapup/482_website.png Binary files differnew file mode 100644 index 0000000..dc80170 --- /dev/null +++ b/docs/umich/img/w24_wrapup/482_website.png diff --git a/docs/umich/img/w24_wrapup/banana.jpg b/docs/umich/img/w24_wrapup/banana.jpg Binary files differnew file mode 100644 index 0000000..beec971 --- /dev/null +++ b/docs/umich/img/w24_wrapup/banana.jpg diff --git a/docs/umich/img/w24_wrapup/blueberry_pizza.jpg b/docs/umich/img/w24_wrapup/blueberry_pizza.jpg Binary files differnew file mode 100644 index 0000000..51b9956 --- /dev/null +++ b/docs/umich/img/w24_wrapup/blueberry_pizza.jpg diff --git a/docs/umich/img/w24_wrapup/boston_art.jpg b/docs/umich/img/w24_wrapup/boston_art.jpg Binary files differnew file mode 100644 index 0000000..760e774 --- /dev/null +++ b/docs/umich/img/w24_wrapup/boston_art.jpg diff --git a/docs/umich/img/w24_wrapup/dallon.jpg b/docs/umich/img/w24_wrapup/dallon.jpg Binary files differnew file mode 100644 index 0000000..92218dc --- /dev/null +++ b/docs/umich/img/w24_wrapup/dallon.jpg diff --git a/docs/umich/img/w24_wrapup/eclipse.jpg b/docs/umich/img/w24_wrapup/eclipse.jpg Binary files differnew file mode 100644 index 0000000..506c903 --- /dev/null +++ b/docs/umich/img/w24_wrapup/eclipse.jpg diff --git a/docs/umich/img/w24_wrapup/fluke_77.jpg b/docs/umich/img/w24_wrapup/fluke_77.jpg Binary files differnew file mode 100644 index 0000000..092a5a4 --- /dev/null +++ b/docs/umich/img/w24_wrapup/fluke_77.jpg diff --git a/docs/umich/img/w24_wrapup/gummy_worm_cake.jpg b/docs/umich/img/w24_wrapup/gummy_worm_cake.jpg Binary files differnew file mode 100644 index 0000000..4c5fa49 --- /dev/null +++ b/docs/umich/img/w24_wrapup/gummy_worm_cake.jpg diff --git a/docs/umich/index.md b/docs/umich/index.md index ecb443b..ee428cb 100644 --- a/docs/umich/index.md +++ b/docs/umich/index.md @@ -5,3 +5,7 @@ so basically i live in ann arbor now - [Lessons in the US of A](us_lessons.md) - [Fall 2023 Wrapup](f23_wrapup.md) - [Fall 2023 winter break wrapup](f23_winter_break.md) +- [Winter 2024 Wrapup](w24_wrapup.md) + - [EECS 482, Intro to OS](w24_482.md) + - [EECS 373, Intro to Embedded System Design](w24_373.md) + - [EECS 311, Analog Circuits](w24_311.md) diff --git a/docs/umich/w24_311.md b/docs/umich/w24_311.md new file mode 100644 index 0000000..7080ee4 --- /dev/null +++ b/docs/umich/w24_311.md @@ -0,0 +1,238 @@ +# Winter 2024 Course Review: EECS 311 + +2024-05-03 + +Course Title: Analog Circuits + +Rating: 3/5 + +## Instructor (David Garmire) + +On the first lecture I had a feeling I've seen him before. I checked the +"courses offered" spreadsheet at SJTU last semester, and he taught 281. + +He's all nice and stuff, and he never judges you. But the vibes are not +the best I could imagine. He's pretty reserved, and often seems in doubt +of himself, as if he's teaching it for the first time. Contrary to two +other EECS professors I had this semester, he had the least "authority +figure" vibes. (Robert Dick sometimes has too much; Brian Noble has it +just right.) Sometimes we can't tell if we're wrong or he's wrong. If we +point out he _might_ be wrong, he stops right away, which is good, but his +first assumption is always he _is_ wrong, which hurts credibility if he's +not. + +One thing I like about David Garmire is his analogies. The best one is how +the NPN BJT is like a leaky tub of water. + +## Course topics + +- Introduction & review (e.g. Laplace transform, Bode plots) +- Opamps + - Inverting & non-inverting amplifiers + - Nonidealities +- Sallen & Key filters +- Diodes +- BJTs + - CE, CC and CB configurations + - High frequency + - Degeneration +- MOSFETs + - CS, CG and CD configurations + - High frequency + - Degeneration + +### Personal reflections + +Compared to EE majors in the room, I was all chill about this course. +I enrolled because I was interested, not because I was required to. It's +not like my degree or life depended on it. But my life does depend on +music, and it's part analog circuitry. + +Personally, I think Sallen & Key (S&K) just came out of nowhere. There was +no motivation. It's just a table of equations that we use to solve for +like six unknowns. It's not fun. + +BJTs are the most complex topic. You've got three currents coming in or +out of the BJT, one of which can _sometimes_ be ignored. You have three +modes: cutoff, active and saturation. To make a useful amplifier, you have +to juggle the voltage correctly to bias it in the right range; then you +get a transconductance, then you convert it to a linear circuit with +a dependent current source, then you either do a bunch of nodal analysis +or just apply formulas. In most cases formulas Just Work™. + +I remember taking 215 (the OG circuits course) and scoffing at the notion +of a "voltage-dependent current source". Like who would use that in real +life? I bet you ten bucks you can't even build one. However, it turns out +if you apply superposition principle to a non-linear circuit, and +constrain your input to a narrow range to pretend it was linear, an +"X-dependent Y source" appears, and it helps you apply linear formulas to +an otherwise unholy "e to the power of v over something" pasta. + +MOSFETs are just BJTs but with different names for everything (the "active +region" of the BJT is analogous to "saturation mode" of MOSFETs). Also one +of the three currents is gone (except in high frequency) and you juggle +the voltages in a different way. + +Overall, this course was more inspiring and extensive than I thought. +However, it was also pretty elementary. I enrolled because two of my +hobbies (ham radio and music) are closely relevant to analog circuits, and +I had hoped to build an amp after this course. Although half of the course +_is_ building amps, it's pretty theoretical. + +### Building amps + +The majority of our discussion toward the second half of the course was +transistor-based amplifiers. Interest was mostly on NPN common-emitter or +NFET common-source, but there are other configurations to fit niches. We +had these parameters to optimize for: + +- Gain (open-circuit, loaded, or overall) +- Output voltage swing (how many Vpp can you output before clipping) +- Bandwidth (low & high 3dB cutoff) +- Output impedance (affects loaded gain) +- Input impedance (affects overall gain) +- Power dissipation (how much DC power does it draw) + +Desiging amps, especially multi-stage ones such as what I did in lab 5, is +an ardous chain of trial and error. My observations are + +- Build first stage with around 10x the signal impedance +- Think about gain first +- 1 mA is usually a good DC current to start with +- If it doesn't work, try 1.5 or 2 +- DC current determines gain, output impedance, and power +- Too little and too much current both lead to bad overall gain +- Decouple all stages by chucking in a 1 µF to 47 µF cap +- If load impedance is small, add a buffer at the last stage +- Bandwidth is the last thing to worry about +- If you need to squash highs, add a cap from a signal to ground +- If you need more lows to pass, use larger decoupling caps + +Those tradeoffs are an inevitable part of an electronic engineer's life. +Besides, some transistor parameters (such as beta) depend on temperature +and fab variations, so we had to add feedback to make our circuit less +susceptable. I now appreciate the amount of work that analog engineers go +through just to create a usable amp. + +### Sine wave breakdown & shoutout to Samuel + +Another way to look at amp-building in the scope of 311 is to break down +a sine wave: + +x(t) = A * sin(ωt + ɸ) + b + +- A: amplitude, or in our case, gain. We talk _a lot_ about gain. Arguably + the _point_ of amps is gain. +- ω: frequency. We spent two lectures on high frequency response, one for + BJTs and one for MOSFETs, which discuss internal capacitances within the + transistors. The effect of external capacitors is discussed in the first + half of the course, in analog filters. +- ɸ: phase. We hardly ever talked about phase, and phase Bode plots were + not required. However we were required to tell apart inverting and + non-inverting amps. +- b: DC offset. In general not a thing to worry too much about. If you + need to get rid of it, just add a cap. If you need it back, bias your + base/gate/whatever. It's just a stepping stone for the AC signal. + +The frequency discussion is very interesting. We used a duo of methods +called OCTC and SCTC (open/short circuit time constant) to estimate the +lower and upper 3dB cutoff frequencies. They work like magic. Two separate +occasions, the estimate I got with them is within 1% of SPICE simulations. +Huge kudos to Samuel Nolan, our IA, for explaining the methods in the lab. +He is the GOAT IA this semester. + +### Analog vs. digital + +On the first 311 lecture, David Garmire talked about the quote unquote +"superiority" of analog circuits over digital ones, such as energy +efficiency. Somewhat ironically, exams two and three had one design +problem on each, and the premises are both to design an amplifier for an +ADC, presumably into a chain of DSP algorithms. + +Many systems now use DSP, which often is cheaper and/or more noise-proof, +so unless you're an retro-audiophile or still live in the 1900's, very few +things actually have analog circuitry from top to bottom. They usually +have at least one piece of integrated circuit somewhere. But even if it is +the case — he argues — analog circuits are essential. + +There was a 373 lecture dedicated to ADC/DAC, and later there were a few +slides that discuss analog filters. It was one of the few occasions this +semester that 311 was useful for another course. I am more than sure it'll +be useful for 473 next semester as well. + +Robert Dick acknowledges that sometimes there are problems 1's and 0's +cannot solve. One such example is high frequency noises in the ADC input, +which cause aliasing, and are a pain to distinguish from actual signal in +software. So the solution is to add a lowpass filter to the input. + +I am unsure whether my preference is analog or digital. On one hand, +analog is cool because my bass is an analog system. But the DAW is digital +(it literally stands for digital audio workstation). Let's leave it this +way. + +## Labs + +Labs are the heaviest workload of 311. There are five labs in total, each +spanning over two or three weeks. + +- Lab 1A/B: opamps +- Lab 2A/B: S&K filters with opamps +- Lab 3A/B: voltage boosting & power harvesting with diodes +- Lab 4A/B: single-stage BJT amp, measuring beta and capacitances of BJT +- Lab 5: designing a 3-stage amp + +The typical roadmap of a lab: + +- Prelab: Do calculations, simulate in SPICE +- In-lab: Build circuit, measure with ADALM and Scopy + +Note: + +- The ADALM is a virtual lab kit USB device by Analog Devices +- Scopy is the software to interface with the ADALM. It's got an + oscilloscope, a voltage supply, a multimeter, and a network analyzer + (which you use to get Bode plots). Thankfully it is open source and runs + on Linux (was a pain to install though because it's not in any pacman + repo or AUR. Had to manually build it because I didn't want flatpak. + Somehow it wanted a patched version of Qt and many other deps so I had + to build like six libraries and manually change CMakeLists so one of + them compiles) +- SPICE is a circuit simulator. The lab docs mention LTSpice, which does + not run on Linux, so I used ngspice integrated in KiCad. Halfway through + the semester, KiCad upgraded to 8.0 which includes a major overhaul of + the ngspice frontend — huge improvement. + +In lab 3B, I built a circuit that harvests power from a 3.5mm jack to +light up an LED. Naturally, I made it play Bad Apple: + +![Bad Apple playing next to an oscilloscope waveform. An LED lights up on +a breadboard circuit](img/w24_wrapup/311_bad_apple.jpg) + +In lab 4B, I hooked an NPN BJT to a giant beast of a machine, the HP 4155B +semiconductor parameter analyzer that thought it was 1997. + +![An HP 4155B semiconductor parameters analyzer displaying a graph. The +date is "97AUG07 11:46PM"](img/w24_wrapup/311_hp_4155b.jpg) + +Despite not having an A/B, lab 5 took three weeks. After designing and +simulating (but not building) a circuit, I needed to write a report for +the design of my three-stage amp. It "must be written with a word +processor", but did not mention which one. + +![Three pages of my report written with LaTeX, featuring a circuit +schematic, a bode plot, a transient plot, and +a table](img/w24_wrapup/311_latex.png) + +I used up like 10 pages of scratch paper (single sided) just for the +calculations. Glad I did meet the specs. + +## Verdict + +It's just a gateway drug to EE. Don't expect too much — you won't be an +expert when you walk out, but do expect mind-bending moments, like how +I discovered that I've been misunderstanding BJTs for like five years. + +If your job involves interfacing with "weird" analog signals, like signal +impedances in the megaohms, then this course is essential. + +Would be better if the lab was larger though. It's like a can of sardines. diff --git a/docs/umich/w24_373.md b/docs/umich/w24_373.md new file mode 100644 index 0000000..95001ce --- /dev/null +++ b/docs/umich/w24_373.md @@ -0,0 +1,1081 @@ +# Winter 2024 Course Review: EECS 373 + +2024-05-02 + +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](https://en.wikipedia.org/wiki/Toughbook) running openSUSE. He's +the lecturer of this course. + +Pros: + +- FOSS advocate +- Is happy to discuss "what if" scenarios +- Shares stories of real startups (including his own) + +Cons: + +- 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. + +Pros: + +- Is willing to talk about any idea +- Knows everything in the lab + +Cons: + +- 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](../projects/byseekel.md) 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. + +## 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. + +## Project + +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](#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. + +### Brainstorming + +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. +> +> [1] https://www.cdc.gov/transportationsafety/bicycle/index.html +> [2] https://www.amazon.com/dp/B0C27FGHMW + +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 +sockets](img/w24_wrapup/373_pcb_back.jpg) + +▲ Back hub + +![Similar PCB with no radar but an extra buzzer screwed on the +board](img/w24_wrapup/373_pcb_front.jpg) + +▲ 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 +> +> 17:52: I GOT IT WORKING ON THE BIG NUCLEO WHAT THE FUCK IS DHAPPEBING +> +> 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 +> +> ITS WRONG +> +> 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 +ST"](img/w24_wrapup/373_fuck_you_st.png) + +### 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. + +### Presentation + +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. + +### PCB + +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](img/w24_wrapup/373_dhl.png) + +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](img/w24_wrapup/373_pcb.png) + +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 +marker](img/w24_wrapup/373_this_side_toward_enemy.jpg) + +- 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](img/w24_wrapup/373_pcbway_meme.png) + +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 +it](img/w24_wrapup/373_protoboard_parts.jpg) + +![The back side. Bunch of wires, real +abomination](img/w24_wrapup/373_protoboard_wires.jpg) + +### 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. + +### FUCK YOU ST / FUCK YOU NXP + +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 +- WHY IS EVERYTHING FAILING EVERY OTHER SECOND??? +- OH GOD OH FUCK SOLDER UP A RESET BUTTON +- MORE VELCRO!!! +- 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 +records)](img/w24_wrapup/373_log_cover.png) + +The bicycle: + +![Two clunky boxes barely holding on +a bicycle](img/w24_wrapup/373_bike.jpg) + +### 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. + +## Verdict + +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. + +## Future? + +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. diff --git a/docs/umich/w24_482.md b/docs/umich/w24_482.md new file mode 100644 index 0000000..5fb6d2b --- /dev/null +++ b/docs/umich/w24_482.md @@ -0,0 +1,356 @@ +# Winter 2024 Course Review: EECS 482 (4 credit) + +2024-04-30 + +Course Title: Introduction to Operating Systems + +Rating: 4/5 + +## Instructor (Brian Noble) + +Pros: + +- Talks clearly +- Has a schedule +- Lots of interesting stories so you learn something even if you fail 482 + (see [Trivia](#trivia) + +Cons: + +- Practically none? + +## What did I learn? + +Course topics: + +- Threads and concurrency + - Mutexes & condition variables + - Semaphores + - CPU scheduling +- Virtual memory + - Address spaces + - Page tables + - Page replacement (swapping) +- Filesystems + - inodes + - Consistency after crashing +- Network + - Sockets + - Client-server model + - Distributed systems +- Miscellaneous + - RAID + - LFS (log-structured filesystem) + +Brian constantly brought up the five tools of computer science: + +1. Caching +2. Hashing +3. Indirection +4. Replication +5. Encryption + +482 discusses 1 and 3 in great detail, 2 and 4 occasionally. The +philosophical takeaway is: + +- Whenever you have something to protect, add a layer of indirection (e.g. + using virtual addresses for user programs) +- If there's too much data to copy, also use indirection +- It can't be indirection all the way down; there must be something fixed + by convention (e.g. the first sector being the bootloader) +- If indirection gets slow, add caching +- If you want consistency, use replication (e.g. RAID with redundancy) + +The course is all about abstraction: + +- Threads are abstractions for CPUs +- Virtual memory is an abstraction for physical memory +- Filesystems are abstractions for disks +- Sockets are abstractions for network interfaces + +Part of abstraction design is to provide user programs with the illusion +that resource is infinite. A process can spawn thousands of threads on an +8-core machine, and they take turns to execute, thanks to the OS +scheduler. Of course, at some point the context switching overhead +overshadows the benefits of parallelism, but you _could_. + +Another job of the OS is to protect a program from other programs. You +can't trust user programs. Therefore you must build a layer of abstraction +so that the user program can never "control" the machine. The three things +a user program is allowed to do: + +- Touch its own property, e.g. address space, open files +- Touch property that another process explicitly shared with it +- Transfer control back to the OS with a syscall + +The point is that the OS is an absolute tyrant. A user program can never +run for as long as it likes, nor can it touch anything other than what +it's explicitly allowed to. To achieve this, the OS conspires with the +hardware so that it can intervene when certain things happen: + +- Every few milliseconds, the timer interrupt fires, transferring control + over the CPU to the OS +- The program issues a load/store marked unreadable/unwritable, and the + MMU triggers a page fault, also handled by the OS + +Although the timer and the MMU are technically part of hardware, they +always hand over control to the OS. They're part of the abstraction. +Without the timer, it would be up to a user program to give up the CPU, +which makes it really easy to freeze a machine. Without the MMU, user +programs would use direct addressing, enabling anyone to tamper with +anyone's memory. + +However, the OS can bypass either restriction, and it is the only one +allowed to do so. When a timer interrupt fires and hands control over to +the OS, the first thing the OS does is to disable the interrupt, so the OS +itself gets to run for as long as it likes. Once its job is done, it +re-enables the interrupt, and hands control back to a user program (may +not be the same one). We don't give user programs the ability to control +interrupts; not MMU either. + +We just discussed the first half of the course. The second half was less +mind-bending and more optimization trickery with "make the common case +fast" heuristics. However we did make a big deal about consistency. + +The disk only guarantees block writes are atomic. Therefore, if you need +to write two blocks to disk and you lose power halfway, you could have +written zero, one, or two blocks. That basically means you just lost two +blocks of data, because you're unsure either block is the right version. +Worst case is you end up breaking essential metadata, which corrupts the +entire filesystem. + +We can play clever tricks like careful ordering of block writes so the +last block we write "commits" the changes. But when this is not possible, +due to cyclical dependencies, we came up with the notion of journaling, +which doubles the cost of writes because we always keep a copy of the data +we're writing in the journal until we're sure these data made it where +they belong. Where is the journal? On disk. At this point I was convinced +that disks just suck. We're paying 100% overhead just to handle the 0.001% +chance that the machine crashes. But to deliver the "persistent storage" +promise, we have to pay that cost. + +The disk is just a big pool of zeroes and ones — and as such there is no +way to distinguish a block of metadata and a block of data. You have to +allocate a static location as the "boss of metadata"; for example, writing +the root inode to block 0, from which we can discover every descendent, as +we did in project 4. + +### Personal reflections + +The reason why I enrolled in the course is all my friends did it. It was +taught by Manuel, one of the "signature" professors we had at JI, +Shanghai. It's one of the most challenging courses there ever was, so +being the arrogant boy, I took it. Peer pressure except it was me who +pressured myself into taking it. + +The most mind-blowing chapter, also the one I once had the most incorrect +understanding about, is virtual memory. + +Rewind to 2021, when I was taking VG151, intro to CS. I had no idea what +virtual memory was, and was amazed that `malloc` always handed me roughly +the same address every time, beginning with `0x7fff` or something, as if +that part of the RAM was always free. I had mistakenly thought that all +processes share one big heap on the physical memory, and `malloc` had +a global table of free chunks. It does not. Each process has its own +address space, and the user program does not know, nor does it care, where +it lives on physical memory. + +The MMU also explains a gap in my brain. Prior to this course, I thought +the OS would translate memory addresses of a program before it ran (which +is not possible because you can dynamically allocate memory). Now it +became clear that there is a dedicated piece of hardware that does the +translation. + +## Projects + +Project 1 is solo, 2-4 are done in a group of two or three; mine was +three. We were enrolled in the 4-credit version of 482, which means we're +only required to do the core version, which is supposedly less work. + +We met Mondays and/or Wednesday mornings at 10 AM at the Duderstadt. It +was a great excuse to spend money on muffins and coffee at the cafe. +Nearly every time we sat at the same table with a giant screen. There was +an HDMI cable but it doesn't work. I ended up opening a Zoom meeting. + +Of the three autograders I've used at UMich, this is the least visually +interesting one, besides only allowing one submit per day with feedback, +plus three bonus submissions for each project. + +![Plain HTML website titled "Project +4 submission"](img/w24_wrapup/482_submission.png) + +It does fit in the brutalist aesthetic of the website. + +![Plain HTML website with very little CSS and an embedded google +calendar](img/w24_wrapup/482_website.png) + +### Project 1: Multithreaded disk scheduler + +Given mutexes and condition variables, build a disk scheduler. + +Not that hard, took me a few tries to get used to the paradigm of +signaling _after_ work is done. + +### Project 2: Thread library + +We built our own threads, mutexes, and condition variables. We also get to +decide what happens in a timer interrupt. + +The hardest part was taking care of all the `ucontext_t` objects, which +can't be moved because they contain pointers to themselves. We had trouble +keeping track of which stacks and which `ucontext_t`s we could delete, +because the lifetime of the `thread` object is unrelated to that of the +thread's execution flow. We ended up playing pointer tricks, which is +basically shared pointers with extra steps. + +Here is a snippet of code I wrote at 2024-02-20 00:30: + +``` +void thread::delete_context(ucontext_t *context) { + auto it = cpu::self()->stacks.find(context); + assert(it != cpu::self()->stacks.end()); + // delete stack of thread that previously died + // like burying your sibling's bones + // pour one out for the binary spirits + // freed from deallocated homes + delete[] cpu::self()->stack_to_delete; + // we cannot simply delete the stack + // of the thread that is running + // for a ghastly segfault taketh us aback + // with a coredump equally alarming + cpu::self()->stack_to_delete = it->second; + cpu::self()->stacks.erase(it); + delete context; +} +``` + +Another design mistake is how we used the `ucontext_t` pointer in the +mutex as a unique identifier for threads. It turns out the instructors +were so cunning that they managed to make our library allocate +a `ucontext_t` exactly where one was just deleted, tricking our library +into thinking the new thread owned the mutex. I still have a hard time +believing it was possible. They probably overloaded `operator new` on +a modded version of `ucontext_t`. + +I was very involved in project 2; I wrote more than half of the code, and +thus knew it like the back of my hand. + +### Project 3 + +Virtual memory pager. Manages memory address translation, paging, and +swapping. Lots of data structures needed, even a state diagram. + +I grossly underestimated the complexity. The first time I read the specs, +I was like, "pfft! single level page tables?" But it was the hardest +project for me. + +Unlike project 2, project 3 had much less effort from me. All I did was +draw the state diagram and propose the data structures and their names. +Then I got consumed by 373 and the workload shifted to Samuel who +basically did it all on his own. Therefore I don't understand it as +thoroughly as project 2. By the end of project 3 I was completely lost. + +The data structures were a complete mess. Here is a list of structs we +defined: + +- `shadow_table_entry_t` +- `filename_block_t` +- `page_occupant_t` +- `file_occupant_t` +- `swap_occupant_t` +- `page_status_t` + +which are distinct and redundant in a chaotic way. It's a miracle we +passed all the test cases. + +The lack of involvement resulted in a relatively poor understanding of the +pager, so I devoted more energy to project 4. + +### Project 4 + +Network filesystem. Listens on a TCP port and handles concurrent +read/write/create/delete requests from clients. + +I think I did a pretty good job at factoring out just the redundant code +while handling special cases in respective functions. Fortunately we just +have four request types (endpoints) to handle, so a little redundancy is +ok. + +My least favorite part of this project is how strictly we had to enforce +the one request string format. The request string is delimited with _one +space_. No leading or trailing whitespace. All this while claiming that +parsing is "is amenable for processing by `istringstream` (e.g., +`operator>>`)". My sibling in heaven, `istringstream` is not the one you +want if whitespace is significant. I ended up using regexes, because it's +preferable to having to read one character at a time while constantly +checking whether you've exhausted the string stream. I regret nothing. + +Project 4 was the first time I actually used RAII in a productive way. +Because every filesystem access is a traversal down a tree, and we want to +prevent race conditions, every descent requires that we grab a lock and +release a lock. Some are reader locks and some are writer locks. This is +cumbersome to manage manually, so I wrote an RAII wrapper that keeps track +of what locks we are currently holding and what type of locks they are. At +the end of the object lifetime, the destructor simply goes over the list +and unlocks them one by one. If we call a function that needs to +lock/unlock, we simply pass the wrapper by reference. Easy! + +I'm not sure if this is healthy, but I cringe whenever someone optimizes +code to "fit the scenario at hand". In the early stage of the project, +I wrote a function called `alloc_block()`, which takes void and returns +the block number just taken out of a pool. Later we realized that if an +operation needs two allocs, but failed in between, then the first one +would never be freed. We thought it would be better if we could atomically +alloc two blocks, so I suggested my teammate to generalize the function to +take one optional parameter and return potentially more than one block. + +When the function was reimplemented, I found that it was not quite what +I meant. I was thinking something along the lines of + +``` +std::vector<uint32_t> alloc_block(uint32_t count = 1); +``` + +What it ended up being was + +``` +std::pair<uint32_t, uint32_t> alloc_block(uint32_t count = 1); +``` + +which returns the allocated block # in the _second_ element of the pair if +`count == 1` (because it kinda fits our semantics better), and returns two +valid block #s if `count != 1`. + +I feel uncomfortable that `count` did not function as advertised; it +behaved more like a bool. But since we're using our late days (it's the +first time I ever used a late day) and we're tired, I let it slide. + +## Verdict + +Now that I've taken the course, done the projects and sit through the +exams, I do not regret taking this course. I do, however, regret taking it +with two more workload EECS courses, one of which (373) is also +heavy-workload. + +I would recommend Brian Noble to anyone, no questions asked. He is my GOAT +professor of the semester. The slides follow the +motivation-solution-problem-remedy train, which tightly model the actual +evolution of real systems in the e.g. 1980s. It's interesting to know what +came before modern systems and what Linus Torvalds et al. needed to take +care of when they crafted the revolutionary kernel. + +## Trivia + +Brian always has stories to tell. My favorite story is how when he was +young, his advisor talked to him about his unnecessarily complex wording +in his paper. I personally do believe the doctrine, "why many word when +few word do trick". + +Later on a lecture on log-based filesystems, he had a callback to the +story. He goes (paraphrased): + +> What I lament about project 2 is, the right way to identify who owns the +> mutex is to add something to your data structure. But you never do that. +> What you do is you add another map. So what you end up with a lot of +> suprooflo- su- sur- (waves hand) I can't say it. Uhh… extra. My advisor +> would be happy about that. Extra maps. diff --git a/docs/umich/w24_wrapup.md b/docs/umich/w24_wrapup.md new file mode 100644 index 0000000..386f374 --- /dev/null +++ b/docs/umich/w24_wrapup.md @@ -0,0 +1,194 @@ +# Winter 2024 wrapup + +2024-05-05 + +My second semester at UMich is just over, and I will recount major things +that happened. I will continuously update this blogpost. + +## Course reviews + +The biggest mistake that I made is that I elected three EECS courses, two +of which are extra heavy in workload. The rest are not trivial either. It +is impossible to cover all of them in one single blogpost, so I will split +them up into individual articles, listed below. + +- [EECS 482, Intro to OS](w24_482.md) +- [EECS 373, Intro to Embedded System Design](w24_373.md) +- [EECS 311, Analog Circuits](w24_311.md) +- Other courses WIP + +## Notable material gains + +- A 20 oz thermo flask, as a gift from the School of Information for + participating in the 10-week accessibility challenge last semester +- A bicycle, as described in [2024-04-05](../random/2024-04-05.md). Easily + the best investment this semester. +- A MIDI keyboard (AKAI MPK mini play) with which I made a few loops +- A MCR-themed zine I took at the Duderstadt gallery (it said "take one") +- Two CDs: Blurryface (2015) and Scaled And Icy (2021). + +More on the CDs: Blurryface is for myself, SAI is for a friend. I rode +downtown to four record stores in one day and bought them in the third and +fourth, respectively. The first store had SAI listed online, but they sold +out recently. The second store sold mostly vinyls. In both the third and +fourth, I took the last tøp CD in stock, so I can't really blame the +person who did it in the first store. + +The four stores are + +- Your Media Exchange, 319 S Main St +- Underground Sounds, 120 E Washington St +- Encore Records, 208 N 4th Ave +- Wazoo Records, 336 S State St + +All in downtown Ann Arbor. I've been to YMX last year, and I found some +rare items in the tøp vinyl section like the Location Sessions for record +day. I don't have a turntable, so I left them for people who do. This time +it's gone, along with many more. Whoever bought them has great taste. + +## Notable losses + +- My sanity over the 373 project + +## Notable expenditures + +- $39 for the MIDI keyboard (I outbid a swarm of ebay bots by one second) +- $512 for the Boston trip +- $90 for the bicycle +- $187 for a ticket to tøp's Clancy Tour (ffs fbr) + +## Notable experiences + +- I visited my friend in Boston over spring break. + - I saw The Museum of Fine Arts + - I saw The Museum of Bad Art + - By law of the excluded middle, I saw all art in existence + - I took a lecture on Chinese policy at Harvard + - I took a lecture on computer systems in the auditorium by the + so-called Banana Lounge at MIT + - I took the MBTA subway + - I saw a weird MIT exhibit with a bunch of glass, lamps, and wood + rescued from a bathhouse on fire + - I went to the MIT museum + - I talked with W1ATO over the W1XM repeater + - I went to the Harvard art museums is basically a tub for rich people + to dump their art in and as an excuse to exhibit stolen shit + +Quiz time! + +Which two of these paintings are from the Museum of Bad Art, and which two +are from the Harvard art museums? + +![Four paintings. 1: a tabby cat resting paws on a basket of fruit. 2: +a frowning lady drawn with crude lines. 3: a bald child with blurry facial +features. 4: a frowning lady with a rodent-like thing on her +head.](img/w24_wrapup/boston_art.jpg) + +<details markdown="1"> +<summary>Click to show the answer!</summary> +1, 4: Museum of Bad Art + +2, 3: Harvard art museums +</details> + +- I went to an iDKHOW show in Detroit, as described in + [2024-04-05](../random/2024-04-05.md). + +![Dallon Weekes singing and playing a red bass](img/w24_wrapup/dallon.jpg) + +- I watched the eclipse (98% partial in Ann Arbor) + +![Solar eclipse through eclipse lens; a crescent +glow](img/w24_wrapup/eclipse.jpg) + +For the folks without eclipse lenses, here's a reenactment: + +![Me holding a banana in the way of the sun](img/w24_wrapup/banana.jpg) + +- Except for two occasions, I participated in the W8UM/R Sunday net every + week, getting to know AC8TO, KE8BZJ, W8EMV, and KB6NU. Also I love our + net control WD4DSR. +- Attended a W8UM monthly meeting (though one hour late and didn't get any + pizza) and met AC8TO in person +- Saw a crime drama play called Trojan Horse. My friend played a role who + died for the most of the play +- Applied for IA of 370 and 373 next semester +- Cracked open a beer, which I just finished as I write this. The cashier + typed a "1" into the YYYY field on the auto checkout before realizing + (1) I was born 2003 and (2) aging is inevitable + +## Things unrelated to coursework that made my day worse + +I received the prize money for last semester's GERMAN 103 roleplay. +Instead of $200 per group, it was $200 per person. But it went straight to +my direct deposit and was split to two parts: + +- $172 to repay my "financial aid" +- $28 in federal tax + +It pisses me off that I worked so hard on a roleplay just for the prize +money to fund genocide. + +## Things unrelated to coursework that made my day better + +Last year I signed up for [Kristin Henry's Stickers and Stamps +project](https://kristinhenry.medium.com/stickers-and-stamps-a-bright-spot-in-2020-d3011afefa09). +It took months, but I finally received their letter in the mail. Enclosed +is a sticker, a handwritten postcard, and a stamped envelope for me to +return something in. So I handwrote a brief letter a few days later and +sent it to Kristin. + +It was the second time I physically put something in a US mailbox. The +first time was when I had to send form 8843 to the IRS to prove that I had +zero income last year. + +Cool find at the 373 lab: a vintage Fluke 77 multimeter. + +![Grey multimeter with automatic range +selection](img/w24_wrapup/fluke_77.jpg) + +## Albums discovered + +I spent the entire semester listening to Radiohead, all thanks to [a meme +video](https://www.youtube.com/watch?v=2KGRvIFrF3c). + +- _The Bends_ (1994) + - Favorite tracks: + - Fake Plastic Trees + - Street Spirit +- _OK Computer_ (1997) + - Paranoid Android + - Let Down +- _Kid A_ (2000) + - Everything In Its Right Place + - The National Anthem + - Idioteque +- _Amnesiac_ (2001) + - Pyramid Song + - Life In a Glasshouse +- _In Rainbows_ (2007) + - Weird Fishes + - Videotape + +And if you stretch the definition of "discover", I discovered _Clancy_ +(2024). + +## Interesting food in the dining hall + +Both of these were found in Bursley: + +- Blueberry pizza (pretty good actually) + +![Blueberry pizza](img/w24_wrapup/blueberry_pizza.jpg) + +- Gummyworm cake (it tastes exactly what it looks like) + +![A single gummy worm on top of oreo powder and +cream](img/w24_wrapup/gummy_worm_cake.jpg) + +## Funny car plates + +- NYANKO +- UWU 55 +- B1GENUF (on a mini) +- QING1SE (清一色) |