How do you build a menu for data input?
tosjduenfs
Posts: 37
I've been working on a telescope tracking system and I've got most of my motor control and tracking calculations worked out but now it is time to start tying them all together. Part of the system will be a hand controller with a 12 key number pad, a directional pad with up,down,left,right and center buttons, and a small joystick for slewing the telescope manually.
When I first start up the telescope tracker I need to input information such as latitude, longitude, time, etc... I thought making the menu and getting the data would be the easiest part of the coding but it is turning out to be more difficult than expected and I'm not sure how to proceed and structure it. Here is where I have started:
Here is what I get when I run this:
http://youtu.be/kNgQ94qL5Do
I have the * and # buttons on the keypad set to move the cursor left and right. I still need to make the d pad. What I'm really trying to figure out is how to take the numbers I put on the screen and put them into the variables they represent in my code.
In the second line there are 4 variables: longitude degrees, longitude minutes, latitude degrees, latitude minutes. I'd like to be able to enter the values and be able to go back to fix mistakes before going to the next screen. I'm just not sure how to take the values I put up on the screen. If I could I would just have the lcd tell me what values are in certain positions on the screen when I ask it to but I don't think I can do that. I don't think I there was anything useful in the obex for making menus, if anyone has any ideas I would appreciate it.
When I first start up the telescope tracker I need to input information such as latitude, longitude, time, etc... I thought making the menu and getting the data would be the easiest part of the coding but it is turning out to be more difficult than expected and I'm not sure how to proceed and structure it. Here is where I have started:
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 lcdpin = 0 'serial lcd pin assignment k1 = 9 'keypad pin assignments k2 = 10 k3 = 11 k4 = 12 k5 = 13 k6 = 14 k7 = 15 OBJ LCD : "SparkFun_Serial_LCD" PUB Main LCD.init(lcdpin,9_600,2,16) 'initialize LCD waitcnt(clkfreq/10 + cnt) 'wait for LCD to initialize LCD.cls 'clear lcd lcd.cursor(2) 'set cursor type lcd.str(string("ENTER LOCATION:")) 'display first page of menu: lcd.gotoxy(0,1) lcd.str(string("000")) 'ENTER LOCATION: lcd.putc(223) '000d00'W 00d00'N 'where d is the actual degree symbol lcd.str(string("00'W 00")) lcd.putc(223) lcd.str(string("00'N")) lcd.gotoxy(0,1) repeat lcd.dec(keypad) waitcnt(clkfreq/4+cnt) PRI keypad 'keypad sets the columns as outputs and the rows as inputs. It sweeps each column indidually and looks for a keypress on a row. When a keypress is detected it returns the associated value dira[k1] := dira[k3] := dira[k5] := 1 dira[k2] := dira[k4] := dira[k6] := dira[k7] := 0 repeat outa[k1] := 1 'set column one high then check rows for key press if ina[k2] == 1 return 2 elseif ina[k4] == 1 return 0 elseif ina[k6] == 1 return 8 elseif ina[k7] == 1 return 5 outa[k1] := 0 outa[k3] := 1 'set column three high then check rows for key press if ina[k2] == 1 return 1 elseif ina[k4] == 1 lcd.cursorleft '* button waitcnt(clkfreq/4+cnt) elseif ina[k6] == 1 return 7 elseif ina[k7] == 1 return 4 outa[k3] := 0 outa[k5] := 1 'set column five high then check rows for key press if ina[k2] == 1 return 3 elseif ina[k4] == 1 lcd.cursorright '# button waitcnt(clkfreq/4+cnt) elseif ina[k6] == 1 return 9 elseif ina[k7] == 1 return 6 outa[k5] := 0
Here is what I get when I run this:
http://youtu.be/kNgQ94qL5Do
I have the * and # buttons on the keypad set to move the cursor left and right. I still need to make the d pad. What I'm really trying to figure out is how to take the numbers I put on the screen and put them into the variables they represent in my code.
In the second line there are 4 variables: longitude degrees, longitude minutes, latitude degrees, latitude minutes. I'd like to be able to enter the values and be able to go back to fix mistakes before going to the next screen. I'm just not sure how to take the values I put up on the screen. If I could I would just have the lcd tell me what values are in certain positions on the screen when I ask it to but I don't think I can do that. I don't think I there was anything useful in the obex for making menus, if anyone has any ideas I would appreciate it.
Comments
In my projects I tend to define LCD menu screens in DAT tables which allows me change screens quickly with a method call (the screen displayed is based on the main-menu state). Then I call a handler for that screen which knows where the fields are and how to manipulate them.
Till this point, your input method sounds great.
At last, there are only two lines of text, and you wisely decided to use the first one, to explain the meaning of the second one.
As long as you keep using defined templates to gather data input, you won't have to worry about "Insert" or "Delete" alike keys, just the ones you have in fact.
IMHO, if you decide not using extra buttons, in a separate keypad, to input an "Enter" alike key stroke and other suitable function keys, you could use the detection of a simultaneous pressing of both * and #, to create into your decision tree, suitable branches to deal with them.
As for storing gathered data, you can do it in a multitude of ways, its only a matter of each programmer's personal preferences.
Testing various options will help you decide which "style" best fits yours.
In cases like the one you has shown us at the video, my trend is to point a base register, to value place holders at local memory, and an index to the leftmost (or rightmost) item, whichever best fits; It's related to the place where the cursor was left, at the very beggining of data input screen editing routine; Then you can be confident of the following operator movements.
Then, as the operator progresses, doing left or right movements using the "cursor positioning" keys, the index variable is incremented or decremented accordingly.
You just have to set upper and lower limits to the index value, to don't mess with neighboring memory areas.
For each valid keystroke, you will have only two options:
- store the new value at its memory position, and decide if the chosen input method determines a left or right cursor movement, or not;
- if you choose to update cursor's position, adjust the index variable accordingly. If you reached leftmost or rightmost display line position, then you must choose staying there, or executing some line wrapping code, but your current application doesn't appear to benefit of such an strategy.
To be true, short-key-counts keypad projects, are a sure head ache to deal with, when it comes to wrapping data or text input. But its your decision, and operator's convenience, that will prevail at the end.
Since Propellers are, by nature, multitasking processors, you can act wisely, keeping the original value, the one displayed at the beggining of data input routine, at Hub ram, and use a copy to deal with, during data input editing.
After the input and edit process exits, thru the detection of a "Enter" keystoke, you can forward the fresh new value to Hub ram, and sign another waiting Cog's routine, to deal with the mechanical positioning system.
As long as you are entering some new coordinates, if you chose to dinamically update its contents, in parallel with the motor steering mechanics controller, then, IMHO, I'm about to suggest you to update it from right to left, minute units first, sparing your system from doing large movements at first.
But its just my point of view, your own choices will dictate project's final behavior.
Good luck!:thumb:
I hope it can help a bit
Yanomani
Tested using my 4x20 parallel LCD, which I've commented out. Also shows the value on the serial terminal.
The button used is a the Parallax 5 position switch. When the method is activated it cycles through the list using lookup(). The up /dwn button inc and dec the value to control the display and selected option.