DESK BUDDY: a Multi-Function IoT Desk Companion With Games
by nilutpolkashyap in Circuits > Sensors
243 Views, 1 Favorites, 0 Comments
DESK BUDDY: a Multi-Function IoT Desk Companion With Games
Have you ever wanted a tiny desk gadget that tells time, shows weather, runs a Pomodoro timer, displays animated robot eyes, AND lets you play 5 retro games — all on a screen smaller than a postage stamp?
Meet Desk Buddy — a multi-function desk companion built with an ESP8266, a 0.96" OLED display, a motion sensor, two touch buttons, and a buzzer.
Here's what it does:
- Displays real-time clock and date (synced via WiFi)
- Shows live weather for your city
- Runs a Pomodoro timer you control by flipping the device
- Shows animated robot eyes that follow your hand and react to touch and shaking
- Plays 5 games: Chrome Dino, Space Invaders, Flappy Bird, Tilt Maze, and Pong
All 9 modes are cycled with a single touch button. Games are controlled with a second touch button and by tilting the device. The whole thing runs on a single Arduino sketch — no app, no Bluetooth, no cloud dependency beyond a quick weather fetch.
Total cost: around $8-15 in parts. No soldering required — it's all breadboard-friendly.
NOTE: My 3D printed enclosure didn't arrive on time, so I had to improvise with paperboard for the enclosure.
Let's build it.
Supplies
MATERIALS:
- 1x ESP8266 NodeMCU development board
- 1x SSD1306 OLED display, 0.96", 128x64 pixels, I2C interface
- 1x MPU6050 6-axis IMU breakout board (accelerometer + gyroscope)
- 2x TTP223 capacitive touch sensor modules
- 1x Active buzzer module (3.3V compatible)
- 1x 5 x 7 cm Universal PCB Prototype Board (perfboard)
- 1x 3.7V 500mAh LiPo battery
- 1x TP4056 lithium battery charging module (micro USB input)
- 1x MT3608 DC-DC Step Up Boost Converter module (3.7V to 5V)
- Hookup wire / jumper wires for soldering connections
- Pin headers (optional, for socketing the ESP8266)
- 1x Micro USB cable (for charging and programming)
TOOLS:
- Soldering iron and solder
- Wire strippers / cutters
- Computer with Arduino IDE installed
- USB port
SOFTWARE (install via Arduino Library Manager):
- Adafruit SSD1306
- Adafruit GFX Library
- Adafruit MPU6050
- Adafruit Unified Sensor
- NTPClient (by Fabrice Weinberg)
- ArduinoJson (v6, by Benoit Blanchon)
- FluxGarage RoboEyes
- ESP8266 board package (install via Boards Manager)
ACCOUNTS:
- OpenWeatherMap account (free tier) — get your API key at https://openweathermap.org/api
NOTE: All components use 3.3V logic, which is what the ESP8266 outputs. No level shifters needed.
UNDERSTAND THE COMPONENTS
Before wiring, let's understand what each part does:
ESP8266 NodeMCU:
The brain. A WiFi-enabled microcontroller that handles everything — reading sensors, driving the display, connecting to the internet, and running game logic. The NodeMCU variant is beginner-friendly with built-in USB programming.
SSD1306 OLED Display (128x64, I2C):
A tiny monochrome screen where each pixel is self-lit. Sharp contrast, wide viewing angles, and it only needs 2 data wires (SDA and SCL) plus power. Address: 0x3C.
MPU6050 IMU:
A 6-axis motion sensor — 3 axes of acceleration and 3 axes of rotation. We use the accelerometer to detect which way the device is tilted (for games and timer) and the gyroscope to detect shaking (for robot eye reactions). Also connects via I2C, sharing the bus with the OLED. Address: 0x68.
TTP223 Touch Sensors:
Capacitive touch buttons. Touch them and they output HIGH. One button (D6) cycles through the 9 modes. The other (D5) is the action button — jump, shoot, flap, serve, or trigger expressions depending on what mode you're in.
Active Buzzer:
Makes sound when given voltage. Unlike a passive buzzer, it has a built-in oscillator — you just toggle it on and off. We create different feedback patterns by varying the on/off timing.
TIP: If you've never used an ESP8266 before, first upload the basic "Blink" example to make sure your board and Arduino IDE are set up correctly.
WIRE EVERYTHING UP
Connect everything to the ESP8266 NodeMCU as follows:
OLED Display:
VCC --> 3.3V
GND --> GND
SDA --> D2
SCL --> D1
MPU6050 (shares I2C bus with OLED):
VCC --> 3.3V
GND --> GND
SDA --> D2
SCL --> D1
Left Touch Sensor (Mode cycle):
VCC --> 3.3V
GND --> GND
SIG --> D6
Right Touch Sensor (Action button):
VCC --> 3.3V
GND --> GND
SIG --> D5
Active Buzzer:
+ --> D7
- --> GND
NOTE: The OLED and MPU6050 share the same SDA and SCL wires. This works because I2C supports multiple devices on one bus — they have different addresses (0x3C and 0x68).
WARNING: Double-check that you're connecting to 3.3V, not 5V. The ESP8266 GPIO pins are not 5V tolerant.
TIP: Place the MPU6050 flat on the breadboard, with the chip facing up. The orientation matters for the timer and game controls. In this project, the +X axis points out through the OLED screen, and the +Y axis points to the left.
CONFIGURE THE SOFTWARE
1. Setup ESP8266 boards in Arduino IDE by following this article Installing ESP8266 NodeMCU Board in Arduino IDE 2 by RandomNerdTutorials
2. Install all required libraries:
- Go to Sketch > Include Library > Manage Libraries
- Search and install each one listed in the Supplies step
3. Open the sketch file (desk-buddy.ino)
4. Edit the configuration at the top of the file:
WiFi credentials:
const char* WIFI_SSID = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
Weather API:
const char* OWM_API_KEY = "YOUR_API_KEY";
const float OWM_LAT = xx.xx; // Your latitude
const float OWM_LON = xx.xx; // Your longitude
const char* OWM_CITY = "YOUR_CITY_NAME"; // Your city name
Timezone:
const long UTC_OFFSET_SEC = 19800; // Your UTC offset in seconds
// Examples: IST +5:30 = 19800, UTC = 0, EST -5 = -18000,
// PST -8 = -28800, CET +1 = 3600
5. Select your board: Tools > Board > ESP8266 Boards > NodeMCU 1.0
6. Select the correct COM port: Tools > Port
TIP: To find your city's latitude and longitude, search "[your city] coordinates" on Google.
TIP: Get your free OpenWeatherMap API key by signing up at openweathermap.org. The free tier allows 1000 calls/day — this project uses about 48 calls/day (once every 30 minutes).
UPLOAD AND CALIBRATE
1. Click Upload in Arduino IDE. The sketch is about 2000 lines, so compilation takes a minute.
2. Once uploaded, the device boots with a "Desk Buddy" welcome screen and a startup beep.
3. IMPORTANT — Calibration:
The device will show "Calibrating... Keep sensor flat and still!"
Place it on a flat, stable surface and DON'T TOUCH IT for about 1 second.
During calibration, the MPU6050 takes 200 readings and calculates offset values. This removes per-unit sensor bias that would otherwise make readings inconsistent. The offsets are printed to Serial Monitor if you want to verify.
4. After calibration, the clock screen appears. If WiFi is available, it will sync time and weather in the background within a few seconds.
NOTE: If you see "Waiting for sync..." on the clock, WiFi hasn't connected yet. Give it up to 10 seconds. If it still fails, check your WiFi credentials. The timer and games work without WiFi.
TIP: Open Serial Monitor (115200 baud) to see debug messages — WiFi status, calibration offsets, orientation changes, and mode switches.
MODE 1 — CLOCK
The default mode. After boot, the OLED shows:
- Day of week and date (e.g., "Tue, 31 Mar")
- Time in large HH:MM format
- Your city name at the bottom
The time comes from NTP (Network Time Protocol) servers, adjusted for your timezone. After the initial sync, the NTPClient library keeps time locally using the ESP8266's internal clock — so time stays accurate even with WiFi off.
How WiFi works in the background:
- On boot, WiFi connects silently while the clock is already displayed
- Once connected (up to 10 seconds), it syncs time and fetches weather
- WiFi turns OFF to save power
- Every 30 minutes, it briefly reconnects, refreshes data, and turns off again
- This all happens without interrupting whatever mode you're using
Tap the Right Touch (D5 touch sensor) to move to the next mode (Weather).
MODE 2 — WEATHER
Shows current weather for your configured city:
- Weather condition in large text (e.g., "Clouds", "Rain", "Clear")
- Temperature in Celsius
- Feels-like temperature
- Humidity percentage
The data comes from OpenWeatherMap's OneCall 3.0 API. The ESP8266 makes an HTTPS request (using BearSSL), receives a JSON response, and parses it with the ArduinoJson library.
Weather updates every 30 minutes automatically — the same WiFi cycle that updates the clock also refreshes weather.
MODE 3 — POMODORO TIMER
The Pomodoro timer is controlled entirely by the orientation of the device. No buttons needed — just flip it:
- Flat (screen up or down) --> Timer Stopped
- Standing on end (+Z up) --> 30 minute countdown
- Standing on end (-Z up) --> 5 minute countdown
- On side (+Y up) --> 45 minute countdown
- On side (-Y up) --> 60 minute countdown
The MPU6050 detects which axis is aligned with gravity. A 10-sample moving average filter smooths out jitter, and a threshold of 6 m/s² ensures only deliberate orientation changes trigger a new timer.
When a timer starts, you hear a double beep and the countdown begins in large MM:SS format. The display rotates to match the device orientation so text is always readable.
When the timer hits zero:
- 5 rapid beeps sound as an alarm
- The screen shows "TIME'S UP!"
- Flip to the flat position to stop
TIP: This is great for the Pomodoro technique — use 30 minutes for work, 5 minutes for breaks. Just flip the device when the alarm goes off.
MODE 4 — ROBOT EYES
An animated robot face powered by the FluxGarage RoboEyes library. The eyes blink, look around, and react to your interactions.
Tilt the device:
The eyes follow! The accelerometer maps your tilt to 8 directions (N, NE, E, SE, S, SW, W, NW) plus center when flat. It feels like the device is watching you.
Tap Right Touch:
The eyes randomly go either angry (with a heavy buzzer tone) or confused with shaking (with stuttery beeps).
Shake the device:
The gyroscope detects the shake. The eyes go confused and angry with a surprise beep. When you stop shaking, they calm back to happy.
Leave it alone for 20 seconds:
The eyes get tired and blink slowly — like they're falling asleep. Any interaction wakes them back up.
The RoboEyes library handles smooth 60fps animation with tweened transitions. Auto-blinking and random idle eye movements are always active.
MODE 5 — CHROME DINO GAME
A recreation of Chrome's offline dinosaur runner game.
How to play:
- The dino runs automatically
- Tap D5 to jump over cacti
- Score goes up as cacti pass behind you
- Speed increases gradually — gets harder over time
The dino has a body, head, eye, tail, and animated running legs that alternate between two poses. Cacti spawn with random widths and heights, and some wider ones get arm details.
On collision, you hear a two-tone descending beep and see your score and high score.
Tap Right touch to restart.
MODE 6 — SPACE INVADERS
Classic Space Invaders with tilt controls.
How to play:
- Tilt the device left/right to move your ship
- Tap Right Touch to shoot (up to 3 bullets on screen)
- Destroy all 24 aliens to win
- Don't get hit by enemy bullets!
The aliens are arranged in 3 rows of 8, each row with a unique pixel art design. They move side-to-side as a group, dropping down when they hit a screen edge. As you destroy aliens, the survivors speed up.
Enemies shoot back every 1.5 seconds from a random column. If an alien reaches the bottom or a bullet hits your ship, game over.
Score: 10 points per alien. Win by clearing all 24.
MODE 7 — TILT MAZE
A procedurally generated maze you navigate by tilting.
How to play:
- Tilt the device to roll a ball through the maze
- Get from the top-left corner to the bottom-right goal (hollow square)
- Tap Right Touch anytime to generate a fresh maze
Each maze is unique, generated using a randomized depth-first search algorithm on a 16x8 grid. This guarantees exactly one path between any two cells — no shortcuts, no dead-end traps you can't escape from.
The ball has real physics: acceleration from tilt, friction that slows it down, momentum that carries it, and wall collision that stops it cleanly. It feels like rolling a marble on a board.
On solving, you see your completion time and a level counter. Tap Right Touch for the next maze.
TIP: Gentle tilts give more control. The ball has momentum, so sudden movements will send it crashing into walls.
MODE 8 — FLAPPY BIRD
The classic Flappy Bird — simple controls, addictive gameplay.
How to play:
- Tap Right Touch to flap — each tap gives an upward boost
- Gravity constantly pulls the bird down
- Navigate through gaps in the pipes
The bird has a body, eye, beak, and an animated wing that points up when rising and down when falling. Pipes have the classic lip/ledge detail at the gap edges.
Three pipes cycle on screen with randomized gap positions. The gap is 22 pixels — tight but fair. Speed is constant, so difficulty comes from gap placement and timing.
A title screen shows "Flappy Bird" with a preview bird before you start. Tap Right Touch to begin.
MODE 9 — PONG
Classic Pong against a CPU opponent.
How to play:
- Tilt up/down to move your paddle (left side)
- Tap Right Touch to serve the ball
- First to 5 points wins
The CPU opponent tracks the ball when it's heading toward them, but drifts lazily toward center when the ball is coming your way. This makes the CPU beatable with well-placed shots.
The ball speeds up 5% on every paddle hit. Where the ball hits your paddle determines the angle — edge hits give steep angles, center hits go straight. This gives you spin control for strategic play.
The classic look: center dashed line, large score numbers, and distinct beeps for bounces and scoring.
CONTROLS QUICK REFERENCE
Left touch - Mode button (D6 TOUCH sensor):
Tap to cycle through all 9 modes:
Clock > Weather > Timer > Eyes > Dino > Invaders > Maze > Flappy > Pong > Clock
Right touch - Action button (D5 TOUCH sensor):
- Robot Eyes: Trigger angry/confused expression
- Chrome Dino: Jump
- Space Invaders: Shoot
- Tilt Maze: Reset / new maze
- Flappy Bird: Flap
- Pong: Serve ball
TILT (IMU):
- Robot Eyes: Eyes follow tilt direction
- Space Invaders: Move ship left/right
- Tilt Maze: Roll ball through maze
- Pong: Move paddle up/down
SHAKE:
Robot Eyes: Confused + angry reaction
FLIP:
Timer mode: Set timer duration by face orientation
POSSIBLE IMPROVEMENTS AND FINAL THOUGHTS
Ideas for version 2:
- Store high scores in EEPROM so they survive power cycles
- Add more games (Snake, Breakout, Reaction Timer)
- Use a passive buzzer for actual melodies and different tones
- 3D print an enclosure with cutouts for the OLED and touch sensors
- Add a power switch between the TP4056 and MT3608 to fully cut power when not in use
- Upgrade to a larger LiPo (1000mAh+) for all-day battery life
What started as "display some text on a screen" turned into a 9-mode desk companion with a real-time clock, weather, a productivity timer, an animated robot face, and 5 playable games — all running on a $3 microcontroller with a $2 screen.
The whole project is a single Arduino sketch, about 2000 lines of code. It's soldered onto a compact 5x7cm perfboard, powered by a rechargeable LiPo battery with USB charging — truly portable. No custom PCB design, no app, no cloud dependency. Just off-the-shelf modules, a soldering iron, and components that cost less than a lunch.
Build it, put it on your desk, and enjoy your new Desk Buddy.
CODE
The complete source code and README are available in the GitHub repository nilutpolkashyap/desk-buddy