forty-2
09-09-2012, 03:42 PM
Greetings all,
about a month ago, I set out on the task of building a flight sim radio controller using only parts in my apartment. Here's what happened:
6918
I had always been interested in using a number pad to input radio frequencies. As luck would have it, I had a keypad kicking around from some odd control panel (possibly a drunken eBay purchase). I had an ardiuno and LCD shield for general development, and the case is a plastic storage container I'd picked up a while ago.
I've attached the 3 arduino sketch files and the lua file in a zip file. The lua file is run through FSUIPC, right now I have the Lua start & kill commands bound to buttons on my X-keys, but at some point I'll just have it auto-load.
The keys are currently set as follows - the engraving on the keys is incorrect, but I deal.
-
-
-
-
com Sel
1
2
3
nav Sel
4
5
6
com swap
7
8
9
nav swap
.
0
ent
the top row is unused (and not even connected). With the LCD taking 6 digital pins, I didn't have enough left to scan the keypad in the usual way, so with the help of some resistors, I'm reading the keyboard using a single analog input. I was concerned that this would be too slow or prone to errors, but it's worked great so far, here's the hookup diagram:
6920
In the main program loop, I'm only calling two functions, readKey() & readFSX(), alternating between dealing with keyboard inputs, and serial inputs. All of the code is in the attachment, but I'll highlight one or two specific approaches. Here's keyboard read function called from readKey():
char getKey(int aKey){ if (aKey < 432){keypressed = '3';}
else if ((aKey > 432) && (aKey < 451)){keypressed = '2';}
else if ((aKey > 451) && (aKey < 473)){keypressed = '1';}
else if ((aKey > 473) && (aKey < 492)){keypressed = 'C';} //Com select
else if ((aKey > 492) && (aKey < 513)){keypressed = '6';}
else if ((aKey > 513) && (aKey < 541)){keypressed = '5';}
else if ((aKey > 541) && (aKey < 571)){keypressed = '4';}
else if ((aKey > 571) && (aKey < 599)){keypressed = 'N';} //Nav select
else if ((aKey > 599) && (aKey < 630)){keypressed = '9';}
else if ((aKey > 630) && (aKey < 672)){keypressed = '8';}
else if ((aKey > 672) && (aKey < 720)){keypressed = '7';}
else if ((aKey > 720) && (aKey < 766)){keypressed = 'c';} //Com swap
else if ((aKey > 766) && (aKey < 818)){keypressed = 'E';} //Enter
else if ((aKey > 818) && (aKey < 890)){keypressed = '0';}
else if ((aKey > 891) && (aKey < 976)){keypressed = '.';} //Decimal point
else if ((aKey > 976) && (aKey < 1024)){keypressed = 'n';} //Nav swap
while (aKey > 25) {
delay (25); //wait until key no longer being pressed before continuing
aKey = analogRead(keyboardPin);
}
return keypressed;
}
The enter key does a few things:
if you type ###.##, enter isn't required
if you type ###.#, hitting enter places a zero in the last digit
if you hit enter with fewer digits entered, it acts as a clear key, which is kinda handy.
Nav/com select & swap buttons, and inputs from FSX will set a 'mode', which is an index from 0 - 7:
"com1A", "com1S", "nav1A", "nav1S", "com2A", "com2S", "nav2A", "nav2S"
('A' & 'S' is for active & standby)
The mode is used as an index for a hand-full of int & char arrays, used in re-positioning the LCD cursor, showing the current mode on the LCD, and setting the correct prepended codes for serial communication. Right now its only working for Com1/Nav1, but the next step is making the select buttons alternate between 1 & 2 respectively.
here are the relevant arrays and functions:
//cursor positions
int cursorX[] = {0, 0, 10, 10, 0, 0, 10, 10};
int cursorY[] = {0, 1, 0, 1, 0, 1, 0, 1};
//send frequency prefixes
char* sndFreq[] ={"d", "e", "f", "g", "h", "i", "j", "k"};
char* swapCode[] ={"c", "c", "n", "n"}; //only nav/com1
//LCD gak
char* lcdL1[] ={"C1", "C1", "N1", "N1", "C2", "C2", "N2", "N2"};
char* lcdL2[] ={"<0", "<1", "2>", "3>", "<4", "<5", "6>", "7>"};
//places cursor based on mode - called on keyboard input & mode changes
void lcdCursor(){
lcd.setCursor(cursorX[mode]+keyCount, cursorY[mode]);
}
//called on mode change from keypad input or FSX input.
void setMode(int i){
mode = i;
lcd.setCursor(7,0);
lcd.print(lcdL1[mode]);
lcd.setCursor(7,1); //update mode indication on LCD
lcd.print(lcdL2[mode]);
lcd.setCursor(cursorX[mode], cursorY[mode]);
}
I'll post a video at some point, but it does work (as of about 2:00 AM last night)!!
This was my first real experience with Lua, and the most complex arduino project I've done to date. The code isn't terribly hideous (and it is commented!), but I'm sure someone with more experience could find room for improvement.
I'm considering this a proof of concept project that I hope to build upon, since right now, it's not the prettiest thing on my desktop, and the keypad isn't so great (small, short travel, too much force required). I'm open to suggestions!
I hope this information is useful to someone out there, please feel free to offer up suggestions or ask any questions.
thanks!
about a month ago, I set out on the task of building a flight sim radio controller using only parts in my apartment. Here's what happened:
6918
I had always been interested in using a number pad to input radio frequencies. As luck would have it, I had a keypad kicking around from some odd control panel (possibly a drunken eBay purchase). I had an ardiuno and LCD shield for general development, and the case is a plastic storage container I'd picked up a while ago.
I've attached the 3 arduino sketch files and the lua file in a zip file. The lua file is run through FSUIPC, right now I have the Lua start & kill commands bound to buttons on my X-keys, but at some point I'll just have it auto-load.
The keys are currently set as follows - the engraving on the keys is incorrect, but I deal.
-
-
-
-
com Sel
1
2
3
nav Sel
4
5
6
com swap
7
8
9
nav swap
.
0
ent
the top row is unused (and not even connected). With the LCD taking 6 digital pins, I didn't have enough left to scan the keypad in the usual way, so with the help of some resistors, I'm reading the keyboard using a single analog input. I was concerned that this would be too slow or prone to errors, but it's worked great so far, here's the hookup diagram:
6920
In the main program loop, I'm only calling two functions, readKey() & readFSX(), alternating between dealing with keyboard inputs, and serial inputs. All of the code is in the attachment, but I'll highlight one or two specific approaches. Here's keyboard read function called from readKey():
char getKey(int aKey){ if (aKey < 432){keypressed = '3';}
else if ((aKey > 432) && (aKey < 451)){keypressed = '2';}
else if ((aKey > 451) && (aKey < 473)){keypressed = '1';}
else if ((aKey > 473) && (aKey < 492)){keypressed = 'C';} //Com select
else if ((aKey > 492) && (aKey < 513)){keypressed = '6';}
else if ((aKey > 513) && (aKey < 541)){keypressed = '5';}
else if ((aKey > 541) && (aKey < 571)){keypressed = '4';}
else if ((aKey > 571) && (aKey < 599)){keypressed = 'N';} //Nav select
else if ((aKey > 599) && (aKey < 630)){keypressed = '9';}
else if ((aKey > 630) && (aKey < 672)){keypressed = '8';}
else if ((aKey > 672) && (aKey < 720)){keypressed = '7';}
else if ((aKey > 720) && (aKey < 766)){keypressed = 'c';} //Com swap
else if ((aKey > 766) && (aKey < 818)){keypressed = 'E';} //Enter
else if ((aKey > 818) && (aKey < 890)){keypressed = '0';}
else if ((aKey > 891) && (aKey < 976)){keypressed = '.';} //Decimal point
else if ((aKey > 976) && (aKey < 1024)){keypressed = 'n';} //Nav swap
while (aKey > 25) {
delay (25); //wait until key no longer being pressed before continuing
aKey = analogRead(keyboardPin);
}
return keypressed;
}
The enter key does a few things:
if you type ###.##, enter isn't required
if you type ###.#, hitting enter places a zero in the last digit
if you hit enter with fewer digits entered, it acts as a clear key, which is kinda handy.
Nav/com select & swap buttons, and inputs from FSX will set a 'mode', which is an index from 0 - 7:
"com1A", "com1S", "nav1A", "nav1S", "com2A", "com2S", "nav2A", "nav2S"
('A' & 'S' is for active & standby)
The mode is used as an index for a hand-full of int & char arrays, used in re-positioning the LCD cursor, showing the current mode on the LCD, and setting the correct prepended codes for serial communication. Right now its only working for Com1/Nav1, but the next step is making the select buttons alternate between 1 & 2 respectively.
here are the relevant arrays and functions:
//cursor positions
int cursorX[] = {0, 0, 10, 10, 0, 0, 10, 10};
int cursorY[] = {0, 1, 0, 1, 0, 1, 0, 1};
//send frequency prefixes
char* sndFreq[] ={"d", "e", "f", "g", "h", "i", "j", "k"};
char* swapCode[] ={"c", "c", "n", "n"}; //only nav/com1
//LCD gak
char* lcdL1[] ={"C1", "C1", "N1", "N1", "C2", "C2", "N2", "N2"};
char* lcdL2[] ={"<0", "<1", "2>", "3>", "<4", "<5", "6>", "7>"};
//places cursor based on mode - called on keyboard input & mode changes
void lcdCursor(){
lcd.setCursor(cursorX[mode]+keyCount, cursorY[mode]);
}
//called on mode change from keypad input or FSX input.
void setMode(int i){
mode = i;
lcd.setCursor(7,0);
lcd.print(lcdL1[mode]);
lcd.setCursor(7,1); //update mode indication on LCD
lcd.print(lcdL2[mode]);
lcd.setCursor(cursorX[mode], cursorY[mode]);
}
I'll post a video at some point, but it does work (as of about 2:00 AM last night)!!
This was my first real experience with Lua, and the most complex arduino project I've done to date. The code isn't terribly hideous (and it is commented!), but I'm sure someone with more experience could find room for improvement.
I'm considering this a proof of concept project that I hope to build upon, since right now, it's not the prettiest thing on my desktop, and the keypad isn't so great (small, short travel, too much force required). I'm open to suggestions!
I hope this information is useful to someone out there, please feel free to offer up suggestions or ask any questions.
thanks!