Guess the Weight is a recreational device that uses a digital scale to create an interactive and fun experience. The game features two distinct modes:
An object is placed on the scale and weighed. The player must then try to guess the weight by inputting a value as close as possible to the actual measurement.
An object is weighed and its weight is stored. The player is then given several smaller objects of known weights. The goal is to recreate the original weight by placing a combination of these objects on the scale.
Both modes encourage observation, estimation, and logical thinking while offering a fun and hands-on interaction with real-world measurements.
A brief overview of our project:
The “Guess The Weight” system consists of the following main modules:
Interaction Description:
# Components List
'Interface:
' Digital serial communication (2 wires - DT and SCK)
'Connections:
'
* VCC → 5V Arduino
* GND → GND Arduino
* DT → D2 (digital input)
* SCK → D3 (digital output)
'Voltage:
' 5V logic
Note:
No level shifting needed; both HX711 and Mega operate at 5V logic
'Interface:
' PWM or simple digital ON/OFF signal
'Connections:
'
* Pin + (red) → D9 (PWM digital pin)
* Pin - (black) → GND
'Voltage:
' 5V
Note:
Directly compatible with Arduino Mega digital outputs
'Interface:
' I2C (2 wires)
'Connections:
'
* VCC → 5V
* GND → GND
* SCL → Pin 21 (SCL on Mega)
* SDA → Pin 20 (SDA on Mega)
'Voltage:
' 3.3V–5V
Note:
No conversion needed; internal protection resistors present
'Interface:
' Digital, column and row scanning (8 pins)
'Connections:
'
* 8 wires connected to digital pins D22–D29
'Voltage:
' 5V
Note:
' Passive mechanical switches using internal pull-up resistors
'Powers:
'
* OLED Display
* Buzzer
* HX711
'Power Source:
' USB AM-BM connected to Arduino Mega
Note:
' 5V and GND lines distributed on both sides of breadboard
Both the display and the buzzer works, the dislpay can be seen in the picture, as for the buzzer, it was tested using a script.
The firmware was developed using 'Visual Studio Code
' with the 'PlatformIO
' extension. This setup offers efficient dependency management, integrated serial monitor support, and cross-platform compilation.
The following third-party libraries were used:
'Adafruit_SSD1306
' – controls the OLED display via I2C.
'Adafruit_GFX
' – provides graphics primitives for the display.
'HX711
' – interfaces with the load cell and reads weight data.
'Keypad
' – handles input from the 4×3 matrix keypad.
These libraries simplify hardware communication and allow for clean, readable application logic.
A simple 'menu system
' navigated using the keypad, allowing selection between two modes:
'Guess the Weight
' – user estimates an object’s weight and inputs the guess via keypad.
'Match the Weight
' – user adds objects to match a previously recorded weight.
The 'buzzer
' plays dynamic tones in “Match the Weight” mode. The rhythm (tone interval) increases as the current weight gets closer to the target.
A 'state-driven structure
' manages transitions between menu, gameplay, and results.
The OLED screen provides 'real-time feedback
', such as instructions, results, and animated weight indicators.
drawMenu()
– displays the main menu with selection cursor.
startGuessTheWeight()
– logic for guessing the weight of an object.
startMatchTheWeight()
– records a target weight, provides animation and rhythm-based buzzer feedback as the player matches it.
playMatchingTones(currentWeight, targetWeight)
– adjusts buzzer rhythm according to proximity to target.
drawWeightAnimation(animY)
– animates a simple visual indicator on the OLED screen.
playSuccessTone()
– plays a tone sequence when the task is completed correctly.
The software combines interaction, sound, and visual elements to create an engaging user experience.
The OLED screen is used to display menus, game instructions, and feedback to the user. It communicates via the I2C protocol using the Wire library. Functions such as
display.begin()
,
display.clearDisplay()
, and
display.display()
reflect the practical application of Lab 6 concepts.
The buzzer is used to provide audio feedback in the “Match the Weight” game. The
tone()
function utilizes the PWM feature to generate audio signals. As the weight approaches the target value, the rhythm speeds up, demonstrating real-time control over frequency generation.
The weight sensor is interfaced using the HX711 ADC module, which reads analog signals from a load cell. This directly implements the analog-to-digital conversion concepts introduced in Lab 4. The function
scale.get_units()
reads these values in digital form.
The 4×3 matrix keypad allows the user to input commands and navigate the menu. It is scanned to detect key presses by reading digital signals, which aligns with the digital input techniques introduced in Lab 0.
Serial.print()
and
Serial.println()
are used for debugging and displaying values such as the current weight. This is a practical use of USART, as explored in Lab 1.
Delays using
delay()
are introduced to manage user interaction timing (e.g., allowing the user to see feedback before the next step). These practices relate to timing management topics covered in Labs 2 and 3.
OLED (I2C) | Lab 6 | ||
Buzzer (PWM) | Lab 3 | ||
HX711 (ADC) | Lab 4 | ||
Matrix Keypad | Lab 0 | ||
Serial Communication | Lab 1 | ||
Menu / State Logic | Lab 2 | ||
Timing / Delays | Lab 2 / Lab 3 | ||
Shows the main menu, game instructions, user prompts, and results. Provides all visual feedback to the user during setup and gameplay.
Accurately measures the weight of objects placed on the device. Used in both games to set or check the weight value.
Lets the user navigate menus, select game modes, and enter numerical guesses or commands (such as start, confirm, or return to menu).
Outputs audio signals for feedback. Plays different tones to indicate success or to help the user get closer to the target weight in the matching game.
Central controller that runs the main program. Reads inputs from the keypad and weight sensor, updates the display, and controls the buzzer.
To test the weight sensor, I weighed an object with a kitchen scale and checked if the values matched.
For the weight sensor, I used an object with a known weight (75 grams) and observed the sensor reading (approximately 148,500). Based on this, I calculated the calibration factor as (sensor_value / actual_weight).
Used modular functions for clarity and easier maintenance.
Limited display updates to only when changes occur, reducing flicker.
Grouped hardware initialization in setup for faster start.
Provided immediate feedback with the buzzer for better user experience.
Used keypad library debouncing for reliable input.
Calibrated the weight sensor once for consistent measurements.
Demo