Tuesday, May 10, 2011

Capacitive Touch Sensor for pic16F84A (no special hardware required)

Here is my newest project I've been working on. I'll get more details up when I have the time. In the mean while enjoy the video.

 
Update: Sorry its been awhile since my last update. I've been busy with work and my other projects. The capacitive sensing input is really simple because everything is done in software. Here's my hand drawn schematic for the input stage generalized so that any mcu can be used (For some reason I haven't yet installed a schematic program on my netbook and I don't feel like booting up my other laptop).
It's amazing that all you really need is a single gpio and a resistor (the capacitance is provided by the traces on the breadboard). The ten megaohm resistor allows the discharge rate for the stray capacitance to be slowed down enough for the uC to measure. The uC just continually charges up this capacitance, puts the pin into high impedance by making it an input, and then counts until it measures the "capacitor" is discharged. This count can then be analyzed to determine if the pin has been pressed or not (the count increases if the button is pressed because your finger adds to the stray capacitance in parallel which increases the discharge time). That's pretty much all that's necessary other than some fancy algorithms for error proofing detection.

Update 2: I've finally gotten around to porting my capacitive touch sensing code to C. The code should work for most PICs and can be easily modified to change pin assignments and whatnot to work on any other chip you might need. Below you will find the function freqcapsense. All you need to do is call it and it will sense whether RA0 is being touch or not. I've included averaging multiple samples and an adjustable threshold in order to tweak the sensitivity and accuracy for any given setup. You can have it return a 1 or 0 for touch status or by commenting out the if else statement at the end and uncommenting the return current statement it will return the raw period value it is reading from the pin. Enjoy.

int freqcapsense(){
    unsigned int avg;
    unsigned int current=0;
    unsigned int thresh=29;
    unsigned int trials=10;

    while(trials>0){
        TRISA=0b0;
        RA0=1;
        delay();
        TRISA=0b1;
        while(RA0==1){current++;}
        trials--;
        avg=(avg+current)/2;
    }

    if((current-avg)>thresh){return 1;}
    else{return 0;}

    //return current;
}

22 comments:

  1. hi friend, congratulations for your work, I would like you to know how that works, thank you from Venezuela

    ReplyDelete
  2. Thanks for reading my blog. It's really simple. All my microcontroller does is charge the capacitor (parasitic in my case due to the breadboard) and then switch it to an input so that the pin is high impedance. Then the capacitor discharges into the high value resistor (chosen for long time constant) while the micro counts until the capacitor empties entirely. When you are not touching the pin the capacitance is more or less constant and thus the counted number should remain the same between each cycle. But once your hand touches the sensor it adds a capacitance in parallel with the normal value (so total capacitance increases) which in turn increases the time constant which means that the count then increases. By analyzing the counted number you can determine if a finger has indeed touched the sensor or not. How I implemented two sensors is that I read one and store the count and then immediately read the other and store that value in a different register. This is not truly multitouch, but to our perception of time everything occurs so quickly that it appears to be. If you have any more questions feel free to ask.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Hello Mr SMJ.

      Can You pleace Give me the .HEX File for 16f84a ic. and circuit diagram for make a simple touch sensor with this HEX file and this ic... Just mail me the .HEX File and Diagram...... Please Help me This is really Important To ME....THANK YOU VERRY MUCH..... MY EMAIL- ERANDA99@GMAIL.COM

      Delete
  3. thanks for your answer you are working in C or ASM. if C can show the charge and capture of time?

    ReplyDelete
  4. I wrote my code in ASM. I've gotta clean it up before I can post it (otherwise it will only be understandable by myself).

    ReplyDelete
  5. r u serious ?!
    engineer on site...i doubt that !!

    ReplyDelete
  6. anyways...first i wanna thank you MR. sjm4306 for sharing this with us. i have a little question.
    while looping do i have to output a high level on a pin and then quikly convert it into an input then calculate the discharge time ?
    and when saying quikly, is it immediately or after a certain clock cycles...or millisecondes..etc ?
    is like this how the algorithm should look like ?
    thanks in advance :)

    ReplyDelete
  7. I set the pin to output, set it high, call a little delay to allow it to fully charge, switch it to input, and immediately start counting until I read zero on the input. In theory I guess you could wait a little as long as its not too long and the wait is exactly consistent between cycles but I dont see why you would want to. I'll dig out my code and post it if it'll help.

    ReplyDelete
  8. it works !!!
    thanks , what i missed was that i should convert the pin to input without reset it back to the low level after the charging delay.....obviously ! :P
    well i'm still learning and thanks to peopele like you, whom don't have this complexity of sharing things and ideas nowadays.
    anyway a big thanks for the tip and wish you good luck in you carriere :)
    peace !

    ReplyDelete
  9. I Love the simplicity, Great work! ;-)

    ReplyDelete
  10. source code please ?
    or ware can i download the hex

    ReplyDelete
  11. hi, may I have the schematic and code please? :)
    I am studing this kind of project now. Thanks,

    ReplyDelete
    Replies
    1. I've posted the C function that will do capacitive touch sensing above. It will poll pin RA0 of whatever PIC you choose. Just copy and paste the function into your function declarations. All you need to do is call the function and it will return the button status. If you need any help feel free to ask.

      Delete
    2. hola, ¿tendrás el código para CCS?

      ¡Saludos!

      Delete
  12. Hello,

    congratulations for your project and for make available to all
    I think that you could
    turning this post in something more elaborate in terms of didactic
    explain better

    software and hardware.

    are few options of low cost capacitive keytouch that is reliable
    especially for those living in the third world
    as I
    I will try now based on what I have that is his post
    make a 16F628 manage 4 touch keys and make it programmable for pulse like in your video or retention
    that is
    turn on the first touch and turn off in the second .



    thanks for all

    please consider my proposal for increase information about this post

    ReplyDelete
  13. this week I implemented the code in a PIC 16F628
    I experienced some
    cintillations on LEDS and some instability
    i made mounting on breadboard and then made ​​an arrangement with the PCB
    PCB everything went more stable but still not as stable as in your video.

    follows the code that I used in CCS:

    #include <16f628.h>
    #fuses HS,INTRC_IO, NOLVP, NOWDT, PUT
    #use delay (clock=4000000)


    void main (){
    unsigned int avg;
    unsigned int thresh=29;

    while (true){
    unsigned int trials=10;
    unsigned int current=0;
    while(trials>0){
    output_high(PIN_B5);
    delay_us(1);
    while(input(PIN_B5)){current ;}
    trials--;
    avg=(avg current)/2;
    }

    if((current-avg)>thresh){output_high(PIN_B0);
    }
    else{output_low(PIN_B0);}

    }
    }


    I also test using output_toggle (PIN B0);
    in order to implement a function rocker switch
    and its run reasonably

    ReplyDelete
  14. just found your blog, this look very nice.
    i have a question, is it possible to detect about 1cm from a big sensor with this technique?

    i have a piece of aluminium foil to act as a touch sensor, will it be able to sense my hand from 1cm?

    Will be attempting it when i have time...

    ReplyDelete
    Replies
    1. Yep the sensor can be made sensitive enough in software to detect even if you aren't touching the bare metal. I played around with sensitivity by hooking up a lcd and spitting out the raw timing values so that I could see what thresholds I should set for different distances.

      Delete
  15. Hello, good day, I'm from Brazil, I'm 12 and I wonder if I could borrow the code for me to study and try to understand, I believe that only studying to understand it, thank you for your attention.
    email = gilvan.leal @ yahoo.com.br

    ReplyDelete