This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

FDC2214 in the Arduino environment

Other Parts Discussed in Thread: FDC2214, FDC1004

I've experimented with the FDC2214 evaluation kit for a biomedical application, and it looks really promising. To progress further along this route, I'd like to try evaluating the FDC2214 with a specialized board, operating in the Arduino type environment for initial prototyping. Does anyone have any working Arduino code for obtaining data from this chip, or pointers to successfully interfacing with it in the Atmel environment?  Figured I'd ask before reinventing the wheel! :)

  • Hi John,

    Thanks for your question - unfortunately, we  do not have any Arduino code for the FDC2214.

    Thanks,

    Rachel

  • Hi John, I hope this code helps. Remember that the configuration will entirely depend on your system application. See the datasheet of the FDC2214. Cheers!

    //unsigned long 4 Bytes 0 to 4,294,967,295
    //long 4 Bytes -2,147,483,648 to 2,147,483,647
    //float 4 Bytes 1.2E-38 to 3.4E+38 (6 decimal places)
    #include <Wire.h>
    #define DT 1 //Derivative threshold.
    #define IT 1500 //Integration threshold.
    #define HAND 3500 // Hand threshold.
    #define AVGN 3 //Degree of the IIR filter.
    #define L 1 //Leakege Factor.

    byte FDC = 0x2A;// FDC address either 0x2A or 0x2B;
    byte CH0MSB = 0x00; //Most significant bits of the conversion result on channel 0. [11:0]-->>[27:16]
    byte CH0LSB = 0X01; //Less significant bits of the conversion result on channel 0. [15:0]-->>[15:0]


    void LedOn() {
    digitalWrite(2, HIGH);
    }

    void LedOff() {
    digitalWrite(2, LOW); //Target approaching!
    }

    //Build the complete conversion result from the specific channel
    unsigned long readChannel() {
    unsigned long val = 0;
    word c = 0;
    word d = 0;
    c = readValue(FDC, CH0MSB);
    d = readValue(FDC, CH0LSB);
    val = c;
    val <<= 16;
    val += d;
    return val;
    }

    //Read bytes from register channel specified
    word readValue (int FDC, int reg) {
    byte a = 0;
    byte b = 0;
    word value = 0;
    Wire.beginTransmission(FDC);
    Wire.write(reg);
    Wire.endTransmission();
    Wire.requestFrom(FDC, 2);
    while (Wire.available())
    {
    a = Wire.read();
    b = Wire.read();
    }
    value = a;
    value <<= 8;
    value += b;
    return value;
    }


    //IIR Filter
    long average( unsigned long meassure, long avg_1, int n) {
    long avg = ((avg_1 * n) - avg_1 + meassure) / n;
    return avg;
    }

    void monitor() {
    long current = readChannel();
    long delta = 0, Integral = 0, Integral_1 = 0;
    long avg = 0, avg_1 = 0, last = 0;
    //avg = current;

    for (;;) {

    last = current;// Shift register. The variable last will storage the current value for the next iteration.
    current = average(readChannel(), last, AVGN);//New value for current return from IIR filter --> function average(meassure, avg_1, n)

    //Derivative integration algorithm
    delta = current - last;

    if (abs(delta) > DT) {
    Integral = Integral_1 + delta;
    }
    else {
    Integral = Integral_1;
    }

    if (abs(Integral) >= IT && abs(Integral) < HAND) {
    LedOff();
    Integral_1 = Integral;
    Serial.println("Pot approaching...");
    }
    else {
    LedOn();
    Integral_1 = Integral * L;
    }
    Serial.println(abs(Integral));
    delay(100);
    }
    }


    //Configuring the FDC2214
    void writeConfig(int FDC, byte reg, byte MSB, byte LSB) {
    Wire.beginTransmission(FDC);
    Wire.write(reg);
    Wire.write(MSB);
    Wire.write(LSB);
    Wire.endTransmission();
    }

    void Configuration() {
    writeConfig(FDC, 0x14, 0x20, 0x01);//CLOCK_DIVIDERS_CH0
    writeConfig(FDC, 0x1E, 0xF8, 0x00);//DRIVE_CURRENT_CH0
    writeConfig(FDC, 0x10, 0x00, 0x0A);//SETTLECOUNT_CH0
    writeConfig(FDC, 0x08, 0x69, 0xE8);//RCOUNT_CH0
    writeConfig(FDC, 0x19, 0x00, 0x00);//ERROR_CONFIG
    writeConfig(FDC, 0x1B, 0x02, 0x0C);//MUX_CONFIG
    writeConfig(FDC, 0x1A, 0x14, 0x41);//CONFIG
    }


    void setup() {
    Wire.begin();
    Serial.begin(9600);
    Serial.println("Starting");
    pinMode(2, OUTPUT);
    Configuration();
    }

    void loop() {
    Wire.beginTransmission(FDC);
    monitor();
    }

  • Hello Josue,

    Thank you for sharing your code!

    Regards,
    Yibo
  • Wow, Josue! How very helpful of you!

    Thank you very much. Over the next few days, I'll try out your code, and post any changes and comments back to this group so that we can all continue to benefit. I'll be happy to verify your answer then!
  • We are here to help and grow together. I tried to implement the theory of the derivative integration algorithm. If there is any improvement you find. Please let me know. here is the link of the TI report. 

    Regards.

    Josue Uribe

  • Hi Josue Uribe;
    Thank you for sharing your code! , It is very helpful for me.In the codes just channel-0 register address is known but what is the channel-1 register address? I dont found channel-1 register address , please help me!!!!

    Regards ,
    Unal
  • Hi Unal,

    Channel 1's register address is in the Register Maps section of its datasheet.

    Thanks,

    Rachel

  • How do you connect the FDC EVM to the Arduino. I want to change the microcontroller, the EVM has 7 ports (SCL,SDA,ADDR,SD,INTB,GND,3.3V). Where do i connect those ports to the arduino or what do those ports send?

    Thank you very much in advance.
  • Hello Josue Uribe,

                                        Thanks for sharing your code. The output values are some what different and a huge numerical value. how to convert them to capacitance value?

  • Hi @all
    also this post is a little bit older - i wanted to let you know that i have started to write a arduino library for the FDC1004.
    (hopefully the next one that searches for this finds it ;-) )
    you can find the current state at github.com/.../slight_FDC1004
    i also designed a minimal break-out board with i2c levelshifting: github.com/.../TI_FDC1004_Breakout
    the basics of library are working. you can set the configuration and read values - but i don't know if all is correct... so needs some more testing..

    sunny greetings
    stefan
  • Hey, this is very good news! I and others will certainly be following your updates with great interest and appreciation. Anytime you are in Las Vegas, hit me up for a few adult beverages as a token of my appreciation!
  • Thanks to Josue Uribe for his interesting example!

    Building on and extensively modifying his code (based mostly on prior optimization of the registers using the TI demo program for this part), I have come up with the following four-channel scanning touch/proximity detector. Note that I mostly discarded the TI app note technique of derivative-integration, re-implementing it in a simpler and, for me anyway, more intuitive form. This is working and tested code (admittedly inelegant in its present state) but unlikely to be exactly what you need. Unfortunately I can't guarantee a response to questions about it, particularly those that can be answered by first consulting Mr. Google or the FDC2214 datasheet :)

    The Arduino is fantastic for quick prototyping. After the code is modified to your complete satisfaction it can be implemented on any flavor of microcontroller without much modification. Migration to the Raspberry Pi running Python should be easy too.

    With a 20 cm wire attached to any input the system can easily detect hand proximity at ~15 cm, or more if you care to tweak the thresholds.


    #include <Wire.h>

    float L = 0.5; //Leakage Factor.
    int delta_threshold = 500;
    int trigger_threshold = 1000;


    byte FDC = 0x2A;// FDC address either 0x2A or 0x2B;
    //byte FDC = 0x2B;// FDC address either 0x2A or 0x2B;


    //Build the complete conversion result from the specific channel
    unsigned long readChannel(byte Channel) {
    unsigned long val = 0;
    uint16_t c = 0;
    uint16_t d = 0;
    c = readValue(FDC, 2 * Channel);
    d = readValue(FDC, 2 * Channel + 1);
    val = c;
    val <<= 16;
    val += d;
    return val;
    }

    //Read bytes from register channel specified
    word readValue (int FDC, int reg) {
    byte a = 0;
    byte b = 0;
    uint16_t value = 0;
    Wire.beginTransmission(FDC);
    Wire.write(reg);
    Wire.endTransmission();
    Wire.requestFrom(FDC, 2);
    while (Wire.available())
    {
    a = Wire.read();
    b = Wire.read();
    }
    value = a;
    value <<= 8;
    value += b;
    return value;
    }


    void monitor() {
    long current[4];
    long delta[4];
    long deltaSum[4];
    long last[4];
    boolean sign[4];
    boolean triggered[4];
    long trigCounts[4];
    byte n;
    unsigned long zt, target;

    for (n = 0; n < 4; n++) {
    current[n] = readChannel(n);
    delta[n] = 0;
    deltaSum[n] = 0;
    last[n] = 0;
    sign[n] = false;
    triggered[n] = false;
    trigCounts[n] = 0;
    }
    long rc;
    zt = millis();
    target = zt + 1000;

    for (;;) {
    for (n = 0; n < 4; n++) {
    last[n] = current[n];
    rc = readChannel(n);
    current[n] = (3 * current[n] + rc) / 4;
    //Serial.println(current[n]);

    delta[n] = (current[n] - last[n]);
    sign[n] = (delta[n] > 0);
    delta[n] = abs(delta[n]);

    if (delta[n] > delta_threshold) {
    deltaSum[n] += delta[n];
    if ((sign[n] == 0) && (deltaSum[n] > trigger_threshold)) {
    // detect only downward changes
    if (triggered[n] == false) {
    trigCounts[n]++;
    //avoid multiple counts for single triggers;
    //triggered[] is reset to false only once per second
    }
    triggered[n] = true;
    // Serial.print(deltaSum[n]);
    // Serial.print('\t');
    // Serial.print(sign[n]);
    // Serial.print('\t');
    // Serial.println("DETECT!");
    }
    } else {
    deltaSum[n] *= L;
    // Serial.print(deltaSum[n]);
    // Serial.print('\t');
    // Serial.print(sign[n]);
    // Serial.print('\t');
    // Serial.println("-");
    }

    }

    delay(50);

    zt = millis();
    if (zt >= target) {
    target += 1000;
    // accept only 1 event per second across all sensors
    for (n = 0; n < 4; n++) {
    triggered[n] = false;
    }
    for (n = 0; n < 4; n++) {
    Serial.print(trigCounts[n]);
    Serial.print('\t');
    }
    Serial.println("");
    }
    }
    }


    //Configuring the FDC2214
    void writeConfig(int FDC, byte reg, byte MSB, byte LSB) {
    Wire.beginTransmission(FDC);
    Wire.write(reg);
    Wire.write(MSB);
    Wire.write(LSB);
    Wire.endTransmission();
    }

    void Configure() {
    // based on best results with the TI demo program
    writeConfig(FDC, 0x14, 0x10, 0x01);//CLOCK_DIVIDERS_CH0
    writeConfig(FDC, 0x1E, 0x88, 0x00);//DRIVE_CURRENT_CH0
    writeConfig(FDC, 0x10, 0x04, 0x00);//SETTLECOUNT_CH0
    writeConfig(FDC, 0x08, 0xFF, 0xFF);//RCOUNT_CH0

    writeConfig(FDC, 0x15, 0x10, 0x01);//CLOCK_DIVIDERS_CH1
    writeConfig(FDC, 0x1F, 0x88, 0x00);//DRIVE_CURRENT_CH1
    writeConfig(FDC, 0x11, 0x04, 0x00);//SETTLECOUNT_CH1
    writeConfig(FDC, 0x09, 0xFF, 0xFF);//RCOUNT_CH1

    writeConfig(FDC, 0x16, 0x10, 0x01);//CLOCK_DIVIDERS_CH2
    writeConfig(FDC, 0x20, 0x88, 0x00);//DRIVE_CURRENT_CH2
    writeConfig(FDC, 0x12, 0x04, 0x00);//SETTLECOUNT_CH2
    writeConfig(FDC, 0x0A, 0xFF, 0xFF);//RCOUNT_CH2

    writeConfig(FDC, 0x17, 0x10, 0x01);//CLOCK_DIVIDERS_CH3
    writeConfig(FDC, 0x21, 0x88, 0x00);//DRIVE_CURRENT_CH3
    writeConfig(FDC, 0x13, 0x04, 0x00);//SETTLECOUNT_CH3
    writeConfig(FDC, 0x0B, 0xFF, 0xFF);//RCOUNT_CH3

    writeConfig(FDC, 0x19, 0x00, 0x01);//ERROR_CONFIG
    writeConfig(FDC, 0x1B, 0xC2, 0x0C);//MUX_CONFIG
    writeConfig(FDC, 0x1A, 0x1E, 0x01);//CONFIG
    }


    void setup() {
    Wire.begin();
    Serial.begin(9600);
    Serial.println("And so it begins");
    Configure();
    }

    void loop() {
    Wire.beginTransmission(FDC);
    monitor();
    }