ADCTouch capacitive touch implementation for STM32F103 development board

Can someone help me port this library?
User avatar
juliusbangert
Posts: 10
Joined: Tue Aug 01, 2017 4:02 pm

ADCTouch capacitive touch implementation for STM32F103 development board

Post by juliusbangert » Thu Aug 03, 2017 4:20 pm

Before I came across these STM32F103 development boards I was playing around with an Arduino Nano and a nice implementation of capacitive touch sensing. This library by martin2250 requires only one analog pin per touch pad and doesn't need the send/recieve pins and the large 1МΩ resistors that the popular Capacitive Sensing Library by Paul Badger needs.

I know that this ADCTouch library is a kind of implementation of Atmels QTouch and uses some internal capacitor in some way, and I also know it only seems to work on the AVR arduinos ... but my question is ... has anyone got any idea how I might get this working on the STM32? And if not, are there any other nice ways to get capacitive touch working on these boards without additional hardware?

Here's a youtube video explaining the principal.

Any ideas how to get this working on a STM32F103 development boards?

User avatar
RogerClark
Posts: 7683
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by RogerClark » Thu Aug 03, 2017 10:38 pm

I looked at the AVR code and it seems to do the following

Set the pinmode to PULL-UP
Does some sort of ADC conversion using the AVR hardware control registers directly.
Sets the pin to INPUT
Takes an ADC reading using analogRead

It does this a multiple times and averages the result.

The main thing I don't understand is why the code appears to do one ADC conversion by controlling the hardware directly and then takes the sample using the Arduino API.

Perhaps the first conversion is just a way to delay for a small and fixed period of time.
Or perhaps those AVR register settings do something else to the pin.


I looked at the video,but it does not give any technical details of the principal of operation.

Anyway..
As far as I can see, is the principal of operation is to use the internal pull-up resistor as a charge source, and the ADC is used to measure the voltage across the capacitor, as it charges up.

User avatar
RogerClark
Posts: 7683
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by RogerClark » Fri Aug 04, 2017 1:52 am

Update

The latest version of the capacitive touch library seems to be here

https://github.com/PaulStoffregen/CapacitiveSensor

It would need to be modified to work with the STM32

As far as I can see, the platform specific code is in CapacitiveSensor.h

e.g this is the block of code for the ESP8266

https://github.com/PaulStoffregen/Capac ... h#L95-L105

A block of code similar to this would need to be added for the LibMaple core or for the official HAL based STM core.

BTW.
If you are intending to port this to the STM HAL based core, you can't simply use register a addresses as each STM32 MCU series has different base addresses for its GPIO etc. So you'd affectively need to write functions which are wrapped up to look like macros.

fpiSTM
Posts: 315
Joined: Fri Sep 16, 2016 12:33 pm
Location: Le Mans, France

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by fpiSTM » Fri Aug 04, 2017 8:30 am

Wi6Labs made some change for the STM32 core at the first release but this was not the right approach.
Right one is the one proposed by Roger.

For the main question, to have an ADCTouch without hardware, it seems interesting to check if it is possible with STM32 internal circuit.

User avatar
RogerClark
Posts: 7683
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by RogerClark » Fri Aug 04, 2017 11:29 am

I just looked at this again, and there are 2 different methods of doing capacitive touch.

It seems that the Arduino team use the 2 wire per sensor version.

I've taken a look at the description of how the single wire "QTouch" works, according the github repo, and it has the following explanation
Charge the test pin to 5V via pullup resistor (not directly to prevent short circuits)
Discharge the internal ~14pF capacitor
Set the pin to tristate
Connect the 14pF capacitor with the pin so that charge distributes evenly
The important thing to note here, seems to be the ability of the AVR to "Connect the 14pF capacitor with the pin"

This seems to imply that somehow the AVR has an internal capacitor which can be connected to the pin.

I'm not sure where this capacitor is. Its possible that its a byproduct of connecting the ADC, and somehow there is a way to "Discharge" the internal capacitor independently of it being connected to the pin.

Anyway, I'm not sure if this would work on the STM32 as it seems to rely on the internal ADC architecture of the AVR chip.

Also, what I don't understand is how this can not be effected by mains pickup.

I know that the video shows a 1k resistor in series with the pickup, but this is not really going to damp the mains pickup at all, because the input impedance on the STM32 is many times higher than this (probably 25 x or more high)

I tried writing some code that pulled the pin low and then immediatly sampled the adc until its value had changed by around 1000, but internal capacitance was completely swamped by mains pickup.

If you want a very crude touch sensor, and are mostly indoors i.e somewhere that you will get mains pickup, this works;-)

Input is PA4, and assumes BluePill board with LED on PC13 active LOW

Code: Select all

void setup() {
  // put your setup code here, to run once:
Serial.begin();
  pinMode(PA4,INPUT);
  pinMode(PC13,OUTPUT);
}

void loop() {

  if (abs(analogRead(PA4) - 2048)>500)
  {
    digitalWrite(PC13,LOW);
    delay(10);
  }
  else
  {
    digitalWrite(PC13,HIGH);
  }
  delay(1);
}
Other than that, I'd advise you use the 2 wire system

fpiSTM
Posts: 315
Joined: Fri Sep 16, 2016 12:33 pm
Location: Le Mans, France

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by fpiSTM » Fri Aug 04, 2017 12:20 pm

I've just tested with a Nucleo-F103RB based on the lib code: (with Arduino_Core_STM32)
My sketch:

Code: Select all

