The Imperializer: MM to Inch Conversion Box!

The Imperializer!

Imperializer Assembly Video

Bill of Materials:

4x3 Keypad

In/MM Switch

Power Switch

Small Items

Imperializer Arduino Circuit Layout

Arduino Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
|| NYCCNC IMPERIALIZER
|| -version 1.0
|| -author Ed Rees
|| -11/20/2017
|| -Copyright Saunders Machine Works, LLC 2017
*/


#include <Keypad.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address.

float entry = 0; // whole number value.
float a = 0;
float b = 0;
float c = 0;
float decimalValue = 0; // total decimal number value.
float decimalEntry = 0; // most recent number entered while in decimal mode.
float cursBreak = 0; // breaks main loop to position cursor.
int decimalPlace = 0; // records decimal place for decimal value calculation.
int keyCount = 0; // counts key presses to prevent overflow.
int toggleState = 0; // records state of unit toggle switch.
int cursorCount = 0;
int cursorRow = 1;
int divisor = 0; // used for unit conversion math.
int sleepDelay = 8000;
int sleepTimer = sleepDelay;
int toggleLatch = 0; // current state of the button.
int lastToggleLatch = 0; // previous state of the button.
const int togglePin = 11; // declares digital pin 11 as unit toggle pin.
bool decimalMode = false; // toggles between Inch to Millimeter and Millimeter to Inch conversion.
bool decSkip = true; // used to skip cursor decimal count when entry is less than one.
bool decLatch = false; // used to avoid cursor moving undesirably when decimal button is pushed more than once per entry.
bool wakeMode = false;
bool cursorBump = true;

char customKey;
const byte ROWS = 4;
const byte COLS = 3;

char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'C', '0', 'D'}
};
byte rowPins[ROWS] = {9, 4, 5, 7}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 10, 6}; // connect to the column pinouts of the keypad

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

void setup()
{
pinMode(togglePin, INPUT);
pinMode(3, INPUT);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
lcd.begin(16, 2);
lcd.clear();
lcd.print("0.0000");
lcd.setCursor(0, 1);
lcd.print("0.0000");

if (toggleState == HIGH) // determine initial unit toggle state and set cursor row accordingly.
{
cursorRow = 0;
}
else
{
cursorRow = 1;
}
}

void loop()
{
customKey = customKeypad.getKey();
toggleState = digitalRead(togglePin);
toggleLatch = digitalRead(togglePin);

float a = (entry + decimalValue);
float b = (a * 25.4);
float c = (a / 25.4);

if (sleepTimer <= 1) // puts device to sleep when sleep timer runs out.
{
pinMode(8, OUTPUT);
digitalWrite(8, LOW);
sleepNow();
}

if (toggleLatch != lastToggleLatch)
{
sleepTimer = sleepDelay; // reset sleep timer if unit toggle is changed
lcd.begin(16, 2);
lcd.setCursor(0, 0);

if (toggleState == HIGH)
{
cursorRow = 0;
}
else
{
cursorRow = 1;
}
lcd.clear();
cursBreak = .5;

}

if (cursBreak == a)
{
lcd.setCursor(cursorCount, cursorRow);
lcd.blink();
}

switch (customKey)
{
case '0' ... '9':

sleepTimer = sleepDelay; // reset sleep timer if a key is pressed.

if (decimalMode == true) // determine if in decimal entry mode:
{
if (keyCount < 7 && decimalPlace < 4) // prevents overflow.
{
keyCount++; // increment key press count by one.
cursorCount++; // increment cursor ount by one.
decimalPlace++; // increment decimal place by one.
divisor = 0.5 + pow(10, decimalPlace); // divisor is set equal to (10^decimalPlace), plus 0.5 to ensure proper rounding.
decimalEntry = (customKey - '0') / (float)divisor; // decimal entry set equal to key entered, and divided by divisor.
decimalValue = decimalValue + decimalEntry; // new decimal value set equal to previous decimal value plus last decimal entry.
}
break;
}
else
{
if (keyCount < 7 && decimalPlace < 4)
{
keyCount++;
if (entry > 0)
{
cursorCount++;
}
if (entry <= 9 && entry > 0 && cursorBump == true)
{
cursorCount++;
cursorBump = false;
}

entry = entry * 10 + (customKey - '0'); // increments digit input position. ie: 1(*10)+5 = 15.
}
break;
}

case 'D': //collects decimal keypress.
decimalMode = true;
cursBreak = (a + .5);
if (decLatch == false && entry == 0)
{
cursorCount++;
}
if (decSkip == true)
{
cursorCount++;
}
decSkip = false;
decLatch = true;
break;

case 'C': // clear- reset relevant variables to defaults and return to title screen.
cursBreak = a;
entry -= entry;
decimalMode = false;
decimalPlace = 0;
decimalValue -= decimalValue;
decSkip = true;
decLatch = false;
keyCount -= keyCount;
cursorCount -= cursorCount;
cursorBump = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("0.0000");
lcd.setCursor(0, 1);
lcd.print("0.0000");
break;
}

if (toggleState == HIGH && cursBreak != a) // if toggle is in inch mode:
{
lcd.setCursor(0, 0);
lcd.print(a, 4); //in
lcd.setCursor(0, 1);
lcd.print (b, 4); //mm
}
else if (cursBreak != a) //if toggle is NOT in inch mode:
{
lcd.setCursor(0, 0);
lcd.print (c, 4); //mm
lcd.setCursor(0, 1);
lcd.print(a, 4); //in
}

cursBreak = a;
sleepTimer -= 1; //counts down from sleep delay value.

if (wakeMode == true) // upon waking reset relevant variables to defaults and return to title screen.
{
pinMode(togglePin, INPUT);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
lcd.begin(16, 2);
lcd.home();
lcd.clear();
cursBreak = a;
entry -= entry;
decimalMode = false;
decimalPlace = 0;
decimalValue -= decimalValue;
decSkip = true;
decLatch = false;
keyCount -= keyCount;
cursorCount -= cursorCount;
cursorBump = true;
lcd.print("0.0000");
lcd.setCursor(0, 1);
lcd.print("0.0000");
wakeMode = false;
}
lastToggleLatch = toggleLatch;
}

//Sleep functions below:

void sleepNow ()
{
digitalWrite(13, LOW);
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable (); // enables the sleep bit in the mcucr register
attachInterrupt (digitalPinToInterrupt (3), wake, LOW); // wake up on low level on D3
sleep_mode (); // here the device is actually put to sleep
detachInterrupt (digitalPinToInterrupt (3)); // stop LOW interrupt on D3
}

void wake () // interrupt service routine in sleep mode
{
sleep_disable (); // first thing after waking from sleep:
sleepTimer = sleepDelay;
pinMode(8, INPUT);
wakeMode = true;
}