HP Forums

Full Version: Generic Calculator Shield for Arduino Photo-journal
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
(03-11-2015 10:58 PM)MarkHaysHarris777 Wrote: [ -> ]But still, even at that, with all 24 bars 'ON' my little display is drawing about 184 mA. Even limiting the current a dual twelve digit seven seg display would draw a little more than 1.3 amp---

I'm not aware of any seven segment display device that is not multiplexed. The human eye is so slow that you will not notice a flicker unless you move the device in front of you. Multiplexing will reduce the power requirements to what a single digit or segment (depending how far you go with multiplexing) draws.
(03-12-2015 07:23 AM)Marcus von Cube Wrote: [ -> ]Multiplexing will reduce the power requirements to what a single digit or segment (depending how far you go with multiplexing) draws.
The other way to reduce power consumption would be to reduce the current given to the segments.
(03-12-2015 07:23 AM)Marcus von Cube Wrote: [ -> ]I'm not aware of any seven segment display device that is not multiplexed. The human eye is so slow that you will not notice a flicker unless you move the device in front of you. Multiplexing will reduce the power requirements to what a single digit or segment (depending how far you go with multiplexing) draws.

Yes... similar to PWM; only one digit is 'ON' at any one time... so, let's say we have 24 digits-- that means that at any moment in time 23 digits are technically 'OFF' but because of persistence of vision we still see them 'ON'... but, because they are off most of the time, it seems somewhat higher voltage would be required (or smaller current limiting resistors) so that the digits light just a little brighter for the 1/24 time that they are actually 'ON'?

I do actually see the flicker with my eye... and it drives me crazy (near sighted people are more sensitive to the condition for some reason). My display flickers a bit too because the 24 bits that fly by actually hit all LED bars before they come to rest. Since I have no latch enable line on my 273 devices I can actually see the flicker each time the display is written... but only because I'm sensitive to it, and partially because I'm looking for it.

Well, for a large display, multiplexing is required; a relatively mute point for me, since I probably won't be motivated to actually build my Wang 700c replica... but, I'm crazy, and you never know!

Cheers,
marcus
Smile
Greetings, well, the physical platform is taking shape. There are several 16x2 (similar) LCD displays to choose from, all well documented on the net. I have chosen the LMB162ABC (Topway) display containing green/yellow backlight LCD, controller, and multiplexer built-in. This is a 5v display, is well supported and can be written to with a standard library (probably the easiest option for most people to build up from, also has the most net support in terms of examples and trouble shooting). As usual there is a hi-res pic behind the thumb pic:

[Image: b2-keyboard-display2.jpg]

I have chosen to orient the display similar to the C series HP calcs; although, rather than 10x4 keyboard, this prototype will have 7x5, with the [ENTER] key vertical in the third column. Keyboard layouts will be coming later.

Again, this development prototype is designed to have the micro-controller beneath the keyboard back-plane attached via ribbon cable and headers. Optional 3v jumpers will be provided. Initially the 5v supply will come from the micro-controller, but a 7805 or 3v equivalent may be required. Also, contrast pot and optional back light jumper will be provided; full schematic will follow, with keyboard voltage divider and interrupt circuit.

Cheers,
marcus
Smile
(03-14-2015 10:28 AM)MarkHaysHarris777 Wrote: [ -> ]I have chosen to orient the display similar to the C series HP calcs

Which exactly is...?

:)
Greetings, the 16x2 back-lit display is operational using the LiquidCrystal library which provides support for displays compatible with the Hitachi HD44780 driver. I am using the Topway LMB162ABC LCD wired for four(4) bit and two control lines. As wired the Arduino 'hello,world!' example will run unmodified. This display is quite easy to put together from a hardware perspective, and very easy to write. Basically, you set the cursor, and write 'text' to one of the two output display lines. Hi-res pics first, code following:

[Image: pi-e-display2.jpg] [Image: arduino-display-wiring2.jpg]

Code:

/*
  Generic Calculator

 LCD Display:
 
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 15K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 */

// include the library code:
#include <LiquidCrystal.h>
#define BACKLIGHT 9

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  analogWrite(BACKLIGHT, 220);
  clearDisplay();
  say(0,0," Power-on Reset ");
  delay(1000);
  clearDisplay();
  say(0,0,"Calculator v0.01");
  say(0,1,"mh15cs");
  delay(1500);

}

void loop() {
  // print the number PI:
  say(0,0,"3.14159265358979");
  // print the number e:
  say(0,1,"2.71828182845904");
  delay(5000);
  // print the number PI:
  say(0,1,"3.14159265358979");
  // print the number e:
  say(0,0,"2.71828182845904");
  delay(5000);
}

