#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Arduino.h>
#include <avr/wdt.h>
// LCD Settings (I2C address 0x27, size 16x2)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Keypad Settings
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{',', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8, 9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
struct FractionConversion {
const char* fraction;
double inches;
double mm;
};
//convertion
FractionConversion fraction_conversion[] = {
{"1/64", 0.015625, 0.3969}, {"1/32", 0.03125, 0.7938}, {"3/64", 0.046875, 1.1906}, {"1/16", 0.0625, 1.5875}, {"5/64", 0.078125, 1.9844}, {"3/32", 0.09375, 2.3813},
{"7/64", 0.109375, 2.7781}, {"1/8", 0.125, 3.175}, {"9/64", 0.140625, 3.5719}, {"5/32", 0.15625, 3.9688}, {"11/64", 0.171875, 4.3655}, {"3/16", 0.1875, 4.7625}, {"13/64", 0.203125, 5.1594},
{"7/32", 0.21875, 5.5563}, {"15/64", 0.234375, 5.9531}, {"1/4", 0.25, 6.35}, {"17/64", 0.265625, 6.7469}, {"9/32", 0.28125, 7.1438}, {"19/64", 0.296875, 7.54}, {"5/16", 0.3125, 7.9375},
{"21/64", 0.328125, 8.3344}, {"11/32", 0.34375, 8.7313}, {"23/64", 0.359375, 9.1282}, {"3/8", 0.375, 9.525}, {"25/64", 0.390625, 9.9219}, {"13/32", 0.40625, 10.3188}, {"27/64", 0.421875, 10.7157},
{"7/16", 0.4375, 11.1125}, {"29/64", 0.453125, 11.5094}, {"15/32", 0.46875, 11.9063}, {"31/64", 0.484375, 12.3032}, {"1/2", 0.5, 12.7}, {"33/64", 0.515625, 13.096}, {"17/32", 0.53125, 13.493},
{"35/64", 0.546875, 13.89}, {"9/16", 0.5625, 14.287}, {"37/64", 0.578125, 14.684}, {"19/32", 0.59375, 15.081}, {"39/64", 0.609375, 15.478}, {"5/8", 0.625, 15.875},
{"41/64", 0.640625, 16.271}, {"21/32", 0.65625, 16.668}, {"43/64", 0.671875, 17.065}, {"11/16", 0.6875, 17.462}, {"45/64", 0.703125, 17.859}, {"23/32", 0.71875, 18.256}, {"47/64", 0.734375, 18.653},
{"3/4", 0.75, 19.05}, {"49/64", 0.765625, 19.447}, {"25/32", 0.78125, 19.843},
{"51/64", 0.796875, 20.24}, {"13/16", 0.8125, 20.6375}, {"53/64", 0.828125, 21.0345}, {"27/32", 0.84375, 21.431}, {"55/64", 0.859375, 21.8282}, {"7/8", 0.875, 22.2251}, {"57/64", 0.890625, 22.6220},
{"29/32", 0.90625, 23.0188}, {"59/64", 0.921875, 23.4157}, {"15/16", 0.9375, 23.8126}, {"61/64", 0.953125, 24.2095}, {"31/32", 0.96875, 24.6063}, {"63/64", 0.984375, 25.0032}, {"1", 1.0, 25.4}
};
const int arraySize = sizeof(fraction_conversion) / sizeof(fraction_conversion[0]);
// Number array
int gearInventory[] = {
127, 113, 109, 96, 90, 86, 85, 80, 79, 77, 76, 75, 73, 71, 70, 67, 65, 62, 61, 60, 59, 58, 56,
55, 54, 50, 49, 48, 47, 46, 45, 43, 41, 40, 38, 37, 36, 35, 34, 33, 32, 30, 28, 26, 25, 24, 23,
22, 20
};
const int gearInventoryLength = sizeof(gearInventory) / sizeof(gearInventory[0]);
// Swap function
void swapElements(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
// Median-of-three pivot selection
int medianOfThree(int arr[], int low, int high) {
int mid = low + (high - low) / 2;
if (arr[low] > arr[mid]) swapElements(arr[low], arr[mid]);
if (arr[low] > arr[high]) swapElements(arr[low], arr[high]);
if (arr[mid] > arr[high]) swapElements(arr[mid], arr[high]);
return arr[mid]; // Return pivot value instead of index
}
// Partition function for Quick Sort
int partition(int arr[], int low, int high) {
int pivot = medianOfThree(arr, low, high);
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] >= pivot) { // Sorting in descending order
i++;
swapElements(arr[i], arr[j]);
}
}
swapElements(arr[i + 1], arr[high]);
return i + 1;
}
// Quick Sort implementation
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
// Function to read value from keypad
String getInputFromKeypad() {
String input = "";
char key;
while (true) {
key = keypad.getKey();
if (key) {
if (key == '#') break;
if (key == '*') {
input += '.';
lcd.print(',');
} else if (key == 'D') {
if (input.length() > 0) {
input.remove(input.length() - 1);
lcd.clear();
lcd.print("Input, ");
lcd.print(input);
}
} else {
input += key;
lcd.print(key);
}
}
}
return input;
}
// Function to check conditions
bool checkConditions(float i, float j, float k, float l) {
bool condition1 = ((i + l) / 2.0 < 4600 && (i + j) / 2.0 < 6400 && (k + l) / 2.0 < 5200);
bool condition2 = ((i + l) / 2.0 > 0 && (i + j) / 2.0 > 0 && (k + l) / 2.0 > 0);
return condition1 && condition2;
}
// Find combinations
void findCombination(float Z, float Zc) {
float epsilon = 0.0001;
double Sxesi = 2.4 * (Zc / Z);
lcd.clear();
lcd.print("Looking for 2...");
delay(1000);
// Search for 2 numbers
for (int i = 0; i < gearInventoryLength; i++) {
for (int j = 0; j < gearInventoryLength; j++) {
if (i != j) {
float ratio = static_cast<float>(gearInventory[i]) / static_cast<float>(gearInventory[j]);
float difference = fabs(Sxesi - ratio);
if (difference < epsilon) {
lcd.clear();
lcd.print("Found: ");
lcd.setCursor(0, 1);
lcd.print(gearInventory[i]);
lcd.print("-");
lcd.print(gearInventory[j]);
delay(5000);
return;
}
}
}
}
// Search for 4 numbers
lcd.clear();
lcd.print("Looking for 4...");
delay(1000);
for (int i = 0; i < gearInventoryLength; i++) {
for (int j = 0; j < gearInventoryLength; j++) {
for (int k = 0; k < gearInventoryLength; k++) {
for (int l = 0; l < gearInventoryLength; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
float ratio = static_cast<float>(gearInventory[i]) / static_cast<float>(gearInventory[j]) *
static_cast<float>(gearInventory[k]) / static_cast<float>(gearInventory[l]);
float difference = fabs(Sxesi - ratio);
if (difference < epsilon && checkConditions(gearInventory[i], gearInventory[j], gearInventory[k], gearInventory[l])) {
lcd.clear();
lcd.print("Found: ");
lcd.setCursor(0, 1);
lcd.print(gearInventory[i]);
lcd.print("-");
lcd.print(gearInventory[j]);
lcd.print("-");
lcd.print(gearInventory[k]);
lcd.print("-");
lcd.print(gearInventory[l]);
delay(5000);
return;
}
}
}
}
}
}
lcd.clear();
lcd.print("Not found");
delay(2000);
}
// Setup function
void setup() {
lcd.begin(16, 2);
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("A = gears 2");
lcd.setCursor(0, 1);
lcd.print("B = angles");
// Sort the array in descending order
quickSort(gearInventory, 0, gearInventoryLength - 1);
}
// Main loop
void loop() {
char key = keypad.getKey();
if (key) {
if (key == 'A') {
lcd.clear();
lcd.print("Enter Z:");
String inputZ = getInputFromKeypad();
float Z = inputZ.toFloat();
lcd.clear();
lcd.print("Enter Zc:");
String inputZc = getInputFromKeypad();
float Zc = inputZc.toFloat();
lcd.clear();
lcd.print("Processing...");
findCombination(Z, Zc);
} if (key == 'C') {
lcd.clear();
lcd.print("Restarting...");
delay(1000);
wdt_enable(WDTO_15MS);
while (1) {}
}
else if (key == 'B') {
lcd.clear();
lcd.print("Enter mm:");
String inputMMStr = getInputFromKeypad();
double inputMM = inputMMStr.toFloat();
lcd.clear();
lcd.print("Processing...");
double minDiff = 1e10;
int closestIndex = -1;
for (int i = 0; i < arraySize; i++) {
double diff = fabs(fraction_conversion[i].mm - inputMM); // Compare decimal, not fraction
if (diff < minDiff) {
minDiff = diff;
closestIndex = i;
}
}
lcd.clear();
if (closestIndex != -1) {
lcd.setCursor(0, 0);
lcd.print(fraction_conversion[closestIndex].fraction);
lcd.print(" = ");
lcd.setCursor(0, 1);
lcd.print(fraction_conversion[closestIndex].mm, 4);
lcd.print(" mm");
} else {
lcd.print("No match found.");
}
}
}
}