BS2sx, Keypad data entry, Parallax Serial LCD, display question
xanatos
Posts: 1,120
I have a 4 x 4 keypad, encoded with a 74C922, hooked up to a BS2sx. To the same BS2sx I have a Parallax Serial LCD attached.
I am adapting code I found from N&V #97 (Keyboard Entry and Display). Code as follows:
My issue stems from the fact that the LCD display I am using seems to only display two digits when I send the data to it. The VAR 'dispChar' is a Word.
I would normally use the raw keyIn value and multiply it by 10 with each iteration of the keyCount to allow for multiple key entries, but the result of the LOOKUP is - I believe - ASCII, so I can't multiply that. When I've tried using teh raw keyIn value and the *10 thing, I can SEROUT to the LCD and get the single digit on the first keypress, two digits on the second... and two digits on every subsequent keypress.
So - and I know this is a simple thing - but I seem stuck between being unable to shift the decimal place with an ASCII word, or something I am doing wrong trying to send (up to 5) characters to the LCD.
Any help greatly appreciated. Feeling very dumb at the moment.
Thanks,
Dave
I am adapting code I found from N&V #97 (Keyboard Entry and Display). Code as follows:
keyCount = 0
DO : LOOP UNTIL (kbdDA = 1) ' Wait until Data Available from 74C922
keyIn = INB
LOOKUP keyIn, [ 1, 2, 3, 10,
4, 5, 6, 11,
7, 8, 9, 12,
14, 0, 15, 13 ], keyIn ' translate kbd matrix
LOOKUP keyIn, ["0123456789ABCD*#"], dispChar ' translate key to ASCII
SEROUT LCD, LcdBaud, [LcdCls]
PAUSE 5
SEROUT LCD, LcdBaud, [dispChar, " "]
IF (keyIn = 14) THEN ' 14 = * (Abort and go to beginning)
keyCount = 0
GOTO Main
ELSEIF (keyIn = 15) THEN '15 = # (Accept entry and go to next op)
keyCount = 0
EXIT
ENDIF
My issue stems from the fact that the LCD display I am using seems to only display two digits when I send the data to it. The VAR 'dispChar' is a Word.
I would normally use the raw keyIn value and multiply it by 10 with each iteration of the keyCount to allow for multiple key entries, but the result of the LOOKUP is - I believe - ASCII, so I can't multiply that. When I've tried using teh raw keyIn value and the *10 thing, I can SEROUT to the LCD and get the single digit on the first keypress, two digits on the second... and two digits on every subsequent keypress.
So - and I know this is a simple thing - but I seem stuck between being unable to shift the decimal place with an ASCII word, or something I am doing wrong trying to send (up to 5) characters to the LCD.
Any help greatly appreciated. Feeling very dumb at the moment.
Thanks,
Dave