void clearDisplay() {
  int i;
  for (i=0; i<=1; i++) {
      lcd.setCursor(0, i);
      lcd.print("                ");
   }
}

void say(int col, int lin, const char* outp) {
   lcd.setCursor(col, lin);
   lcd.print(outp);
}

-

The pot in the upper left is used to adjust the display contrast. The back light (yellow|green for the ABC model) is optional. I have provided a jumper which may be used to turn off the back light to save power. The display is of course easier to read with the back light, but is acceptable without it.

The display supports an 8 line data bus, of which I am using the high-order four(4) bits. {D4green(pin5), D5blue(pin4), D6violet(pin3), & D7grey(pin2)} RS(orange) is on pin 12, and Enable(yellow) is on pin 11. The red line is Vcc 5v (rail is on the end of the board), and the tan line is Vss ground, rail runs through the center.

This wiring diagram is the most common LCD wiring used with the 16x2 displays and the Arduino. Of course the same will work fine with any of the boards (Mega is shown) and also the Edison with the Arduino break-outs and Arduino IDE; I will be trying that shortly.


PS Since posting this update (while leaving the display on) the voltage regulator on the Mega got quite warm (hot even). So, the board is going to need its own 7805, if I run it with the back light lit up.

PPS I updated the code a bit...

Cheers,
marcus
Smile
Greetings, I decided to handle the LCD back-light problem before continuing. Connected directly to the 5v supply the back-light draws 100 mA (dissipates 500 mW). So, I placed a 2N4401 switching transistor in-line with the back-light; driving it with pwm (pulse width modulation) on pin 10. I set the analogWrite(10, 120) so that the back-light is operating at 18 mA.

[Image: backlight-transistor2.jpg] [Image: backlight2.jpg]

This has really killed two birds with one stone, as it were, because one of the generic calculator functions (as well as contrast) should be to set the display back-light (on|off) with dimmer option.

Cheers,
marcus
Smile
Greetings, today's mods help to move this board toward its generic goal, being able to interface as a generic calculator shield for both 3.3 and 5 volt systems; specifically, I want this same board to be able to be a calculator interface for both the Arduino Mega2560 and the Arduino Due. The Due is the first Arduino with an Arm core, having the following benefits:

-A 32-bit core, that allows operations on 4 bytes wide data within a single CPU clock.
-CPU Clock at 84Mhz.
-96 KBytes of SRAM.
-512 KBytes of Flash memory for code.
-a DMA controller, that can relieve the CPU from doing memory intensive tasks.

Some hi-res pics, then some comment about the interface:

[Image: lm339-due2.jpg] [Image: lm3392-due2.jpg] [Image: lm3393-due2.jpg]

The beauty of the Due is the 32 bit Arm core, lots of memory, fast, and a DMA controller... the bad news is that unlike the other Arduinos its a 3.3 volt system... and its not forgiving. DO NOT put more than 3.3 volts on ANY I|O pin... you've been warned. There are two opportunities for failure:1) exceed 3.3 volts on any pin, and 2) fail to provide a full logic level high on the interfacing 5v system. Both of these problems are solved by placing a voltage comparator between each I|O pin and the 5v system. I have tucked two LM339 quad comparators under the display module. I am buffering the two control lines, the four data bus lines, and the backlight driver transistor. From the second pic you can clearly see the bus, the ref voltage divider, and the I|O pullup resistors.

The third pic is the schematic for the LM339 (used for each I|O pin). This is a ton of work, but necessary to ensure flawless operation while cross developing for several boards. All good shields support 3.3 and 5 volt systems.

PS I updated the code a bit (couple of slides back), to reflect the back light pin 9, analogWrite(BACKLIGHT, 220), and to show how to embed low level calls in more useful high level calls for display control... clearDisplay(), and say().

