Cosmic Scales - Arduino Based Interplanetary Weight Machine

by _Stemonkey in Circuits > Arduino

75 Views, 1 Favorites, 0 Comments

Cosmic Scales - Arduino Based Interplanetary Weight Machine

Screenshot 2024-10-13 013053.png
Screenshot 2024-10-13 013018.png

Arduino-Based Planetary Weight Calculator

Introduction

Inspired by the Stars

Recently, I visited the Jawaharlal Nehru Planetarium and was fascinated by one of their exhibits. The exhibit had a weight machine that displayed your weight on different planets in our Solar System. This experience sparked an idea: why not create a similar device at home using an Arduino? So, I embarked on a journey to build a Planetary Weight Calculator using an Arduino Uno, a 4x4 matrix keypad, and an I2C LCD display.

This project allows you to input your weight on Earth and instantly see what you would weigh on other planets—and even on dwarf planets like Ceres and Makemake! It's a fun and educational tool that can be used in classrooms, science fairs, or just for some space-themed fun at home.


Step 1: Gather Your Materials

Hardware Components

  1. Arduino Uno: The main microcontroller that runs the program.
  2. 4x4 Matrix Keypad: For entering your weight and controlling the device.
  3. I2C 16x2 LCD Display: To display your weight on Earth and other planets.
  4. Buzzer: (Optional) Provides audio feedback for keypresses and errors.
  5. Connecting Wires: For assembling the circuit on a breadboard.
  6. Breadboard: To connect all the components together.

Screenshot 2024-10-13 013018.png

Step 2: Circuit Assembly

Connecting the Keypad

  1. Connect the rows and columns of the 4x4 keypad to the Arduino's digital pins.
  2. Make sure to define the correct pin connections in the code.

Connecting the I2C LCD

  1. Connect the I2C LCD to the Arduino’s SDA(A5) and SCL(A4) pins of arduino, VCC to 5V and GND to GND respectively.
  2. Ensure the I2C address matches the one in your code (usually 0x27).

Optional: Connecting the Buzzer

  1. Connect the positive lead of the buzzer to a digital pin on the Arduino. (D11) of Arduino.
  2. Connect the negative lead to the ground.

(Refer the image for wire connection)

Writing the Code:


Setting Software Libraries

  1. Wire.h: For I2C communication between Arduino and the LCD.
  2. LiquidCrystal_I2C.h: To control the I2C LCD.
  3. Keypad.h: For interfacing with the 4x4 keypad.

Handle Key Presses

Set up key functionalities to handle weight input, unit toggling, confirmation, and clearing:

  1. # (Confirm): Confirms the weight input and calculates weights on other planets.
  2. * (Clear/Reset):
  3. Short Press: Clears the current input field.
  4. Long Press (More than 2 seconds): Resets the entire input process.
  5. A (Info) Display the info on the display about how to use the device.
  6. C (Toggle Units): Switches between kilograms (Kg) and pounds (lbs).
  7. D (Decimal Point): Adds a decimal point to the weight input.
  8. A (Help): Displays the functionality of each key.

Display Weight on Planets

Store the gravitational ratios and planet names in arrays to calculate and display the user's weight on each planet:

const String planets[] = {"Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Ceres", "Eris", "Haumea", "Makemake"}; const float gravities[] = {0.165, 0.378, 0.907, 0.377, 2.36, 0.916, 0.889, 1.12, 0.063, 0.028, 0.082, 0.044, 0.05};

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

// Initialize the I2C LCD with the correct address
LiquidCrystal_I2C lcd(0x27, 16, 2);

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

String weightInput = "";
boolean isEnteringWeight = true;
bool isMetric = true; // true for kg, false for lbs
bool buzzerEnabled = true;
unsigned long keyPressTime = 0;
bool longPressDetected = false;

const int buzzerPin = 11;

// Arrays for planet names and their gravitational ratios relative to Earth
const String planets[] = {"Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Ceres", "Eris", "Haumea", "Makemake"};
const float gravities[] = {0.165, 0.378, 0.907, 0.377, 2.36, 0.916, 0.889, 1.12, 0.063, 0.028, 0.082, 0.044, 0.05};

int weightLimit = 3;

void setup() {
lcd.init();
lcd.backlight();
pinMode(buzzerPin, OUTPUT);

lcd.setCursor(0, 0);
lcd.print("Enter weight:");
updateWeightDisplay();
}

