This project gives you an example of how a basic user interface can be implemented using only one circular capacitive touch sensor.

Related Information


Required Hardware/Software


The Background

Two recent articles have explored capacitive touch sensing by means of the SLSTK2010A evaluation board for the EFM8 Sleepy Bee microcontroller family from Silicon Labs. This board includes an EFM8 microcontroller and a circular capacitive sensor, as follows:


A diagram of the specialized sensor design is superimposed on the photo; it’s somewhat difficult to see the actual shape of the three individual sensors by simply looking at the PCB.


The first of these recent cap-sense articles focuses on the low-level functionality of the EFM8’s capacitive-sense controller, and the second one presents an algorithm for combining three separate sensor measurements into an approximate angular position. You can still benefit from this article without having all the background information, but if you want a more thorough and complete understanding of what is going on in this user-interface project, I recommend that you read these two previous articles.

Two things from the second article that you definitely should be aware of are the sensor-identification scheme and the physical-position-to-angle mapping. Both of these are conveyed by the following diagram:



The numbers indicate the way in which I refer to each of the three individual sensors that make up the one circular sensor; for example, the upper-left sensor is referred to in the code as “sensor 2.” The sensors are separated from one another by 120°, and the angular positions of the sensors are assigned in such a way as to ensure that the middle-right position corresponds to 0°. This is a convenient arrangement because the circular sensor becomes equivalent to a standard polar-coordinate-system plot in which the positive x-axis is 0°, the positive y-axis is 90°, and so forth:



A Cap-Sense User Interface—But Why?

As suggested by the article title, this project serves as a starting point for a variety of highly functional user interfaces that require nothing more than a single capacitive-touch-sense wheel, which in turn requires only three individual capacitive touch sensors and a microcontroller (preferably a microcontroller with an integrated capacitive-touch controller). By “user interface” I mean a system—composed of a physical device and corresponding firmware—that allows a user to conveniently interact with a particular device. The exact nature of the user interface would, of course, vary according to the functionality of the device. Possibilities include navigating menus, entering text, setting an alarm, and controlling audio playback.

At this point a question naturally arises: Why can’t we just use a keyboard, or a touch screen, or some pushbuttons? Why capacitive touch sense? Well, you are certainly free to design a user interface however you prefer, but cap touch sense offers some significant advantages:

  • It’s inexpensive—the sensor is integrated into the PCB layout and thus costs almost nothing.
  • It is consistent with the “less hardware, more firmware” design philosophy (discussed at the end of the first section in this article).
  • The design process is reasonably straightforward; capacitive touch sensing does not require a burdensome amount of support components or interconnects, and the firmware can be quite simple, such that there is no need for sophisticated drivers or libraries.
  • Capacitive touch sensors do not suffer from the mechanical degradation that affects switches and pushbuttons.
  • The form factor is appealing—the sensor is integrated into the PCB layout and thus does not result in additional product thickness.
  • And surely the most important of all, capacitive touch sense is way cooler than old-school interfaces.


Project Overview

The interface presented in this article allows the user to enter a four-digit number into the “device” (i.e., the evaluation board). The commands recognized by the firmware are divided into two categories: “tap” and “drag.” The difference is the length of time during which the finger is in contact with the sensor; taps are short-duration events and drags are long-duration events. A drag does not always involve actually dragging the finger from one position on the sensor to another, but most of the time it does, and I couldn’t think of a better name.



A tap is expected to be a short-duration touch event in which the finger does not move from one angular position to another. You are free to use whatever maximum tap duration works well for you; I had good results with 150 ms.


                    #define TAP_DURATION 150 //in milliseconds

As you will see if you look through the code, the duration of the touch event must be less than TAP_DURATION in order to be considered a tap.

The angular position assigned to the tap event is simply the last detected position, so if you use a longer tap-duration threshold and move your finger around during the tap, the code will ignore the earlier finger locations.

The firmware currently supports two types of tap events: a tap near the 90° point activates “character entry mode,” and a tap near 270° causes the microcontroller to accept the four-digit number displayed on the LCD and then deactivate character entry mode. (I used “character entry mode” instead of “digit entry mode” to emphasize the fact that this same general interface could be adapted for entering and editing text.)