Cheers,
marcus
Smile
(03-16-2015 04:59 AM)MarkHaysHarris777 Wrote: [ -> ]The beauty of the Due is the 32 bit Arm core, lots of memory, fast, and a DMA controller... the bad news is that unlike the other Arduinos its a 3.3 volt system... and its not forgiving. DO NOT put more than 3.3 volts on ANY I|O pin... you've been warned. There are two opportunities for failure:1) exceed 3.3 volts on any pin, and 2) fail to provide a full logic level high on the interfacing 5v system. Both of these problems are solved by placing a voltage comparator between each I|O pin and the 5v system. I have tucked two LM339 quad comparators under the display module. I am buffering the two control lines, the four data bus lines, and the backlight driver transistor. From the second pic you can clearly see the bus, the ref voltage divider, and the I|O pullup resistors.
Mark: You can also buy 8 bidirectional level translators in a nice package from adafruit here Or for quad I2C compatible (I/O's with pullups less than 50k) level translators here
(03-16-2015 09:47 AM)BarryMead Wrote: [ -> ]Mark: You can also buy 8 bidirectional level translators in a nice package from adafruit here Or for quad I2C compatible (I/O's with pullups less than 50k) level translators here

Thanks, Barry. Actually, for my purposes I've been looking at this level shifter from adafruit. It is essentially an octal chip that combines the functionality of the LM339, with voltage reference, and pullup resistors, in one in-line pack that can be soldered into a proto-board permanently. I have a couple on order, along with a couple of the ones you pointed me to. Those will be good for mounting headers for use with solder-less bread boards. I'm planning to make one more calculator shield (red boards, blue (20 character by 2 line) back-lit display with white lettering) and I'm planning on using the 74LVC245 there. Thanks again.


PS I did not make clear the fact that the 74LVC245 has tri-state logic... meaning, that it can provide buffering for both output AND input. See the datasheet to learn more.


Cheers,
marcus
Smile
Greetings, ... now that I've begun work on the keyboard it has become important to firm-up the platform, provide just a bit more space below, and level the pcb. I've placed the metric machine hardware so that the pcb is 3.4 cm above the table top.

[Image: levelers2.jpg]

The Arduino Uno is driving the generic calculator shield; displayed in the aluminum Tux Case from MakerShed, from Tux Labs.

Cheers,
marcus
Smile
Mark: What did you have in mind for "KEY" labels? There doesn't seem to be much room between the keys, and the tall switches aren't friendly to a paper overlay. Are you planning to keep a "Cheat Sheet" off to the side?
Perhaps you are planning to have the switches poke through holes in a plastic, or metal cover plate where you will have lots of room for labels?
(03-17-2015 02:39 AM)BarryMead Wrote: [ -> ]Mark: What did you have in mind for "KEY" labels?

... thought I would keep that a secret for a while longer. ;-)

Initially, they are going to be very high tech... index card cut-outs printed on the laser printer. There will be an overlay similar to Eric's vinyl overlay, only my initial pass will be paper... and the keys will be tabs glued at the front, which come up and over the key to the rear (printed on the laser printer). That will be a bunch of paper doll work too, but quick and cheap/

Eventually, the buttons are going to be 3D micro printed plastic, rotate-and-click, similar to classic HP keyboards. Picture a plastic frame of rotating buttons that drops down on the pbc platform.


PS The 16x2 LCD display is actually an internal register of 80 characters (full alpha-numeric). The cursor may be placed anywhere within the register to begin the 'write'. Typically the 80 column register is thought of as two (two lines) 40 character alpha-numeric registers. The display may be 'scrolled' left and right; has serious possibilities.

PPS What if your calculator drove a 2D motorized programmable plotting table (X Y axis, pen-up|down)? This one is going to...


Cheers,
marcus
Smile
Greetings, well, my personal analog keyboard R&D is mostly complete and I finally have a fully functional single column nine(9) button analog event (interrupt) driven keyboard. The keyboard is comprised of a voltage divider network (shared among all analog lines (4) and an LM339 comparator used to provide a 'falling' hardware interrupt (0) on pin 2. The interrupt handler routine then 'scans' the keyboard converting the analog-to-digital number 0-1023 to an integer in the range 1-9. On the actual keyboard a keyCode will be constructed (col,row) where '47' would represent column 4, row 7. The keyboard is 5x7 landscape, but will be wired logically as a virtual 4x9 portrait. Pics, then comment:

[Image: keyboard-analog-input2.jpg] [Image: keyboard-analog2-input2.jpg]

In the first pic I have just pressed button(s) '3' followed by '7'. The buttons are logically numbered 9-1 as you move towards the IC (LM339). I am retrieving the button code, and then displaying it to the LED display, as well the virtual display console (VT102) on the PC. You'll notice the digital keyboard has been removed from the shield (no longer needed) nouns and verbs can now be communicated via the analog keybutton panel (binary calc only needs five(5) of the nine(9) buttons.

The second hi-res pic is a close-up of the solderless bread board; you can clearly see the voltage divider, reference divider, and LM339 used to trigger the falling edge interrupt on pin 2 of the Arduino Uno (interrupt 0).

The 'zero' button analog-digital signal is '44'. The 'rest' baseline is '24'. The button numbers range from 134 to 875. The LM339 places the '44' on the non-inverting input, and monitors the other buttons as the interrupt line moves above '44'; the falling leading edge of the 339 output triggers the '0' interrupt on pin 2 leading to keyScan routine being called. The rest is display history.

Today I begin work on the actual prototype keyboard, now that I know my voltage divider | monitor schema works fine.

PS In case you were wondering, yes, I had key-bounce problems galore. Some of it I smoothed out by adjusting the pullup resistor on the output of the 339... and the rest I smoothed out with the keyScan and interruptClear routines in the firmware. What a fit. Did I ever mention that I hate contact bouncing switches!

Cheers,
marcus
Smile
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
(03-17-2015 02:39 AM)BarryMead Wrote: [ -> ]Mark: What did you have in mind for "KEY" labels? There doesn't seem to be much room between the keys, and the tall switches aren't friendly to a paper overlay.

hi everyone, take a look at this.


Cheers,
marcus
Smile
Well, Marcus, there are some rather "unorthodox" design decisions in your proposed solution... Since you mentioned that you intend to use this as an educational project not just for yourself but also as an example to be taught to others, I assume you are posting this here in order to get some review and constructive feedback. That's why I'd like to comment on some aspects of your design.

The first is your choice of an analog readout of the keyboard. While this may work for a few keys, it would become unreliable if you'd need to work with more keys per row. Also, it needs hardware or software calibration or active compensation to make it work over a large batch and long time frame and with different voltages. It is prone to EMI problems (you will get misreadings near EMI sources), is slow compared to a digital readout and it consumes more energy. All this would make it unsuitable for "commercial grade" applications in mobile devices like calculators, I'm afraid.
I understand that you need to save I/Os, however, if the current board does not have enough I/Os, perhaps it's not the best possible choice for the job - after all, there are controllers with lots of I/Os.
While a typical keyboard matrix reduces the number of necessary I/Os for (N/2)^2 keys to N already, using some diode tricks you can increase the number of necessary keys to N^2-N. That is, with four I/Os and four diodes you can already decode twelve keys (instead of four), with six I/Os and diodes thirty keys (instead of nine), and with eight I/Os and diodes 56 keys (instead of sixteen). So, for a keyboard with 35 keys, you'd need seven I/Os and diodes, just two more I/Os than in your current solution, and depending on what else you need, it might be possible to use some of these I/Os for other purposes as well.
Since you are following a distributed controller paradigm anyway, you might also have a look at dedicated keyboard matrix scanner ICs to reduce the number of necessary I/Os on your main controller.

On the software side, you should better draw a clear line between code executed inside and outside of interrupt context. As a general rule, reduce the time spent in interrupt context to the absolute minimum possible and don't use expensive or even blocking resources, because this is affecting your real-time performance and if there is more than one interrupt to be processed, there may be race conditions and dead locks resulting in sluggish or erratic behaviour up to crashes. Also, consider the stack load of subroutines called in your interrupt service routine. So, avoid those delays and time-consuming decoding and printing and just stuff the read values into a circular buffer and leave the evaluation and interpretation of the values in the ring buffer to code executed outside interrupt context, so it won't block anything. While you may not have noticed the ill effects of the current implementation so far, you almost certainly will when things get more complex in the future, and it will be very difficult to track down the actual causes of the problems then.

Hope it helps,

Matthias
Serial RAM is always nice to extend the number of IOs, and they're fairly easy to understand and use. A capacitor per key might be useful, but is maybe not needed. Just an idea.
(03-23-2015 05:29 PM)matthiaspaul Wrote: [ -> ]While a typical keyboard matrix reduces the number of necessary I/Os for (N/2)^2 keys to N already, using some diode tricks you can increase the number of necessary keys to N^2-N. That is, with four I/Os and four diodes you can already decode twelve keys (instead of four), with six I/Os and diodes thirty keys (instead of nine), and with eight I/Os and diodes 56 keys (instead of sixteen).

This sounds interesting. Can you explain the trick in some more detail? Will it allow the detection of keys being pressed simultaneously (n-key roll over)?
(03-24-2015 03:07 PM)Marcus von Cube Wrote: [ -> ]This sounds interesting. Can you explain the trick in some more detail? Will it allow the detection of keys being pressed simultaneously (n-key roll over)?

I think that mattiaspaul is referring to what is sometimes called, "Charlieplexing." Here is a link to the Wikipedia article: Charlieplexing
Here is a link to an article in Electronic Design

For the 4 I/O pins plus 4 diode configuration with 12 keys, there is some ambiguity as to what keys are detected when multiple keys are pressed together. Using 4 tristate I/O pins with 12 diodes supposedly removes all of the ambiguity, so you would have 12 key rollover for your 12 key keypad. I haven't quite understood how the 4 trits of information for the I/O pins (81 states) maps unambiguously to the 4096 possible keyboard key combinations.
Pages: 1 2 3
Reference URL's