Comments
This will be difficult to determine without seeing the rest of the code. Can you attach the entire program as a file?
Thanks for your assistance here. I have edited my code down to only the LCD parts (there are a lot of things hanging off of my BS2 here - printers, solenoids, dataloggers, RTC, odd switches... so here's the code less about 300 lines in two slots:
' {$STAMP BS2sx} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ I/O Definitions ]------------------------------------------------- kbdDA PIN 3 ' Keyboard Data Available line from 74C922 kbd0 PIN 4 ' Keyboard bit 0 from 74C922 kbd1 PIN 5 ' Keyboard bit 1 from 74C922 kbd2 PIN 6 ' Keyboard bit 2 from 74C922 kbd3 PIN 7 ' Keyboard bit 3 from 74C922 These are all now on INB LCD PIN 14 ' Parallax Serial LCD Display ' -----[ Constants ]------------------------------------------------------- LcdBaud CON 110 ' LCD Baud derp LcdBkSpc CON $08 ' move cursor left LcdRt CON $09 ' move cursor right LcdLF CON $0A ' move cursor down 1 line LcdCls CON $0C ' clear LCD (use PAUSE 5 after) LcdCR CON $0D ' move pos 0 of next line LcdBLon CON $11 ' backlight on LcdBLoff CON $12 ' backlight off LcdOff CON $15 ' LCD off LcdOn1 CON $16 ' LCD on; cursor off, blink off LcdOn2 CON $17 ' LCD on; cursor off, blink on LcdOn3 CON $18 ' LCD on; cursor on, blink off LcdOn4 CON $19 ' LCD on; cursor on, blink on LcdLine1 CON $80 ' move to line 1, column 0 LcdLine2 CON $94 ' move to line 2, column 0 ' -----[ Variables ]------------------------------------------------------- keyIn VAR Byte ' Holds translated keypad value char VAR Byte ' ASCII char to display dispChar VAR Word ' Display holder for multiple key presses keyCount VAR Nib ' Number of key presses per cycle passCode VAR Word result VAR Byte ' -----[ Initialization ]-------------------------------------------------- Reset_LCD: HIGH LCD ' setup serial output pin PAUSE 100 ' allow LCD to initialize SEROUT LCD, LcdBaud, [LcdBLon, LcdOn1, LcdCls] 'LcdBLoff/LcdBLon PAUSE 250 SEROUT LCD, LcdBaud, [" XANATRONICS"] SEROUT LCD, LcdBaud, [LcdLine2, "Fuel Management"] PAUSE 1000 ' -----[ Program Code ]---------------------------------------------------- Main: ' Ask for data DI, TR#, TRKMLG, SEROUT LCD, LcdBaud, [LcdCls] PAUSE 5 SEROUT LCD, LcdBaud, ["Driver ID & #: "] keyCount = 0 dispChar = 0 DO ' Routine to accept keyboard data (and then store it in eeprom) DO : LOOP UNTIL (kbdDA = 1) ' Wait until Data Available from 74C922 keyIn = INB LOOKUP keyIn, [ 1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12, 14, 0, 15, 13 ], keyIn ' translate kbd matrix LOOKUP keyIn, ["0123456789ABCD*#"], dispChar ' translate key to ASCII SEROUT LCD, LcdBaud, [LcdCls] PAUSE 5 SEROUT LCD, LcdBaud, [LcdLine2, dispChar, " "] IF (keyIn = 14) THEN ' 14 = * (Abort and go to beginning) keyCount = 0 GOTO Main ELSEIF (keyIn = 15) THEN '15 = # (Accept entry and go to next op) keyCount = 0 EXIT ENDIF PAUSE 5 DO : LOOP UNTIL (kbdDA = 0) keyCount = keyCount + 1 LOOP PAUSE 2000 ' Replace this with routine to accept keyboard data and PUT to eeprom GOTO MainIn looking at the code you'll see that there are two values I have available for the keyboard's input - the raw keyIn value that I get after the first LOOKUP, and the dispChar value that comes from the second LOOKUP of the keyIn value. I can get the LCD to display either properly as a single digit. When I use the keyIn value, I can do the * 10 trick to move the first digit to the left one space and then add the next incoming digit to display two characters on the LCD. I have also done this by using dispChar and subtracting 48 which gives me the same number. But multiplying the dispChar value by 10 does not work - I get very odd characters (looks like japanese symbols). When I use keyIn I sepcify DEC. dispChar displays without needing to specify DEC or anything.
I've been using KeyCount to determine where in the loop the number should be. While it's not in the code above (since it didn't work), what I was using is something along these lines (code paraphrased):
if keyCount = 0 THEN SEROUT dispChar to LCD ELSE dispChar = (old dispChar * 10) + new dispChar SEROUT dispChar to LCD ENDIFBack to the (last keyIn * 10) + new keyIn method... This works for up to two characters. The third never shows up, I only get two characters. So if I type 3, it displays 3. Then I push 6, and I get 36. Then I push 9 and I get 69. Push 9 again and I get 99. Push 3 again, I get 93.
I've even tried setting it to DEC3, and I get 000, 003, 036, 069, 099, and 093 respectively.
Ultimately, my app will need to take a three digit number, followed by #, another 3 dig + #, a 6 digit + # (which will be very interesting because I will need to capture this number and store it in a datalogger, but the number will always exceed 65535... so there's probably another plea for help in the future)... anyway, I need to be able to display, and capture all these entries so I can store them on a datalogger. That part I already have working just fine - it seems to only be the display parts that are stumping me. Shouldn't it be possible for me to just keep typing numbers across the LCD screen until I finally enter the special character that makes it store the number and move on?
I've read N&V #97 several times and I can't seem to see why that code works on that display but not on my regular old Parallax Serial LCD.
So I appreciate your help quite a bit. My brain is fried at this point! :-)
Thanks very much,
Dave
' {$STAMP BS2sx} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ I/O Definitions ]------------------------------------------------- kbdDA PIN 3 ' Keyboard Data Available line from 74C922 kbd0 PIN 4 ' Keyboard bit 0 from 74C922 kbd1 PIN 5 ' Keyboard bit 1 from 74C922 kbd2 PIN 6 ' Keyboard bit 2 from 74C922 kbd3 PIN 7 ' Keyboard bit 3 from 74C922 These are all now on INB LCD PIN 14 ' Parallax Serial LCD Display ' -----[ Constants ]------------------------------------------------------- LcdBaud CON 110 ' LCD Baud derp LcdBkSpc CON $08 ' move cursor left LcdRt CON $09 ' move cursor right LcdLF CON $0A ' move cursor down 1 line LcdCls CON $0C ' clear LCD (use PAUSE 5 after) LcdCR CON $0D ' move pos 0 of next line LcdBLon CON $11 ' backlight on LcdBLoff CON $12 ' backlight off LcdOff CON $15 ' LCD off LcdOn1 CON $16 ' LCD on; cursor off, blink off LcdOn2 CON $17 ' LCD on; cursor off, blink on LcdOn3 CON $18 ' LCD on; cursor on, blink off LcdOn4 CON $19 ' LCD on; cursor on, blink on LcdLine1 CON $80 ' move to line 1, column 0 LcdLine2 CON $94 ' move to line 2, column 0 ' -----[ Variables ]------------------------------------------------------- keyIn VAR Word ' Holds translated keypad value charHold VAR Word ' Holds multiplied values dispChar VAR Word ' Display holder for multiple key presses keyCount VAR Nib ' Number of key presses per cycle passCode VAR Word result VAR Byte ' -----[ Initialization ]-------------------------------------------------- Reset_LCD: HIGH LCD ' setup serial output pin PAUSE 100 ' allow LCD to initialize SEROUT LCD, LcdBaud, [LcdBLon, LcdOn1, LcdCls] 'LcdBLoff/LcdBLon PAUSE 250 SEROUT LCD, LcdBaud, [" XANATRONICS"] SEROUT LCD, LcdBaud, [LcdLine2, "Fuel Management"] PAUSE 1000 ' -----[ Program Code ]---------------------------------------------------- Main: ' Ask for data DI, TR#, TRKMLG, SEROUT LCD, LcdBaud, [LcdCls] PAUSE 5 SEROUT LCD, LcdBaud, ["Driver ID & #: "] keyCount = 0 dispChar = 0 DO ' Routine to accept keyboard data (and then store it in eeprom) DO : LOOP UNTIL (kbdDA = 1) ' Wait until Data Available from 74C922 keyIn = INB LOOKUP keyIn, [ 1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12, 14, 0, 15, 13 ], keyIn ' translate kbd matrix LOOKUP keyIn, ["0123456789ABCD*#"], dispChar ' translate key to ASCII IF (keyCount = 0) THEN IF (keyIn < 10) THEN SEROUT LCD, LcdBaud, [LcdLine2, DEC keyIn, " "] charHold = keyIn * 10 ENDIF IF (keyIn = 14) THEN ' 14 = * (Abort and go to beginning) SEROUT LCD, LcdBaud, [LcdLine2, dispChar, " "] PAUSE 100 keyCount = 0 GOTO Main ENDIF ELSEIF (keyCount > 0 AND keyCount < 5) THEN IF (keyIn < 10) THEN charHold = charHold + keyIn SEROUT LCD, LcdBaud, [LcdLine2, DEC charHold, " "] charHold = charHold * 10 ENDIF IF (keyIn = 14) THEN ' 14 = * (Abort and go to beginning) charHold = charHold/10 SEROUT LCD, LcdBaud, [LcdLine2, DEC charHold, dispChar, " "] PAUSE 500 keyCount = 0 GOTO Main ELSEIF (keyIn = 15) THEN '15 = # (Accept entry and go to next op) charHold = charHold/10 SEROUT LCD, LcdBaud, [LcdLine2, DEC charHold, dispChar, " "] PAUSE 500 keyCount = 0 EXIT ENDIF ELSEIF (keyCount > 5) THEN IF (keyIn = 14) THEN ' 14 = * (Abort and go to beginning) charHold = charHold/10 SEROUT LCD, LcdBaud, [LcdLine2, DEC charHold, dispChar, " "] PAUSE 500 keyCount = 0 GOTO Main ELSEIF (keyIn = 15) THEN '15 = # (Accept entry and go to next op) charHold = charHold/10 SEROUT LCD, LcdBaud, [LcdLine2, DEC charHold, dispChar, " "] PAUSE 500 keyCount = 0 EXIT ENDIF ENDIF PAUSE 5 DO : LOOP UNTIL (kbdDA = 0) keyCount = keyCount + 1 LOOP SEROUT LCD, LcdBaud, [LcdCls] PAUSE 5 SEROUT LCD, LcdBaud, ["Next task .... "] PAUSE 2000 ' Replace this with routine to accept keyboard data and PUT to eeprom GOTO MainAm I on the right track, or am I doing something far more convoluted here than I really need to be?
Thanks,
Dave
I have two suggestions and that's all they are, but they may or may not make things easier in the long run. The first is you're doing two LOOKUP commands when all you need is one. In your case it seems as if in the first one you're trying to get you ducks in a row, so to speak, in order to make the second LOOKUP be in alphabetical order. You don't need to do this...instead just order the ASCII values in the second lookup in order that the codes are returned by the 74C922.
The second thing is that I would deal with the raw values and only format the data going to the LCD. This will make your dealing with the values much easier. If you use a fixed length field you can simplify printing to the LCD as values are added since it will reprint the entire field (3 characters?).
I concur re: the double lookup. I really only need to set the displayed char to # or * under those specific circumstances. The raw keyIn values are fine elsewise.
I'm not sure what you mean by a "fixed length field". How do I go about specifying this and does this replace all my *10 math stuff?
Thanks!
Dave
Fixed length field is when using formatters to send the data to the LCD. It would not interfere with your math because you're formated the output of the data only. In fact, done right you would not need a separate variable for what goes on the display.
I'm only partially following you here.... You're referring to formatters like DEC3, for example, to send a fixed-length (in this case, 3 digit), correct? I guess I'm not seeing how I could eliminate the need for a separate variable for what goes to the display. Also - when I specify DEC3, or DEC5, I get a bunch of leading zeros. Is there any sort of Leading Zero Suppression function available? :-)
Thanks,
Dave
IF value < 10000 THEN SEROUT LCD, LCDBAUD, [" "]
IF value < 1000 THEN SEROUT LCD, LCDBAUD, [" "]
IF value < 100 THEN SEROUT LCD, LCDBAUD, [" "]
IF value < 10 THEN SEROUT LCD, LCDBAUD, [" "]
SEROUT LCD, LCDBAUD, [DEC value]
Thanks again guys!
Dave
For output, you'd use a variation on what I showed above with one sequence handling 1000-999999 and the other sequence handling 0-999.
Thanks.
I apologize for the confusion. If your numbers are only ever 1 to 3 digits you can use the modifiers and/or a position change when printing which can be done in a SELECT...CASE statement only for display purposes. So when you type in a single decimal number it appears right-justified (calculator style) and as you type each digit the current value is multiplied by 10, but the display routine checks to see if the value is a single, double or triple digit value and positions/formats the value accordingly.
By the way...in response to your signature tag line...I can count to 32 (0-31) on one hand.
So, using your variable as an example:
SELECT keyIn CASE 0 TO 9 SEROUT LCD, LcdBaud, [LcdLine2 + 2, DEC inKey] CASE 10 TO 99 SEROUT LCD, LcdBaud, [LcdLine2 + 1, DEC inKey] CASE 100 TO 999 SEROUT LCD, LcdBaud, [LcdLine2, DEC inKey] ENDSELECTThis is on the assumption that you want the text right-justified (calculator style) as I thought originally, though after looking at your more complete code I am not sure that's what you wanted.
Also this code takes up more memory than what is necessary to get the point across. It could be simplified by replacing each SEROUT in the CASE evals with a position/offset aded to the LcdLine2 location for positioning.
I don't have any 74C922 chips anymore or I would write you some example code. I now use the EDE1144 and have plenty of examples for them, but since they have the ability to send the code parallel or serial I use the serial method to save three I/O pins and therefore my examples would look a bit different on the receiving end.
Yes, things move swiftly because I obsess over any oddity in code or function! I'm quite happy with the characters filling in from L to R as I have it now, and I am doing both that and successfully capturing the data that's entered, having converted the keyboard reader section into a subroutine.
Thanks very much to all of you who helped me here. You are a huge part of what makes Parallax such a fantastic organization.
Dave
Dave
PS., I don't consider my thumb a finger I guess! :-)
No problem...they even have an EDE1188 I believe which is 8x8 Matrix. As for the thumb...you could always think of it as a sign bit, giving you +/- counts!
There's so much cool stuff out there... I wish I had the time to find out about them all! :-)
Thanks again,
Dave
That's the great thing about these forums. With so many people there's alway a good pool of information. I myself have learned about things I didn't know via these forums. As always, if you like you can always post projects in the projects forum. Take care.