int ref0, ref1;     //reference values to remove offset

int ADCTouch_read(byte ADCChannel, int samples)
{
  long _value = 0;
  for(int _counter = 0; _counter < samples; _counter ++)
  {
    pinMode(ADCChannel, INPUT_PULLUP);

    analogRead(ADCChannel);

    /*
    ADMUX |=   0b11111;
    ADCSRA |= (1<<ADSC); //start conversion
    while(!(ADCSRA & (1<<ADIF))); //wait for conversion to finish
    ADCSRA |= (1<<ADIF); //reset the flag
    */

    pinMode(ADCChannel, INPUT);
    _value += analogRead(ADCChannel);
  }
  return _value / samples;
}

void setup() 
{
    // No pins to setup, pins can still be used regularly, although it will affect readings

    Serial.begin(9600);

    ref0 = ADCTouch_read(A0, 500);    //create reference values to 
    ref1 = ADCTouch_read(A1, 500);    //account for the capacitance of the pad
} 

void loop() 
{
    int value0 = ADCTouch_read(A0, 100);   //no second parameter
    int value1 = ADCTouch_read(A1, 100);   //   --> 100 samples

    value0 -= ref0;       //remove offset
    value1 -= ref1;

    Serial.print(value0 > 40);    //send (boolean) pressed or not pressed
    Serial.print("\t");           //use if(value > threshold) to get the state of a button

    Serial.print(value1 > 40);
    Serial.print("\t\t");

    Serial.print(value0);             //send actual reading
    Serial.print("\t");
  
    Serial.println(value1);
    delay(100);
}

And it works with only two wire connected and precision is :shock: .
I've just replaced

Code: Select all

 
    ADMUX |=   0b11111;
    ADCSRA |= (1<<ADSC); //start conversion
    while(!(ADCSRA & (1<<ADIF))); //wait for conversion to finish
    ADCSRA |= (1<<ADIF); //reset the flag
by

Code: Select all

    analogRead(ADCChannel);

User avatar
juliusbangert
Posts: 10
Joined: Tue Aug 01, 2017 4:02 pm

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by juliusbangert » Fri Aug 04, 2017 12:29 pm

I'll be honest, the internals of the chip architecture is totally over my head, I'm a noob. But single pin capacitive touch seems like a really great thing to get working on the STM32.

These are the the best explanations I found of the concept:

http://tuomasnylund.fi/drupal6/content/ ... le-adc-pin
http://hackteria.org/wiki/QTouchADC_Library_for_Arduino

The guy who wrote another version based on the original arduino library by martin2250, also started this whole project using the same principal based but on a attiny85.

I've tried the original library out on a atmega328 (nano) and it works very well with good repeatability and seemingly low noise. How is this? Is the fact that this also works on an Attiny85 due to the same Atmel architecture with the internal 14pF capacitor?

User avatar
RogerClark
Posts: 7683
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by RogerClark » Fri Aug 04, 2017 12:45 pm

Frederic,

I tried the same thing, but I also plotted the ADC value, by sending it vie Serial and using the Arduino plotter display

I found I get loads of mains pickup, which has a really big effect on the results.

It does detect when you touch the pin, but I think this is mostly due to the mains pickup which is in excess of the supply voltage

User avatar
juliusbangert
Posts: 10
Joined: Tue Aug 01, 2017 4:02 pm

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by juliusbangert » Wed Aug 16, 2017 12:38 pm

I've been trying to get this ADCTouch to work reliably with minimal noise and I appear to be getting some ok results, I'm experimenting with using the digitalSmooth filter by Paul Badger and calibrating the inputs on the fly.
The serial plotter for eight touch inputs being touched one after the other looks like this :
Screen Shot 2017-08-16 at 13.13.16.png
Screen Shot 2017-08-16 at 13.13.16.png (115.93 KiB) Viewed 732 times
Now I would like to see if low-pass / antialiasing filter circuits would work on the inputs. I was looking at this question on StackExchange and one of the answers mentions adding this kind of circuitry. I don't really understand how or what this does but I'd still like to try it out anyway; they talk about a 100 ohms resistor and a100 uF capacitor in that situation but this is specific to their sampling rate and it's for a 5v circuit.

Code: Select all

 +5V                                +5V
   |                                 |
(sensor)---resistor---+----------(Arduino)
   |                  |              |
   |                  |              |
   |              capacitor          |
   |                  |              |
   |                  |              |
  GND----------------GND------------GND
  
Does anyone know if this would work and if so what values I should use to try it out?

arpruss
Posts: 153
Joined: Sat Sep 30, 2017 3:34 am

Re: ADCTouch capacitive touch implementation for STM32F103 development board

Post by arpruss » Mon Oct 09, 2017 6:15 pm

I tried the ADCTouch library on a Mega clone, and it works well (my kids had a lot of fun playing a piano by tapping on oranges and soda cans).

I don't think it's just the mains. Today I went to the center of a sports field with a phone and an OTG cable, and it was just as responsive as indoors. I then took it indoors, while keeping it running so it would keep the same reference data (the demo sketch I am using gets reference data on startup, and I started up in the middle of the field), and I didn't see any of the false positives you'd expect if mains was swamping everything--again, things worked just fine indoors with the same reference data.

I am using a lower activation threshold than the ADCTouch's demo, 25 instead of 40.

I don't have an STM32 easily accessible right now (one is inside a project box and another is in the mail).
photo.jpg
photo.jpg (111.63 KiB) Viewed 592 times

Post Reply