Search code examples
matharduinomicrocontrollercapacity

Calculating the average of Sensor Data (Capacitive Sensor)


So I am starting to mess around with Capacitive sensors and all because its some pretty cool stuff.

I have followed some tutorials online about how to set it up and use the CapSense library for Arduino and I just had a quick question about this code i wrote here to get the average for that data.

void loop() {                    
  long AvrNum;
  int counter = 0;

  AvrNum += cs_4_2.capacitiveSensor(30);
  counter++;

  if (counter = 10) {
    long AvrCap = AvrNum/10;
    Serial.println(AvrCap);
    counter = 0;
  }
}

This is my loop statement and in the Serial it seems like its working but the numbers just look suspiciously low to me. I'm using a 10M resistor (brown, black, black, green, brown) and am touching a piece of foil that both the send and receive pins are attached to (electrical tape) and am getting numbers around about 650, give or take 30.

Basically I'm asking if this code looks right and if these numbers make sense...?


Solution

  • The language used in the Arduino environment is really just an unenforced subset of C++ with the main() function hidden inside the framework code supplied by the IDE. Your code is a module that will be compiled and linked to the framework. When the framework starts running it first initializes itself then your module by calling the function setup(). Once initialized, the framework enters an infinite loop, calling your modules function loop() on each iteration.

    Your code is using local variables in loop() and expecting that they will hold their values from call to call. While this might happen in practice (and likely does since that part of framework's main() is probably just while(1) loop();), this is invoking the demons of Undefined Behavior. C++ does not make any promises about the value of an uninitialized variable, and even reading it can cause anything to happen. Even apparently working.

    To fix this, the accumulator AvrNum and the counter must be stored somewhere other than on loop()'s stack. They could be declared static, or moved to the module outside. Outside is better IMHO, especially in the constrained Arduino environment.

    You also need to clear the accumulator after you finish an average. This is the simplest form of an averaging filter, where you sum up fixed length blocks of N samples, and then use that average each Nth sample.

    I believe this fragment (untested) will work for you:

    long AvrNum;
    int counter;
    
    void setup() {
      AvrNum = 0;
      counter = 0;
    }
    
    void loop() {                    
    
      AvrNum += cs_4_2.capacitiveSensor(30);
      counter++;
    
      if (counter == 10) {
        long AvrCap = AvrNum/10;
        Serial.println(AvrCap);
        counter = 0;
        AvrNum = 0;
      }
    }
    

    I provided a setup(), although it is redundant with the C++ language's guarantee that the global variables begin life initialized to 0.