Skip to main content

Taking your idea from concept to prototype - a stress ball demo: Part 3

This article is the third part in the series of articles focusing on the Microchip's "Stress Ball" demo. We will look into the basic operation of ADC peripheral and how to implement it with software examples.

Parts list

Qty Product Part number
1 Microchip AVR128DA48 Curiosity Nano Evaluation Kit GPIO Evaluation Board DM164151 204-2690
1 Microchip AC164162 for use with Mikrobus Click Modules, Xplained Pro Extension Boards 193-6490
1 MikroElektronika MIKROE-1881, 4x4 RGB LED Matrix Display mikroBus Click Board 136-0725
1 MikroElektronika Force Click mikroBus Click Board for Implement Force Pressure Measurement MIKROE-2065 136-0788
1 MikroElektronika RN4871 Click Bluetooth Development Kit MIKROE-2544 168-3003

The Curiosity Nano development platform from Microchip is a small-sized, easily customizable rapid prototyping solution that provides developers with everything they might need to bring their project ideas to life. This article introduces the main features of the platform focusing specifically on a target microcontroller from AVR DA family. Together with our DesignSpark members, we will investigate one of the example codes from Microchip’s GitHub repository, while also discussing the basic operation of peripherals that were used in the demo, such as GPIOs, ADC and USART.

Peripheral Configuration - GPIO (Part1)

Peripheral Configuration - USART (Part 2)

Peripheral Configuration - ADC

The applied force is detected using Interlink Electronics’ force sensing resistor (FSR) implemented with a help of add-on circuitry on the Force click board. The analog output voltage from Force click board is then fed to the ADC of the AVR128DA48.

Force sensor

Force click board with force sensing resistor

Force click board with force sensing resistor

The FSR is a type of piezoresistive sensor, which consists of two membranes that are separated by a spacer adhesive. The bottom membrane is a conductor substrate with two sets of interdigitated traces that are electronically isolated from one another, whereas the other membrane is coated with carbon-based conductive ink. In a neutral state, there is a distance between the top and bottom layers due to a small separation created by the spacer, thus resulting in an open circuit configuration with no electricity passing between the layers. When external force or pressure is applied, the gap between two membranes gets closer changing the resistance to be proportional to applied force. The analog output voltage of the FSR is then converted to the corresponding digital value using the in-built ADC.

construction of force sensing resistor

Typical construction of force sensing resistor


The AVR128DA48 microcontroller features a 12-bit successive approximation register (SAR) ADC, with a sampling rate of up to 130 ksps (kilosamples per second). This type of ADCs uses binary search algorithm to convert the analog value to a digital equivalent. Consider an example of 4-bit SAR ADC below.

4-bit SAR ADC

4-bit SAR ADC

The SAR ADC typically consists of a sample and hold circuit, a comparator, a digital to analog converter, a successive approximation register along with the control circuit. When the new conversion period starts, the sample and hold circuit samples the input signal. The comparator then compares that signal with the output signal of the DAC. Based on the result of the comparison, the output of the SAR changes one bit at a time. The complete explanation of SAR ADC’s working is available in this article.

The AVR128DA48 microcontroller has one instance of ADC peripheral accessible through PORTD pins (PD0 to PD7). It supports single-ended and differential inputs implemented using analog input multiplexers. The former allows measurements between selected input level and 0V, whereas the latter measures the voltage between two input channels.

ADC Block Diagram

ADC Block Diagram

The ADC can be configured to specific voltage reference (VREF) levels coming from various sources such as internally generated voltages, AVDD supply voltage as well as external VREF pin (VREFA).

The summary of given ADC registers is given in the table below. We will discuss the initialization steps for setting up the ADC to convert the analog signal from the FSR sensor.

ADC Registers Summary

ADC Registers Summary

ADC initialization

Reference voltage

In the demo, we will be relying on a single-ended 12-bit conversion with the result of the conversion to be stored in the ADCn.RES register given by the following equation:

single-ended 12-bit conversion equation

Here, VAINP is the positive ADC input and the VADCREF is the selected ADC voltage reference. The VADCREF is equal to AVDD = 3.3V in our setup, which can be set by accessing VREF register.

The analog values in the range between 0 and VADCREF are mapped to the 12-bit representation (although the register has a 16-bit capacity). You will notice that the maximum value of VAINP can vary from one setup to another. When maximum force is applied on the Force sensor the voltage on ADC pin is 3.261V which gives ADC count ~ 0xFCF.

The relationship between input range and binary output representation

