Post Reply 
Generic Calculator Shield for Arduino Photo-journal
03-18-2015, 11:23 PM (This post was last modified: 03-18-2015 11:31 PM by MarkHaysHarris777.)
Post: #35
RE: Generic Calculator Shield for Arduino Photo-journal
Greetings, as most of you know there are two ways to read a keyboard (analog and digital) and there are two ways to do each of those... (polling, and hardware interrupts).
I need the GPIO lines for printing, IR, motorized pen plotter, and RTC... so we need to minimize the I|O pins used, and that means that we are going to read the keyboard (interrupt driven) either serial (similar to a PC keyboard) or analog. Since these boards have built-in A2D with very nice resolution, and built-in hardware interrupt lines with supporting library... the chosen solution is to read the keyboard based on hardware interrupt, with analog lines (four of them in my case). I need two lines reserved for the RTC, and I can map the keyboard wiring to a virtual 9x4 matrix so that I can read the entire 35 keys with four analog I|O pins and one hardware interrupt line (0) on pin 2.
I have included a hi-res pic today of the proto-board for binary-calc along with the schematic of a 'single' column of 9 rows... the rest of the board is just the same, each line having its own 339 event trigger (the cool thing there is that the open collectors of the 339 allow them to be wired 'OR' so that they can all drive the interrupt pin 2 easily.

[Image: analog-keybuttons-arduino2.jpg]

Here are some code snippets so that you can see what the sketch looks like to handle the interrupt. First we need to attach the interrupt:

Code:

  attachInterrupt(0, keyScan, FALLING);

We specify the interrupt line (0, on pin 2) then the routine to be called when the interrupt fires (in this case keyScan) and whether the the interrupt should fire on a rising strobe, or a falling ground shot. Then we need to code the keyScan routine:

Code:


void keyScan() {
    int i;
    int val;
    int flag= -1;
    val = getButtonCode(analogRead(potline));
    if (val!=0) {
        for (i=1; i<=7; i++) {
            if (val!=getButtonCode(analogRead(potline))) flag= 0;
            nopDelay(1200);
        }
        if (flag< 0) {
            print_key_code(val);
            keyCode=val;
            interruptFlag=0;
        }       
    }
}

int getButtonCode(int analogCode) {
   return (analogCode + 40) / 100;
}

-

I should explain the nopDelay() and the for (loop). Normal delay() does not work during an interrupt handler... (rats) so we need another way to slow things down a bit ( nopDelay() ) and we need to make sure that the key we 'got' is really the key that was read. To put this bluntly and succinctly, this method (LM339 and voltage divider) is VERY unreliable; especially because of key bounce, but also because of the LM339 hysteresis. Consequently, because we don't want to employ Schmidt triggers, and other components that over complicate the keyboard, we leave the hardware unreliable (as it were) and fix it in software. This is one of those places. The other comes next, in the interrupt clear mechanism:

Code:


  // process any keyCodes and clear the interrupt flag  
  if (interruptFlag==0) {
     noInterrupts();
     int i;
     int val;
     int flag= -1;
     if (keyCode!=0) {
         prevDigit=digit*10;
         digit=keyCode;
         commandDisplay=prevDigit+digit;
         displayDecValue(commandDisplay, INVERTED);
         keyCode=0;
     }
     for (i=1; i<=7; i++) {
         val = analogRead(potline);
         if (val>44) flag=0;
         nopDelay(100);
     }
     if (flag<0) {
         interruptFlag= -1;
         interrupts();
         delay(200);
     }
  }

  // process command line  
  if (interruptFlag== -1) {
    if (commandDisplay==99) {
      commandDisplay=0;
      displayCounterDriver(255, HEXIDECIMAL, INVERTED);
    }
  }

-

This code helps makes sure that we don't get more than one interrupt per keypress, reduces contact bouncing symptoms, and pretty much finishes making the 'unreliable' hardware function reliably! -- and boy does it ever! I have completely eliminated the keybouncing symptoms, and since playing with this thing since this morning at 5:30, I have had NO keyboard failures. Yeaah.

Well, its time to throw this mess on the real thing (meaning, time for me and my assistant to pull out the 'ol soldering iron... ) my favorite part!

Cheers,
marcus
Smile

Kind regards,
marcus
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: Generic Calculator Shield for Arduino Photo-journal - MarkHaysHarris777 - 03-18-2015 11:23 PM



User(s) browsing this thread: 1 Guest(s)