1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
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.
|