The relationship between input range and binary output representation

Clock generation & Prescaler

The ADC converts analog signal into digital signal at regular intervals determined by its operation range, usually in order of kHz frequencies. However, the CPU clock frequency is significantly higher (up to 24 MHz for AVR® DA family). Therefore, the microcontrollers usually have a prescaler circuit to perform a frequency division operation with predefined division factors, such as 2, 4, 8, 12, …,256. For example, defining a prescaler factor of 96 in PRESC bit field of ADCn.CTRLC register will result in fADC = fCPU/96 = 125kHz for fCPU = 12MHz.

ADC Prescaler

ADC Prescaler

Single vs Accumulated Sampling

There are two operation modes supported depending on the accumulator setting: a single sample or an accumulation of samples. The timing diagrams for these modes are shown below. As you might notice, there are a number of operations with specific timing that happen within the conversion cycle for both modes. Those include start-up (2*fCPU cycles), sampling (2*fADC cycles), conversion (13.5*fADC cycles) and result formatting (2*fCPU cycles). Total conversion time will depend on whether the result of the conversion is taken after a single sample or an accumulation of n samples. The SUMPNUM bit field within the ADCn.CTRLB register can be used to set how many samples should be accumulated (if any).

Single sample conversion

Single sample conversion

Accumulated conversion for two samples

Accumulated conversion for two samples

Free-running mode

If the Free-Running mode is enabled in the ADCn.CTRLA register, a new conversion is started as soon as the previous conversion has completed. The timing diagram for the ADC in Free Running mode for a single conversion is shown below.

ADC in Free Running mode

ADC in Free Running mode

Pin selection & enable

In the demo, the pin PD4, which corresponds to the AIN4 channel of the ADC, has been selected to feed the input signal through the positive terminal by writing to the MUXPOS bit field of the ADCn.MUXPOS register. Lastly, the selected pin is enabled by writing “1” to the ENABLE bit in the ADCn.CTRLA register.

void adc_init()
	ADC0.CTRLC = ADC_PRESC_DIV96_gc; /* MAX FCLK_ADC 1.25 Khz */
	ADC0.MUXPOS = ADC_MUXPOS_AIN4_gc; /* ADC channel AIN4->PD4 */

Code implementation – Starting a conversion

To start the conversion, it is necessary to write a “1” to the Start Conversion (STCONV) bit in the ADCn.COMMAND register. The STCONV bit will be set during a conversion and cleared once the conversion is complete.

ADC conversion in the main function

int main(void)
	ccp_write_io((void *)&(CLKCTRL.OSCHFCTRLA),	CLKCTRL_FREQSEL_12M_gc); /* CPU clock is configured to 12 Mhz in clock_config.h */
    while (1) 
			adc_t.adc_result = (uint16_t)adc_get_result();
			adc_t.adc_average_result = (uint16_t)adc_t.adc_result >> DIV_OR_SHIFT;
			strength_percentage  = (float)(adc_t.adc_average_result * MAX_FORCE_PERCENT) / ADC_MAX_VALUE_for_FORCE_CLICK;

The result of the conversion is accessible through the ADCn.RES register, and the RESRDY interrupt flag is set in the ADCn.INTFLAGS register.

Getting the ADC result from RES register

uint16_t adc_get_result(void)
	return (ADC0.RES);

bool adc_result_is_ready(void)
	return (ADC0.INTFLAGS & ADC_RESRDY_bm);


In this (rather long) article, we collated the detailed explanation of three main peripherals that were used to implement the Stress Ball demo from Microchip. Even if this is your first time working with 8-bit microcontrollers from AVR® family, you should able to follow the instructions and get started with building applications easily. The complementary application documents and code examples will be included in the Resources section.

If you have any other tutorials you want to see on DesignSpark, leave us a comment below!


Rapid Prototyping with the Curiosity Nano Platform – Microchip University

AVR1000b: Getting Started with Writing C-Code for AVR® - TB3262

How to Use Force Sensitive Resistor with 12-bit ADC - AN3408

AVR® DA Family Datasheet - Microchip

AVR128DA48 USART Hello World Example – GitHub

USART Serial Terminal – Microchip Developer

WS2812 Tutorial – Friendly Wire

Successive Approximation ADC Explained – ALL ABOUT ELECTRONICS

Differential ADC Using the AVR128DA48 Curiosity Nano - GitHub

I am an electronics engineer turned data engineer who likes creating content around IoT, machine learning, computer vision and everything in between.
DesignSpark Electrical Logolinkedin