A drag event is used to select the desired digit in character entry mode. The finger is applied for at least TAP_DURATION milliseconds, and typically the finger is dragged around until the LCD shows the desired digit. In this project we have only 10 possibilities (digits 0 through 9), so you might be able to find an acceptable angular position without dragging. However, a text-entry system would have many more character options, and thus you would almost always need to start at an approximate angular position and then drag until the LCD displays the desired character.

If a drag is occurring and character entry mode is active, the LCD displays the digit corresponding to the angular position of the detected fingertip:



From Angle to Digit

We have ten digits, which means that we need to divide the circular sensor into ten equal angular sections, with each section corresponding to a particular digit. The following diagram illustrates this concept.


Each section is 360°/(10 sections) = 36°.


The code excerpt below shows how I implemented this in firmware. The first section, corresponding to digit 0, begins at 343° and ends at 18° (if you do the subtraction this looks like 35° instead of 36°, but remember that a range extending from 0° to 1° includes a total of 2°, despite the fact that 1° – 0° = 1°). The next section begins at 19° and ends at 54°; the ending angle (54°) is obvious in the code, but the beginning angle (19°) must be inferred from the fact that the preceding if statement looks for angles that are less than or equal to 18°. This relationship continues down to the final else-if statement, which has a range ending at 342° (this makes sense, considering that the range of the initial if statement begins at 343°).


                    unsigned char Map_Angle_to_Digit(unsigned int Angle)
	if(Angle > 342 || Angle <= 18)
		return 0;

	else if(Angle <= 54)
		return 1;

	else if(Angle <= 90)
		return 2;

	else if(Angle <= 126)
		return 3;

	else if(Angle <= 162)
		return 4;

	else if(Angle <= 198)
		return 5;

	else if(Angle <= 234)
		return 6;

	else if(Angle <= 270)
		return 7;

	else if(Angle <= 306)
		return 8;

	else if(Angle <= 342)
		return 9;

		return 'E';	//for error

The Flow

The operation of the firmware is governed by the sequence in which events occur. This means that we need some sort of state machine, i.e., a firmware structure in which program execution transitions to a new state based on the current state and a relevant event. The following flowchart is a visual representation of the state machine for this project:



Here is the data-entry procedure from the perspective of the user:

  • Tap near 90° to activate character entry mode.
  • You now drag to select the rightmost digit in the four-digit number. This is referred to as the “first digit” in the context of data entry; unfortunately, it’s referred to as the “fifth digit” in the file LCDControl.c, because the digits are written to the LCD from left to right. Sorry for the terminology conflict; I don’t want to change LCDControl.c any more than necessary, but at the same time it makes more mathematical sense to start digit entry at the ones place and move leftward.
  • When the LCD displays the desired digit, lift your finger off the sensor. The microcontroller detects the end of the touch event and stores the currently chosen digit in the ones place of the four-digit number. The next drag event will activate character entry mode for the tens place.
  • Repeat this process until you have chosen all four digits.
  • At this point you have two options: you can complete data entry by accepting the current number, or you can enter a new number. To complete data entry, tap near 270°. To start a new number, drag as per normal, and when you lift your finger off the sensor the ones place will be filled with the selected digit and the other three places will have zero.


The Interface in Action

This first video shows how the microcontroller does not allow data entry until it detects a tap near 90°.


The next video shows a data entry procedure that is completed by a tap near 270° after the four digits have been chosen.


This last video demonstrates the process of entering a new four-digit number after the (presumably erroneous) first four-digit number.



You can download all the source and project files using the following link:


  Download Code  

There are many additional details that you can explore by looking through the code, which uses descriptive identifiers and is written in a way that (hopefully) makes it relatively easy to follow.

As stated above, this project is a starting point. One improvement that comes to mind is incorporating an “edit” mode that allows the user to move from one digit to another using taps near 180° (for leftward movement) and 0° (for rightward movement). If you have any ideas for handy additional features, feel free to mention them in the comments.