Devlog #1: From Macropad Inspiration to Standalone Hardware
💡 The Spark of Inspiration
Initially, I wanted to build a simple 4-button macropad with a volume knob using an Arduino Uno. But as I started thinking about what would actually be useful day-to-day, I pivoted the idea into a Physical Money Tracker—a desktop device that lets me quickly log financial transactions with the twist of a dial and the press of a single button.
I decided to challenge myself: Ax the PC and PyCharm entirely. I wanted a 100% standalone hardware device that works on raw micro-controller logic and remembers my balance even if I unplug it.
🛠️ Designing the Architecture
Instead of hiding data on a computer screen, I dug out a 5461AS 4-digit 7-segment display to show my data directly on my desk.
The control flow is clean and tactile:
-
The Dial (B10K Potentiometer): Acts as an amount selector. Turning it scrolls through transaction amounts (
-20,-10,0,+10,+20). - The Confirmation (Push Button): Acts as the “Enter” key to commit the transaction.
- The Feedback (Active Buzzer): Gives a tiny “click” sound when shifting between numbers, and a satisfying double-beep when a transaction successfully saves.
Because I wanted it to be standalone, I utilized the Arduino’s EEPROM memory so my balance data survives power loss.
🎛️ Mapping the Complex Matrix
The hardest part of the prototype was figuring out the routing for the 5461AS display. Without a dedicated driver chip, it requires 12 independent pin connections. I mapped out a custom configuration to keep the standard digital pins (D2 and D3) free for my tactile inputs:
-
Digits (Left to Right): Pins 12, 13, A1, A2 -> Connected to
D12,D13,A1,A2 -
Segments (A through G + DP): Connected to
D4,D5,D6,D7,D8,D9,D10,D11 -
Inputs: Potentiometer on
A0, Button onD2, Buzzer onD3
💻 Prototype Core Firmware Logic
I integrated the SevSeg library to handle the rapid background multiplexing needed to keep the display lit without flickering. Here is the core operational loop of the system:
void loop() {
int potValue = analogRead(POT_PIN);
int potZone = potValue / 205;
switch(potZone) {
case 0: selectedAction = -20; break;
case 1: selectedAction = -10; break;
case 2: selectedAction = 0; break;
case 3: selectedAction = 10; break;
case 4: selectedAction = 20; break;
}
// Handle Button Press and Save to EEPROM
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW && lastButtonState == HIGH) {
currentBalance += selectedAction;
saveBalance(currentBalance); // EEPROM storage
sevSeg.blank();
tone(BUZZER_PIN, 2700); delay(80); noTone(BUZZER_PIN);
delay(40);
tone(BUZZER_PIN, 2700); delay(80); noTone(BUZZER_PIN);
}
lastButtonState = buttonState;
if (buttonState == HIGH) {
sevSeg.setNumber(selectedAction);
} else {
sevSeg.setNumber(currentBalance);
}
sevSeg.refreshDisplay();
}