One of my students are planning to make a simple musical keyboard with PIC microcontrolers, using MIDI output.

The main problem now is about the pressure/force sensor. I've found a good alternative in this question about flexiforce.

I'm wondering if there is a simpler sensor alternative, without ampops, to be used in AD input.



4 Answers 4


A simple keyboard likely wouldn't even have a force sensor. Most of the pro keyboards only have velocity sensing, i.e. detect two separate positions (released and pressed) and determine the velocity from the time between. Of those that do have pressure sensing, it's often not individual per key. See Channel Pressure. I'd really like to see your results!

  • \$\begingroup\$ Good insights! The on/off state for velocity sensing may be enought! I'll test with my students and post the results here. \$\endgroup\$
    – RMAAlmeida
    Commented Nov 22, 2010 at 10:17
  • \$\begingroup\$ I thought aftertouch was key pressure. There are also (more expensive) keyboards with polyphonic aftertouch. \$\endgroup\$ Commented Feb 17, 2015 at 20:43
  • \$\begingroup\$ Everything depends on how you define "simple". A simple keyboard might, for example, have no moving parts - literally, not even a moving plunger in a switch. The LinnStrument would be an example of such design. The keyboards that have total pressure, do it because their designers didn't know how to cheaply sense per-key pressure. There's nothing inherently simpler about sensing pressure under all keys at once. The mechanical side of it certainly adds some concern. \$\endgroup\$ Commented Feb 17, 2015 at 20:47

There are multiple ways of doing it. I will explain one design that's very cost effective and quite ingenious. It's the design of LinnStrument. You can have a look at its sensor board. Since I didn't do the sensor design, nor do I own a LinnStrument, the below is all a result of reverse-engineering and may not match the original design. Certainly the mechanical and material choices don't.

TL;DR: It's possible to scan a LinnStrument sensor plane using nothing but MCU pins and a resistor per column. No external op-amps nor multiplexers are needed.


The sensor board uses a piezoresistive material such as Velostat. Such material decreases its bulk resistance with increasing pressure. The strips of the material are laid in a grid, and scanned to measure the pressure and position within each cell. I'll elaborate on that below.

A prototype design might look as follows, going top-to-bottom:

  1. adhesive plastic foil cover (large adhesive sheet),
  2. column strips,
  3. double-sided adhesive sheet with large holes cut out at each row-column intersection, to provide an air-gap between rows and columns,
  4. row strips,
  5. a non-conductive base plate (say an acrylic sheet) covered with double-sided adhesive. The base plate should offer a 1/2-3/4 inch margin around the grid, so that the terminations can be properly retained without stressing the rows and columns.

A sheet of thin silicone can be installed on top of this sensor assembly, for a softer feel.

The intersection of each row and column is called a cell.

When assembling, it's fairly important that the columns stick well to the top foil cover, and that the rows stick well to the base plate. This ensures that the air gap will not be prematurely bridged. Thus you should assemble (1)+(2) and (4)+(5) separately, then install the (3) on either one, and then sandwich it up.

If you wish the cells to feel springy and somewhat "weird", you can leave the air-gap enclosed, with air trapped inside. Alternatively, you can cut a small central hole through each cell in the (4)+(5) assembly, prior to sandwiching it with the rest of the sensor. This vents the air gap and offers a different feel.

A half inch on either end of each row and column strip should protrude from this sandwich. Copper tape with conductive adhesive is used to get connections to the ends of each row and column strip. Make sure that you solder connecting wires to the copper tape before you attach them to Velostat. Velostat has very low melting point. You will ruin your painstakingly assembled sensor assembly if you forget that (yeah, I know from first-hand experience).

When mounting the row- and column-strips, it's important to slightly pretension them, so that they are perfectly flat when applied to the adhesives.

As far as I can tell, that's more-or-less Roger Linn's design, inasmuch as the sensor board's picture and the firmware can be used for reference.

With ample experimentation, you should be able to get to cut the Velostat strips using Cricut, while already laminated to either the cover or the base plate. After cutting, you can peel off the thin isolation strips between the rows/columns. This would be useful if you wanted to have a more accurate sensor without swearing each time a column or row stuck down to the adhesive before you got it properly positioned :)


When you actuate four corners of any rectangle on the sensor plane, you short two rows and two columns, and thus effectively take them offline and unusable for other measurements.

To overcome this limitation would require to inter-row pick-offs (connection points) on every column, not only at the ends of each column. For a 4 row matrix, you'd need 5 connections on each column - on each end, and between each row. This would complicate the design.


A basic, single-cell design for Z-axis sensing can be seen here. Since it has a single Velostat square without separate row/column pick-offs, it can't sense the pressure position. A simple modification to this FSR would be to attach narrow column pick-offs along the Top/Bottom edges on the front face, and along the Left/Right edges on the back face. It'd allow read-out of X, Y and Z values.


Z (pressure) detection

  1. Both ends of one row are grounded.
  2. Both ends of one column are attached to the same A/D channel input and a pull-up (divider) resistor. The resistor forms the upper half of a voltage divider, the bottom half is the pressure-sensitive resistance between the row and the column. The sensitivity of each grid position is different, so there needs to be a per-position multiplier applied to normalize the reading.

Once you've detected a touch within a cell, you can do more: you can detect the position of the press within the cell. Thus you can do pitch bending and texture modulation.

X position within the cell

  1. The ends of one row are connected to 0V and VCC, forming a position-to-voltage converter.
  2. Both ends of one column are connected to the same A/D channel.

