Let's Stop Reinventing the Wheel!
When we take a closer look at circuits using a microcontroller, it can be seen that in 75 % of cases the basic circuit is virtually identical: a microcontroller, an LCD display, and a few push-buttons. This observation is nothing new, and Elektor in particular has already suggested several solutions. This project presents yet another way of going about it, a little bit more universal, which allows the use of several types of LCD and a variable number of buttons.
The type of displays usually used in amateur projects generally have either 2 lines of 16 characters (2×16), or 4 lines of 20 characters (4×20). There are rarely more than four buttons, but rotary encoders are increasingly being seen. For circuits using a 2×16 LCD, the buttons are often below the display; for the 4×20 displays, they are more likely to be mounted to the side. The position of the buttons depends on the application and the user; a right-handed person tends to position them differently from a left-handed person. A universal solution must take all this into account and allow a free choice of the LCD and the position of the buttons.
Even though I’d originally had the idea for this circuit several years ago, I started actually building it quite recently, when for the umpteenth time I needed to add an MMI to a circuit that didn’t have enough I/Os free; so I needed an additional port extender. Since NXP brought out their 32-bit ARM Cortex-M3 and M0 microcontrollers, cheaper than port extension devices, an ingenious and inexpensive solution is now possible. Particularly interesting for amateurs, this is the LPC1343, currently the easiest microcontroller to program. No need for a programmer or an RS-232/USB adaptor — this microcontroller is presented quite simply as a USB stick onto which all you have to do is copy the software (only works under Windows; using Linux or MAC OS, you have to use a serial link or a special programmer).
Using a microcontroller like this as a port extender, we get USB, I²C, and SPI ports or a UART for communicating with the application. If we note that in most applications managing the display and the keyboard takes up easily 80 % of the software, we can likewise envisage having the whole application run by the microcontroller – especially when we have the computational power of a 32-bit processor available. So, instead of adding a port extender to an application, we can add an application to a port extender. Since the microcontroller is only available in an SMD package, I decided to use only SMD parts throughout (with the exception of the connectors and keyswitches). In the relatively confined space, cluttered with connectors, this allowed other functions to be added, like powering by rechargeable batteries or primary cells, and a charger for Lipo batteries. This means that the board is also suitable for mobile applications. And to round everything off nicely, the board dimensions are suitable for a standard, cheap case, for a neat, robust finish for your project.
- Suitable for 2×16, 4×16, and 4×20 LCD displays using a standard 14- or 16-pin connector (the latter if backlight is included), software-controlled backlight
- 5×6 matrix keypad for a maximum of 12 keyswitches or nine rotary encoders with built-in push-button (equivalent to 27 pushbuttons!) or a mixed configuration
- One LED
- Power via USB, external 5 V supply, primary cells (0.9–4.5 V) or Lipo rechargeable battery
- 5 V and 3.3 V regulators, software on/off control possible
- Lipo battery charger, plus software measurement of battery level
- 32-bit, 48-pin LPC1343 microcontroller with 32 KB Flash memory, 8 KB RAM and numerous peripherals like USB, I²C, SPI, MLI, UART, and counters
- Compatible with the free LPCXpresso and CooCox IDEs
- Compatible with the LPC-Link and CooCox programmers/debuggers
- Extension connectors: almost all the microcontroller pins are available on a connector or a pad
- Splittable! Certain unused parts can be cut off; detachable mini 4-key pad or a maximum of 3 rotary encoders
- Dimensions adapted to Type 26160000 case from Bopla;
- Open source software and hardware.
Let’s start with the board’s brain, the microcontroller. An oscillator is necessary to make it work, and so three options present themselves: the internal RC oscillator (IRC), an external oscillator, or an external clock (which we are not using here). The microcontroller starts up on its internal oscillator. For applications requiring a more accurate clock, provision has been made to allow a crystal oscillator to be fitted. The microcontroller’s data sheet advises values of 18 pF or 39 pF for C14 and C15, depending on the crystal used. However, most crystals ought to be able to operate with either of these values.
The logic levels on PIO0.1 and PIO0.3 select the microcontroller’s start-up mode after a reset. If PIO0.1 is low, the microcontroller will first run its bootloader (ISP mode), otherwise the user program will be run. The LPC1343 offers two ISP modes: by USB stick (PIO0.3 high) and by serial port (PIO0.3 low). Resistors R3 and R13 let us select the ISP mode. In theory, the function of R3 is also fulfilled by the USB voltage detection circuit, but fit it all the same in order to avoid any possible indeterminate situations, if ever the USB cable should not be connected (correctly). Fit R13 instead of R3 if you prefer to program the chip via a serial link.
Note that there is a bug in the LPC1343’s built-in USB driver, which means you have to wait around 30 s before Windows will detect the “stick” the first time you connect it for a programming session. After that, the detection takes place normally for as long as the microcontroller remains powered. The microcontroller can also be programmed via an SWD (Serial Wire Debug) port, a sort of serial JTAG. Connector K3 has been provided for this purpose, wired in such a way as to be compatible with the LPC-Link used by the free LPCXpresso programming environment. The LED (D34), connected to PIO0.7, is also LPCXpresso compatible, which means that the little test program LPCXpresso1343_blinky included in the IDE ought to work without any modification.
The keypad consists in principle of twelve switches, four to the left of the display, four to the right, and four below (with a 2 × 16 display). The idea is to also be able to use rotary encoders in place of switches; an encoder of this type with built-in push-button is equivalent to three switches. Three encoders take up the same space as four switches. To leave as much freedom as possible in positioning the switches and encoders, I decided to allow up to nine ncoders (in point of fact, I do have an application that needs that many rotary encoders). So nine encoders with built-in buttons correspond to 27 keys, thus a 5 × 6 matrix is needed to connect all the keys using a minimum of I/Os. The matrix is wired in such a way that if you are only using one of the three groups of four keys (left, right, or bottom), only four I/Os are needed for scanning these four keys. The I/Os freed up in this way are available for some other function. JP1 makes it possible to optimize the position of S5 in the matrix.
I have used diodes to avoid the problem of phantom keys if several keys are pressed at once – a situation that can easily arise when you’re turning two encoders at the same time. The diodes are in a SOD323 package, allowing them to be replaced by resistors, in case you might want, for example, to fit one or more LEDs in place of certain keys.