Capacitive Sensing vs Beat detection on Leonardo

Hi,
I want to trigger an LED either by beat detection or by capacitive sensing.

Both ideas work well separately but not together in one sketch .

First I used “ADCTouch” by martin2250 which had problems as it interfered with 2 other things that are connected to 2 other analog inputs.
After I tried the “CapSense”-library which apparently slows down the sampling of the beat detection algorithm which makes it fail :frowning:

Any tips for improving?

Thanks in advance

//***********************************************************
// Arduino Beat Detector By Damian Peckett 2015 modified 2017 by Johannes Hofmann
// License: Public Domain.
//***********************************************************

#include <CapacitiveSensor.h>
#include <TimerOne.h>

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int LedPin = 12;
int InterruptPin = 11;

//unsigned int pinElTransistor = ;
unsigned int pinPlasmaTransistor = 8;
//unsigned int pinElPoti = 1;
//unsigned int pinPlasmaPoti = 2;
unsigned int pinBeatPoti = 1;
unsigned int pinTouchSensor = 2;

unsigned int sampleIndex = 0;

bool envelopeTrigger = 0;
bool buttonTrigger = 0;
bool beatTrigger = 0;

CapacitiveSensor   cs_4_3 = CapacitiveSensor(4,3);

/*******************************************/
/******************* SETUP *****************/
/*******************************************/
void setup() {
  Timer1.initialize(200);
  Timer1.pwm(InterruptPin, 512);
  Timer1.attachInterrupt(setInterruptFlag);
  
  Serial.begin(9600);
  // Set ADC to 77khz, max for 10bit
  sbi(ADCSRA,ADPS2);
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);

  pinMode(LedPin, OUTPUT);
}

void setInterruptFlag(){
  if(sampleIndex++ > 200){  
    envelopeTrigger = 1;
    sampleIndex = 0;
  }
}

// 20 - 200hz Single Pole Bandpass IIR Filter
float bassFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = sample / 9.1f;
    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7960060012f * yv[0]) + (1.7903124146f * yv[1]);
    return yv[2];
}

// 10hz Single Pole Lowpass IIR Filter
float envelopeFilter(float sample) { //10hz low pass
    static float xv[2] = {0,0}, yv[2] = {0,0};
    xv[0] = xv[1]; 
    xv[1] = sample / 160.f;
    yv[0] = yv[1]; 
    yv[1] = (xv[0] + xv[1]) + (0.9875119299f * yv[0]);
    return yv[1];
}

// 1.7 - 3.0hz Single Pole Bandpass IIR Filter
float beatFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = sample / 7.015f;
    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7169861741f * yv[0]) + (1.4453653501f * yv[1]);
    return yv[2];
}

/*******************************************/
/***************** MAIN LOOP ***************/
/*******************************************/
void loop() {
   
    unsigned long time = micros(); // Used to track rate
    static float sample, value, envelope, beat, thresh;
    unsigned char i;

    
    // Read ADC and center so +-512
    sample = (float)analogRead(0)-503.f;

    // Filter only bass component
    value = bassFilter(sample);

    // Take signal amplitude and filter
    if(value < 0)value=-value;
    envelope = envelopeFilter(value);

    // Every 200 samples (25hz) filter the envelope 
    if(envelopeTrigger == 1) {
      envelopeTrigger = 0; // Reset interrupt flag      
      beat = beatFilter(envelope); // Filter out repeating bass sounds 100 - 180bpm      
      thresh = 0.02f * (float)analogRead(pinBeatPoti);// Get threshold based on potentiometer on analog input
//      Serial.print("Threshold = ");
//      Serial.println(thresh);

      // Compare beat with threshold
      if(beat > thresh) 
        beatTrigger = 1;
      else 
        beatTrigger = 0;
    }
    Serial.println(cs_4_3.capacitiveSensor(10));
    delay(200);
    /**** Check if sensor was touched ****/
    if( cs_4_3.capacitiveSensor(10) > 500 )
      buttonTrigger = 1;
    else
      buttonTrigger = 0;
     
    /**** Enable LED/transistor when beat wass detected or button pressed ****/
    if(beatTrigger == 1 || buttonTrigger == 1)
      digitalWrite(LedPin, HIGH);
    else
      digitalWrite(LedPin, LOW);

//    Serial.print("Beat-Value = ");
//    Serial.println(beat);
//    Serial.println(); 
}

main.ino (3.87 KB)

Use a cap sensing chip, the Arduino library is not reliable enough to use in a project it is just a demo thing.

Hm, that doesn't help me because I need it to work for an event on Saturday...
So there is no time for implementing a cap sensing chip.

Why do you say the library is not reliable enough? I tried two different ones and both worked fine so far.

Why do you say the library is not reliable enough?

Experience, and reports on the forum here.

But if you have to get it done in two days you don't have much choice do you? Given that their is no place local you can buy a touch sensor chip breakout board. Let us know how you go on.

It strikes me as odd that you would ask for advice without this vital piece of information.

I could improve it by shifting the touch detection into the if-statement that is triggered every 200 PWM-cycles.
Then it worked like it was meant to :slight_smile:
But unfortunately my energy supply let me down and I couldn't use it this time at the event.