Y position with the cell

  1. The ends of one column are connected to 0V and VCC, forming a position-to-voltage converter.
  2. Both ends of one row are connected to the same A/D channel.

How to do it on the cheap?

The sensor surface itself can be assembled for under $100 in materials, much less if you aim for a small surface. The most important tools that you'll need are an X-acto knife with sharp blades for it, and a steel ruler to cut the materials. Some experimentation on a single cell is necessary to evaluate the particular materials used.

An ingenious way of scanning such grid without need for any signal conditioning is given below. This is a simplification over the original design, which uses analog switches and some signal conditioning. It still performs adequately and has the advantage of requiring no components external to the MCU, save for a few resistors. The assumption is that rows are physically no shorter than columns - this helps with the accuracy of Z sensing. You can of course play it in any orientation you wish.

All we need to interface to the sensor surface are the GPIO pins: no external switches needed!

The sensor performs adequately even if you connect the A/D channel to only one end of a row or column, and leave the other end floating. This allows us to use the pin multiplexer functionality present in most any MCU with analog inputs.

The sensing of one cell operates as follows, with all other pins set as inputs:

  1. Z: both ends of the row to 0V; one end of the column to A/D and pull-up.
  2. X: one end of the row to 0V, another end to VCC; one end of the column to A/D.
  3. Y: one end of the column to 0V, another end to VCC; one end of the row to A/D.

Suppose we have a 4x4 grid and 8+8+4 GPIO pins, 8 of which can perform A/D conversion. The sensor grid has 16 direct connections to GPIO: two ends of each of 4 rows and columns. Let's label the ends of rows as 0L, 0R through 3L, 3R, for left and right ends of rows 0 through 3 respectively. Let's label the ends of columns as 0T, 0B through 3T, 3B, for top and bottom ends of columns 0 through 3, respectively.

  1. The rL and cT ends go to GPIO pins that can double as A/D inputs.
  2. The rR and cB ends go to regular GPIO pins.
  3. Each cT is connected via a pull-up resistor to another GPIO pin, we can call those pins cD.

The sensing of a cell with given row and column is then achieved by simple reconfiguring of GPIOs. The trick is to realize that any GPIO configured as input is effectively disconnected.

  1. Z

    • rL and rR set as output, driven to 0.
    • cB set as input.
    • cT set as A/D input.
    • cD set as output and driven to 1. This connects the top half of the voltage divider to the cell.
    • All others set as inputs.
    • The A/D value is proportional to Z force, with different scale for each cell.
    • Once a given cell is classified as "touched", you can then also obtains its X and Y value.
  2. X

    • rL set as output, driven to 0.
    • rR set as output, driven to 1.
    • cB set as input.
    • cT set as A/D input.
    • All others set as inputs.
    • The A/D value is proportional to the X position.
  3. Y

    • cB set as output, driven to 0.
    • cT set as output, driven to 1.
    • rL set as input.
    • rR set as A/D input.
    • All others set as inputs.
    • The A/D value is proportional to the Y position.

There is some logic involved in tracking a touch as it moves between cells, but this can be ignored if the sensor is designed with wide large cells - say 1x1 inch.

All GPIO pins should be configured for high-current drive mode, to lower their impedance and improve the sensitivity.


simulate this circuit – Schematic created using CircuitLab


simulate this circuit

In Closing

As you can tell, I've decided to make one for myself for less than $1.5k sticker price, and have some fun while doing it :)

If your student wished to leverage LinnStrument's open-source firmware with minimal changes, then the design could be based on Arduino Due, with some external analog switches and an external 12-bit A/D converter. The original design uses ADS7883, but it's a simple change to just one function to use another converter. The source code should be portable to most any platform with a C++ compiler, as long as it's fast enough.


This question seems related to one I asked a while ago. If accuracy is not your main concern, simple voltage dividers may suffice. Take a look at this instructable on how to make a very cheap pressure sensor from anti-static, conductive foam.

  • \$\begingroup\$ This is really nice as a cheap force sensor, but seems a little complicated to make the "piano" keys with this. \$\endgroup\$
    – RMAAlmeida
    Commented Nov 22, 2010 at 10:22

Force gauges are basically variable resistors. They change their resistance relative to a force or pressure applied.

The problem in detection lies in the variation of resistance relative to the force being applied. This is not great, so often a good detection method and amplification are required.

A wheatstone bridge is a really good circuit that allows the for small changes in resistance to be converted into changes in voltages.

A simple but crude method is to connect the output of the wheatstone bridge to you A/D input which will be able to measure the delta V. Alternatively you might even be able to buffer the two outputs, and feed them into a comparator with some hystersis and this can give you a binary output. Very crude, but will allow for detection of force/no force applied.

On the other hand, if you want to know the amount of force being applied, you will need to perform some analysis to work out the voltage variation relative to pressure change. The derivation of the wheatstone bridge equations is a bit tricky but there are plenty of summaries around the interwebs. You will need a good excitation source.

If you know the force/pressure that you trying to detect, you can calculate the change in resistance, and then the change in voltage, and compare this to the resolution of the A/D. If you are after crude changes, this may be sufficient.

If you are after a more precise value you will need an instrumentation amplifier to perform the difference amplification and you can feed this into your A/D. Texas Instruments make some of the best IA's around with respect to CMRR and PSRR against frequency. These were originally made by Burr Brown before TI bought them out.

For precision measurement you will need to have your bridge completing resistors close as possible to your strain gauge to ensure that you can compensate for temperature variations, also a good precise excitation voltage will be needed.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.