void loop() {
char key = customKeypad.getKey();

if (key) {
playTone(1000, 100); // Default tone for key press
if (key == '*') {
keyPressTime = millis();
longPressDetected = false;
}

switch (key) {
case '#':
if (isEnteringWeight) {
if (isNumeric(weightInput)) {
displayWeights(); // Calculate and display weights on planets
playTone(1500, 150); // Confirmation tone
delay(7000); // Display weights for 7 seconds
resetInput(); // Reset for next calculation
} else {
displayError("Invalid Weight!");
}
}
break;
case '*':
if (millis() - keyPressTime > 2000 && !longPressDetected) {
playTone(500, 300); // Reset tone
resetInput(); // Reset all inputs
longPressDetected = true;
} else if (!longPressDetected) {
clearCurrentInput(); // Clear the current weight input
}
break;
case 'C':
toggleUnits(); // Toggle between kg and lbs
updateWeightDisplay(); // Update the display to show the correct unit
break;
case 'D':
handleDecimalInput(); // Add decimal point
break;
case 'A':
showKeyFunctions(); // Display key functions
break;
case 'B':
toggleBuzzer(); // Toggle buzzer on/off
break;
default:
if (isDigit(key)) {
if (weightInput.length() < weightLimit) {
weightInput += key;
updateWeightDisplay();
} else {
displayError("Limit: " + String(weightLimit) + " digits");
weightInput = ""; // Clear input for re-entry
}
}
break;
}
}
}

void updateWeightDisplay() {
lcd.setCursor(0, 1);
lcd.print("Earth: ");
lcd.print(weightInput);
lcd.print(" "); // Clear any trailing characters
lcd.setCursor(13, 1);
lcd.print(isMetric ? "Kg" : "lbs");
}

void resetInput() {
weightInput = "";
isEnteringWeight = true;
weightLimit = 3;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter your weight:");
updateWeightDisplay();
}

void clearCurrentInput() {
weightInput = "";
updateWeightDisplay();
}

void displayWeights() {
float weight = weightInput.toFloat();
if (!isMetric) {
weight = weight * 0.453592; // Convert lbs to kg
}
for (int i = 0; i < 13; i++) {
lcd.clear();
displayWeightOnPlanet(planets[i], weight * gravities[i]);
delay(2000);
}
}

void displayWeightOnPlanet(String planetName, float planetWeight) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(planetName + ":");
lcd.setCursor(0, 1);
lcd.print(planetWeight, 2); // Display weight with 2 decimal places
lcd.print(isMetric ? " Kg" : " lbs");
}

void displayError(String message) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(message);
playTone(400, 500); // Error tone
delay(2000); // Display error message for 2 seconds
clearCurrentInput();
}

void toggleUnits() {
isMetric = !isMetric;
updateWeightDisplay(); // Update the display to show the correct unit
}

void handleDecimalInput() {
if (weightInput.indexOf('.') == -1 && weightInput.length() < weightLimit) {
weightInput += '.';
weightLimit = 5; // Adjust limit for decimal input
updateWeightDisplay();
}
}

void showKeyFunctions() {
lcd.clear();
const char* keyExplanations[] = {
"B: Buzzer On/Off",
"C: Toggle Units",
"D: Add Decimal",
"*: Clear",
"#: Confirm",
};

for (int i = 0; i < 5; i++) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(keyExplanations[i]);
delay(2000); // Display each explanation for 2 seconds
}
resetInput();
}

void toggleBuzzer() {
buzzerEnabled = !buzzerEnabled;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(buzzerEnabled ? "Buzzer: ON" : "Buzzer: OFF");
delay(1000);
resetInput();
}

bool isNumeric(String str) {
bool decimalPoint = false;
for (byte i = 0; i < str.length(); i++) {
if (str.charAt(i) == '.') {
if (decimalPoint) return false;
decimalPoint = true;
} else if (!isDigit(str.charAt(i))) {
return false;
}
}
return true;
}

void playTone(int frequency, int duration) {
if (buzzerEnabled) {
tone(buzzerPin, frequency, duration);
}
}

Conclusion

By following these steps, you can built your own Planetary Weight Calculator! This device is not only a fun and interactive tool but also an educational one. It can help demonstrate the effects of gravity on weight, teaching users how their weight would change on different celestial bodies.

This project is perfect for science fairs, classroom demonstrations, or just as a cool gadget to have around the house. Whether you’re fascinated by space or just enjoy building things with Arduino, this project is sure to inspire and educate.

Enjoy your Arduino-based Planetary Weight Calculator, and keep exploring the wonders of the universe!