summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Yin <fkfd@fkfd.me>2024-02-14 16:28:47 -0500
committerFrederick Yin <fkfd@fkfd.me>2024-02-14 16:28:47 -0500
commit5d0b983893997402949961b46875b19a8e9a41cc (patch)
tree199fa81c88bedd88cacc1aa48ffbf8f3ce61f935
parentab4ceddf5dd0b62fb8b8c7c009f402a96dee0e33 (diff)
New post: byseekel_scrapped
The decision not to index it is intentional
-rw-r--r--docs/projects/byseekel.md4
-rw-r--r--docs/projects/byseekel_scrapped.md441
2 files changed, 445 insertions, 0 deletions
diff --git a/docs/projects/byseekel.md b/docs/projects/byseekel.md
index a0e96c9..ff1f73f 100644
--- a/docs/projects/byseekel.md
+++ b/docs/projects/byseekel.md
@@ -205,6 +205,10 @@ In the end, they grew so complicated I had to throw them away.
![braking lights, reed, ctrl, LCD, brake and the control panel are crossed
out](img/byseekel/feature_creep_removal.png)
+2024-02-14 update: There was [another version of this blogpost that
+I scrapped and rewrote](byseekel_scrapped.md), where you may find some of
+these dead ideas and bad puns.
+
### Speedometer & odometer
My uni has a required 80km of jogging per semester, tracked by GPS to
diff --git a/docs/projects/byseekel_scrapped.md b/docs/projects/byseekel_scrapped.md
new file mode 100644
index 0000000..1c0dbbf
--- /dev/null
+++ b/docs/projects/byseekel_scrapped.md
@@ -0,0 +1,441 @@
+# Byseekel (scrapped version)
+
+> Note: This is the scrapped version of [Byseekel](byseekel.md). I began
+> writing this article in early 2022, until I abandoned it 2022-05-02. The
+> next year I revived and finished the project, but killed many features.
+> That was when I decided to rewrite this blogpost from scratch, with less
+> groundless optimism you'd find in this scrapped version.
+
+> Nevertheless, for archival reasons, I am publishing the scrapped version
+> on 2024-02-14. This article is not finished and will not be updated.
+> Please disregard any sentence that suggests otherwise.
+
+> I deleted the images a long time ago, so I put in the alt text instead.
+
+> Article begins here.
+
+Freddie Mercury famously sang:
+
+> I want to ride my bicycle I want to ride my bike
+> I want to ride my bicycle I want to ride it where I like
+
+I, too, own a bicycle, but in terms of performance and condition it is
+like crap. I certainly wouldn't take riding my bicycle as much of
+a pleasure as Mercury did. This makes me ask myself a question: What do
+I need to make a bike trip more enjoyable, or just less painful?
+
+A [cyclocomputer](https://en.wikipedia.org/wiki/Cyclocomputer).
+
+Image: Cateye cyclocomputer mounted to a bicycle handlebar.
+
+Image credit: Wikipedia user
+[Mnisawlpsa](https://commons.wikimedia.org/wiki/User:Mnisawlpsa).
+
+Despite its stupid name (cyclo? computer? smh) it's kinda useful. It keeps
+track of the speed and mileage of your bike, and displays them on
+a screen. I do know one application where it definitely fits, and that is
+cheating the 80-kilometers-of-jogging-per-semester mandate from my school
+office.
+
+Every (able) undergrad in my uni has to accumulate a certain jogging
+mileage by the end of each semester. For boys, the number is 80
+kilometers. To track your movement you turn on your phone's GPS and start
+jogging. But the loophole is, it can't actually tell if you're jogging, as
+long as you keep your speed within 3-9 minutes/km. Experiments show I am
+able to maintain a steady 3-5 min/km on a bike and trick the system into
+believing I'm legitimately jogging. But even so, I have to pull out my
+phone mid-journey — a quite dangerous act, even when no one was around
+— to make sure I'm not going too fast. It would be helpful if I had
+a device to check that for me and warn me if it exceeds that range.
+
+Guess what, it'd be extra helpful if it could tell me how far I've cycled.
+It'd also be cool if I could integrate this with my previous
+semi-successful project, [Bikeblinkers](../bikeblinkers). What if besides
+blinkers, it also had a braking light. Hey, since looking for my bike
+among 200 others in front of the gate is such a pain, how about something
+that would tell me where it is?
+
+I should totally make a bucket list of features to implement:
+
+- speedometer
+- odometer
+- blinkers
+- hazard light
+- braking indicator
+- remote-activated buzzer
+
+And no, this is so much more than a cyclocomputer. As a tribute to Freddie
+Mercury, I'm going to name my project after how he enunciates the word
+"bicycle".
+
+Note: this blogpost is continuously being updated.
+
+## Hardware
+
+### MCU (spoiler: it's AVR)
+
+The project at hand really seems to dwarf [Bikeblinkers](../bikeblinkers)
+in terms of complexity, and apparently a single 555 IC simply won't do,
+and an MCU is necessary.
+
+Which MCU? That is one of the most consequential decisions to make. Up to
+this point I had a really limited tech stack, because before this one all
+I knew was Arduino (in this blogpost I treat the Arduino as a distinct
+"MCU", despite its real MCU being ATmega328P), and I hadn't really done
+any project that (a) has an MCU, and (b) runs more than one meter away
+from a computer and a power source that draws power from the mains.
+
+"How about Arduino," I thought. However, upon close inspection, the
+Arduino isn't all cake.
+
+- Many Arduino libraries are bloat and inefficient (I'm not judging
+ though)
+- Arduino IDE v1 is a huge pain to use (Yes I am judging here)
+- The Arduino has a 3.3V regulator which isn't useful for this project but
+ consumes quite a substantial chunk of power
+
+That said, I am really hoping there was some alternative. What I want is
+a bare-bones version of Arduino, where I get the freedom to do whatever
+I want, but still somehow match the Arduino's capabilities.
+
+I have a few ATmega328P's lying around, so let's try them.
+
+🛒 BOM += ATmega328P
+
+Admittedly, you _can_ embed AVR C/C++ snippets in your `.ino` or
+completely write your sketch with it, and if done right it's possible to
+compile and download an Arduino sketch onto your average ATmega328P, but
+what's the fun? I'm going to ditch Arduino completely here.
+
+I'm going with avr-gcc and avr-libc, so that I won't touch assembly and as
+a bonus practice C which I had been learning for 2/3 of a semester.
+
+I fetched a copy of datasheet for the ATmega328P and began reading. The
+most important information as of now is
+
+- Pinout (GPIO and SPI)
+- IO registers (`PORTB`, `DDRB`, etc.)
+
+I bought a [USBASP](https://www.fischl.de/usbasp/) to download my code
+onto the chip. Well, in fact it's not the code I'm downloading, it's the
+hex file obtained by compiling the code, linking the libraries, generating
+an elf, then summoning Satan.
+
+There are three limitations on the specs one ought to care about when
+designing software for an AVR chip:
+
+- Flash size
+- SRAM size
+- Clock frequency
+
+The 328P has 32KB flash, 2KB SRAM and a maximum frequency of 20MHz, but of
+course we're not using all that much. Of the three what worries me most is
+RAM, because after 2/3 of a semester of C I know how hard keeping track of
+memory can be, and for some reason my programs easily ate up megabytes on
+the OJ. Although 2KB sounds extremely limited, fortunately we don't need
+fancy algorithms here.
+
+So far, all I needed was the I/O functionality, and the most basic
+conditionals and loops C has to offer. By lumping up stuff like
+
+```c
+#include <avr/io.h>
+#include <util/delay.h>
+int main(void) {
+ DDRB |= _BV(PB5); // set pin direction of PB5 to output
+ while (1) {
+ PORTB ^= _BV(PB5); // toggle PB5
+ _delay_ms(500);
+ }
+}
+```
+
+I was able to blink an LED.
+
+Image: An illuminating LED driven by a DIP-28 ATmega328P on a breadboard
+
+This was all very basic, equivalent to what you would do with `pinMode`
+and `digitalWrite` on an Arduino. Although I was eager to write some
+_real_ code, I should figure out how my MCU would sense and react to the
+physical world.
+
+### Input Peripherals
+
+#### Learn to reed
+
+To calculate the speed the bicycle is traveling at, we need to count the
+number of revolutions. I initially had two ideas:
+
+- Optical: reflective material on the spokes, IR LED and phototransistor
+ on the fork;
+- Magnetic: reed switch on the fork and a permanent magnet on the spokes.
+
+The optical solution in theory works like this:
+
+Image: Diagram showing the location and schematics of the optical sensor
+
+However, the weaknesses are pretty obvious.
+
+- Requires power source
+- Requires directional alignment
+- Requires a minimum of three wires (VCC, GND, output)
+- Aluminum foil on a bicycle wheel looks silly
+- Electrical noise
+
+Moreover, the industrial standard for cyclocomputers is reed switches.
+
+Image: Wired reed switch sensor with spoke mounted magnet.
+
+Image credit: Wikipedia user
+[AndrewDressel](https://en.wikipedia.org/wiki/User:AndrewDressel).
+
+They should be installed on the rear wheel, because rotations of the rear
+wheel are more representative of the real mileage.
+
+🛒 BOM += reed switch, permanent magnet
+
+#### Turning big
+
+In Bikeblinkers my control for the blinker circuit was a tiny SP3T toggle
+switch. It's a bit too small, and it was the source of two design errors
+in my rev. 1 PCB (look I gotta find someone else to blame okay?)
+
+Image: A SP3T toggle switch mounted on a PCB
+
+🛒 BOM += bigger SP3T switch
+
+I spent a fortune buying one, but it was worth it. Cue the industrial
+switch!
+
+Image: Industrial SP3T switch in metal and plastic casing. It is thrown to the right.
+
+(ruler in centimeters)
+
+This is all good and such, but one problem is it's pretty likely you'll go
+all the way to the opposite direction when your intention is to throw it
+back to neutral. No countermeasure so far.
+
+In February 2022, I came up with an alternative. This is one of those
+blinker switches they use on e-bikes. It has three terminals: left, right,
+and common. Flick it to the left, and left connects to common. Flick it to
+the right, and right does so. Push the stalk down to disconnect all
+terminals. Two models are sold: one that allows three terminals to be
+simultaneously connected, and one that doesn't. I picked the former, as
+hazard lights are just left and right blinkers on at the same time.
+
+🛒 BOM += e-bike blinker switches
+
+Image: A pair of e-bike blinker switches. One of them has its three copper
+terminals exposed.
+#### Brake it apart
+
+The brake is a little trickier and as of the time of writing I have one
+idea but have absolutely no idea how it would work out in the physical
+world.
+
+Image: Diagram of the location and schematics of the brake switches
+
+This design taps into movements of the brake handle but not anywhere
+further in the braking mechanism, e.g. brake pads. This is because brakes
+are a key part to bike safety, and it's stupid to tamper it just for
+a braking indicator.
+
+It comprises of four metal contacts: two on the left, two on the right. Of
+each two, one is on the hinge and remains stationary relative to the
+bicycle, but the other is somewhere on the moving part, the handle. They
+are normally closed, forming an electrical connection. When you pull back
+the handle to engage the brake though, they are forced apart, breaking the
+continuity. The two pairs are wired in series and act like a single
+switch. When it is open, it means at least one brake is engaged, which is
+good enough since we don't care which.
+
+Sure, ugly hack, but having read Arduino forum threads like
+[this](https://forum.arduino.cc/t/interfacing-with-a-bicycle-sensing-braking-solved/72661)
+it actually isn't _the_ ugliest one, while in my reach in terms of
+afforability.
+
+Problems:
+
+- I can't think of a way to install them other than superglue
+- Rainwater can interfere with the connection, for example shorting a pair
+ of contacts that are supposed to be open
+- The location of contacts have to be super precise
+- Exposed wires are a potential cosmetic imperfection (shut up your bike
+ isn't beautiful anyway)
+
+🛒 BOM += tiny metal contact plates? is that a thing?
+
+📋 TODO: install this to prove I'm not an idiot
+
+#### WhereTheFuck™
+
+WhereTheFuck™ (WTF) is a bleeding-edge, innovative and disruptive
+technology which augments and accelerates your vehicle retrieving
+experience with audiovisual cues.
+
+OK, it's just a regular bike finder. The components are an RF receiver and
+a transmitter at 433MHz, and a LED-beeper combo, which I will show later.
+
+🛒 BOM += RF TX/RX kit
+
+I am not a radio expert, so what I bought is this kit. It's a cute
+[OOK](https://en.wikipedia.org/wiki/On%E2%80%93off_keying) RF receiver
+module capable of detecting four programmable signals, which happens to be
+the number of keys the transmitter has. The transmitter is just your
+average garage door opener.
+
+Image: Left to right: four-key RF transmitter with antenna extended, RF
+receiver as a small yellow PCB with 7 bent pin headers.
+
+Looks like I can attach an antenna to the RX module too, so here's a bunch
+of them I ordered a few weeks later.
+
+Image: 10 RF antennae in plastic packaging. They look like coils with tails and
+are made of copper.
+
+📋 TODO: install, find out how effective it is
+
+### Output Peripherals
+
+#### Crystal clear
+
+Sure, we're able to calculate our speed and mileage now, but of course we
+will need to display it somehow. For this purpose we will use an LCD.
+I have one lying around but it's one of those expensive 12864 models,
+which is best for complex graphics and a complete overkill for showing
+a bunch of numbers. So I opted for a downgrade, i.e. 1602, which can only
+draw characters only (of course, there are hacks which let you draw custom
+pixmaps. we won't touch them here)
+
+🛒 BOM += 1602 LCD
+
+Image: An LCD with soldered pins
+
+#### Blinkers, again (also stop lamp)
+
+On one hand, I could reuse the blinkers for my previous project,
+Bikeblinkers. They are working perfectly fine; they're just four sets of
+yellow LEDs. I even spent hours designing a 3D printed case, which in the
+end was never gestated into the physical world, but I feel it would be
+a pity if no one saw it, so here's a picture.
+
+Image: FreeCAD model of an enclosure for blinkers and a stop lamp
+
+However I want something big. No, not physically, but it's going to amaze
+everyone.
+
+🛒 BOM += LED strips
+
+Look at these bright boys!
+
+Image: 1 meter long red LED strip resting on my lap. It's drawing 654mA at
+12.0V from my DC power supply and hella bright
+
+I bought a red strip for the stop lamp and a yellow one for blinkers, one
+meter each which is a plenty amount. Given I cut them in appropriate
+lengths, they don't draw much more power than the discrete LEDs do.
+
+#### WhereTheFuck™
+
+My idea for WhereTheFuck™ is, I press a button on my transmitter, and
+something on my bicycle flashes and/or makes a loud noise. That is
+basically my patent claim. How novel.
+
+I bought this thingie, which is basically two LEDs and a (really loud)
+buzzer, and it fits in a 22mm hole designed for industrial pushbuttons.
+When fed 12V it happily beeps on and off thanks to its internal RC
+circuitry (it's visible from the holes).
+
+Image: Buzzer. It's a black plastic cylinder with a transluscent red cap.
+
+Image: The red lid is removed to reveal two LEDs and a buzzer.
+
+## Software
+
+### Oh boy, avr-gcc
+
+That's right y'all, it's official: I wrote C for AVR. Embedded
+programming. One more line on my resume I guess?
+
+Oh, you're asking me if it's enjoyable? You better ask yourself: is it
+really possible to enjoy C? Is it in all plausibility an attainable
+outcome that I, a mere mortal of flesh and soul, would have the `__asm__
+__volatile__` in my command, or possess enough power to conquer the army
+of CMOS logic gates? No. To write C one must suffer. To control the
+silicon, one must first wrestle it, then tame it.
+
+#### State and global variables
+
+Global variables are gross, but atop 2,048 bytes of memory there are no
+rules. I am representing global state in a pile of global variables. One
+of them is called `state`. At the time of writing it holds 5 boolean
+states in bits [6..2] (imagine the memory saved compared to 5 ints) and
+the two least significant bits represent a finite state of four.
+
+```c
+uint8_t state = 0;
+```
+
+As you might have expected, reading and writing on `state` is a pain. But
+AVR C is full of bitwise stuff anyways, so it doesn't really matter if you
+define macros wisely.
+
+In my `main.h` I defined the following:
+
+```c
+#define BRAKE_BIT _BV(6)
+#define BLINKER_L_BIT _BV(5)
+#define BLINKER_R_BIT _BV(4)
+// ...
+```
+
+(`_BV(x)` is macro for `1 << x` which is used to create a bitmask, with BV
+standing for Bit Value)
+
+To test a bit, say `BRAKE_BIT`, I need to do:
+
+```c
+if (state & BRAKE_BIT) { /*...*/ }
+```
+
+And to alter it:
+
+```c
+state |= BRAKE_BIT; // set to one
+state &= ~BRAKE_BIT; // set to zero
+```
+
+#### LCD
+
+#### Stop lamp
+
+Despite the hardware implementation being unproven, this is one of the
+easiest features in software. There are only two possibilities:
+
+- braking, and
+- not braking
+
+If it is the former, we turn on the red stop lamp. Otherwise, turn it off.
+Here's the code:
+
+```c
+void braking(void) {
+ if (PIND & BRAKES && !(state & BRAKE_BIT)) {
+ state |= BRAKE_BIT;
+ PORTC |= STOPLAMP;
+ lcd_print("[BR]", 0x19);
+ } else if (!(PIND & BRAKES) && state & BRAKE_BIT) {
+ state &= ~BRAKE_BIT;
+ PORTC &= ~STOPLAMP;
+ lcd_clear(0x19, 4);
+ }
+}
+```
+
+...where `STOPLAMP` is a macro for `_BV(PC1)`, the assigned pin.
+
+#### Blinker
+
+#### Sleep mode
+
+#### WhereTheFuck™