DC offset Issues

Hi peeps :slight_smile:

I'm having issues with DC drift on a rather "how you doing" microphone input reader :confused: which I want to use as knock sensor.

The idea is a simple one, create a virtual ground between the +5V and ground using a simple resistor voltage divider and then use a speaker/microphone to inject voltage at the mid point, this is working better than expected however it looks like inductance or capacitance of the speaker coil is creating momentary DC drift, I have no real clue how to fix this, I tried strapping a resistor across the speaker terminals, one to stop high voltage spikes and was hoping that this would pin the DC offset, but as seen in the video it drifts, not by a great deal though and I could probably code this out, but would rather fix the issue.

Any ideas for resistor value or basically any thoughts on this and a good starting place to help me understand where I'm going wrong would be greatly appreciated. Thank you :slight_smile:

Post a circuit diagram, with parts values.
And the code (read the forum rules first).

Stab in the dark: too high resistor values, and/or a capacitor on the virtual ground.

You should really use a contact microphone for a knock sensor.
A contact speaker (surface transducer) could do, but a bare 1" piezo disk (musical wishing cards) with a 1Megohm resistor across works well.
There is even a (poorly written) knockSensor example in the IDE.
Leo..

Hi Wawa,

sorry I was having issues with the inline image displaying, found out the "how to" :slight_smile:

the values of the divider resistors are 3.9K just used what I had to hand, I could probably use much higher as I'm only interested in creating a virtual ground for the A/C of the microphone/speaker, the pickup coils are from Band Hero drums and are surprisingly sensitive to minor hits :slight_smile: and are what I also have to hand.

the code is from the knock sensor example as it was simple and plots well :slight_smile:

"pickup coils are from Band Hero drums"

That doesn't tell me anything.
Post a link.

The "knock" code is poor, because it takes ONE (~100ns) sample every 0.1sec.
Leo..

At the very least you need to AC couple into the input, that is put the speaker through a capacitor. However the voltage you are going to get from any speaker / microphone is way way too small to give you any meaningful signal you can measure. You need to amplify the signal so it is 5V peak to peak to get a good signal.

Im not sure how to measure this, I can say It's 10nF and my DMM can not read its resistance.....

well fool me lol, just dismantled it and the construction suggested voice coil, but it is in fact a piezo disk.

so what could be creating the D/C to drift?

Yep Mike,

I was surprised when hooked up the what I thought was a coil as I was getting very low values from using a speaker, oh well, next time I'll investigate a little further, I just didn't want to destroy what could have been a fine coil as It was taped up and foamed in :confused:

I'll keep the virtual ground point for now, as I don't want to inject negative voltage into my inputs.

It's all proof of concept Idea at the moment so the knock code is all I need to see if it worked.

How much shift/drift, and what do you mean momentary?

You generally don't want a virtual ground in this situation. You want the input biased at 2.5V so it can swing positive and negative from there. Then depending on the application you can subtract-out the bias in software.

Your connections are wrong but a coil WILL mess-up the voltage divider. You need a capacitor between the microphone and analog input to "isolate" the bias. A piezo will not mess-up the bias and you don't need the series capacitor.

[u]Here[/u] is a schematic. The two equal-value resistors provide the bias and the 10uF capacitor isolates the DC bias from the audio circuit while allowing the AC signal through. (You can leave out the 47nF capacitor.)

Generally, you need a preamplifier for a microphone, and that includes a speaker used as a microphone or a piezo used as a microphone. A piezo knock sensor might not need an amplifier, depending on how hard you "knock" it, but you need higher value resistors (1M to 10M) because low value resistors will kill the piezo signal.

You can run a line-level or headphone-level into the biased, capacitor-isolated, input without an amplifier.

With a piezo, you probably don't have to worry about negative voltages. The Arduino has (small) built-in protection diodes to protect it from negative voltages or voltages greater than +5V. Those little diodes won't protect it from high current so if you connect a 12V battery or 12V power supply, you'll kill it. But a piezo puts-out a very low current and you should be OK.

However, you do need a (high value) resistor across the Piezo to hold the DC input voltage at ground.

wow awesome thanks doug, will take me awhile to digest :slight_smile:

I think the DC drift was created from the piezo adding voltage to the 5v rail, I've also added diodes in series to the divider on both +5v and ground and that seems to have cured the issue, although it has dropped the centre voltage a little, not an issue for me as I'm only looking to use this as an analogue trigger for midi project.

Currently the sensitivity is great, from the lightest of taps to hard hits, using a 100k across the peizo to lower its output more and that has helped to stop it clipping but has dulled the sensitivity a smidgen.

thank you all for your advise and help, the original circuit was most definitely crude, if I get any good results from my build I'll post up on it :slight_smile:

Just connect the piezo between pin and ground, with a 1Megohm load resistor also from pin to ground.
A small piezo can't produce enough current to damage the pin protection 'diodes' of the analogue input,
(assuming you're not going to hit it with a hammer).
The 1Meg resistor is to refer the analogue input to ground (no DC offset).
Try this sketch. It reads the analogue pin multiple times, so bridges negative waves, and stores the peak value.
Leo..

// knock sensor/alarm
// Piezo, with 1Megohm load resistor across, connected to A0 and ground
// optional 5volt buzzer on pin 13

int threshold = 100; // alarm threshold from 1 (very sensitive) to 1022 <<<<<<<<
int alarmDuration = 100; // alarm duration in milliseconds <<<<<<<<

const byte piezoPin = A0;
int rawValue; // raw A/D readings
int piezoValue; // peak value
const byte onboardLED = 13; // onboard LED and/or buzzer

void setup() {
  analogReference(INTERNAL); // remove this line if too sensitive
  Serial.begin(115200); // serial monitor for raw piezo output
  pinMode (onboardLED, OUTPUT);
}

void loop() {
  // reset
  piezoValue = 0;
  // read
  for (int x = 0; x < 250; x++) { // multiple A/D readings
    rawValue = analogRead(piezoPin);
    if (rawValue > piezoValue) {
      piezoValue = rawValue; // store peaks
    }
  }
  // print
  if (piezoValue > 0) {
    Serial.print(F("Piezo value is "));
    Serial.println(piezoValue);
  }
  // action
  if (piezoValue > threshold) {
    Serial.print(F("Knock was over the threshold of "));
    Serial.println(threshold);
    digitalWrite (onboardLED, HIGH);
    delay(alarmDuration);
    digitalWrite (onboardLED, LOW);
  }
}