Noisy analog reference when using usb wall adapter

I am making a device that measures temperature and vibrations and records the values onto an SD card. It will be a standalone device that is powered via the USB port, preferably with a USB wall adapter.

Design and debugging has been done with the Arduino powered via a laptop. However, when I tested the final device with a wall adapter, the vibration detection failed. The threshold was always overcome due to noise in the analog piezo read-out. It appears that the wall adapter gives a jitter or noise to the 5V which I am using as an input via a divider for the piezo. The noise trips the threshold.

The hardware used:

  • Arduino Uno
  • PCF8523 RTC clock
  • MAX3186 + PT100 RTD temperature sensor
  • Adafruit data logger shield
  • Typical bare piezo sensor

The piezo sensor is read via analog input 0. It is connected with the red terminal to A0 and the black terminal to a voltage divider of 2x100K resistors between 5V and GND. A 10uF cap is attached from the voltage divider to GND to stabilise the signal. A 1M resistor is placed in parallel with the piezo to slightly reduce the sensitivity.

When connected to the laptop USB port, the resting value jumps between 511 and 512. The threshold is set at 518 to pick up any small vibration spikes. When connected to a wall adapter, the signal jumps +/- 50 bits so any small vibrations completely dissapear in the noise.

I would like some help to find the best way forward. I have some rough ideas but find it hard to pick the right direction:

  • Change analog 2.5V from the divider to a stable signal (measure from GND? > means losing negative peaks...)
  • Stabilise the current 2.5V divider signal
  • Use a different 5V source
  • Stabilise the USB wall adapter source

So I just tried powering the Arduino with 9V via the jack input, hoping that the internal regulator gives a more steady signal. Unfortunately, this did not help and actually seems to make things worse, the jitter is now +/- 65 bits...

Any ideas?

Perhaps wiring issue - perhaps with ground?

Are all the wires laid out neatly? Any large loops between signal and ground or power and ground will pick up interference. A photo of the setup might be illuminating.

Any sources of electrical interference nearby such as fluorescent lights?

MarkT:
Perhaps wiring issue - perhaps with ground?

Are all the wires laid out neatly? Any large loops between signal and ground or power and ground will pick up interference. A photo of the setup might be illuminating.

Any sources of electrical interference nearby such as fluorescent lights?

That's the weird thing, it works flawlessly in the final setup when connected to a laptop USB port. I really expect to be because I use the 5V through a voltage divide for the piezo combined with noise on the 5V input from AC/DC adapters.

I guess my question is, how can I get a truly stable 5v on the Arduino when powered from AC?

The ratiometric behaviour of the piezo and A/D is defeated by the 10uF cap.
That cap makes it more sensitive to supply ripple.
Remove it, and lower the 100k resistors to 10k resistors.

The 1Meg resistor is mainly there to also have that same voltage of the divider (VCC/2) on the analogue pin.
Otherwise the pin would be 'floating' for DC, since the piezo is mainly a capacitor.
The resistor only lowers sensitivity below a certain (very low) frequency.

Wiring is very important with that high impedance (short and/or shielded), and you can't have the piezo grounded to metal.

Another option is to set the Uno Aref to EXTERNAL in setup(),
and connect the Aref pin to the 3.3volt pin (must do BOTH!!!).
Then power the voltage divider also from the 3.3volt pin.
That makes the setup fully independent of the 5volt supply of the Uno.

Like to see your code (the analogRead part).
Leo..

Wawa:
The ratiometric behaviour of the piezo and A/D is defeated by the 10uF cap.
That cap makes it more sensitive to supply ripple.
Remove it, and lower the 100k resistors to 10k resistors.

The 1Meg resistor is mainly there to also have that same voltage of the divider (VCC/2) on the analogue pin.
Otherwise the pin would be 'floating' for DC, since the piezo is mainly a capacitor.
The resistor only lowers sensitivity below a certain (very low) frequency.

Wiring is very important with that high impedance (short and/or shielded), and you can't have the piezo grounded to metal.

Another option is to set the Uno Aref to EXTERNAL in setup(),
and connect the Aref pin to the 3.3volt pin (must do BOTH!!!).
Then power the voltage divider also from the 3.3volt pin.
That makes the setup fully independent of the 5volt supply of the Uno.

Like to see your code (the analogRead part).
Leo..

Thanks for that lesson, obviously I don't fully understand my own circuit. That's what you get when you try stuff after googling haha. Could you maybe explain how the small cap on the voltage divider actually makes things worse? I would expect it to stabilise the 2.5V signal? And in what way does the resistor value in the divider impact the signal?

Regarding the piezo, it's wired with about 75 cm of shielded paired wire, should be good! It's not grounded either. And considering everything works fine with power from a laptop, I guess the cause should be somewhere where the power supply has some influence. Actually, the program stops properly working when connecting the laptop to 230V as well, so it's probably something to do with mains 50Hz ripple or something similar?

My code is a bit long to post in completeness (I could do that as well if you want) but here are the functions for the piezo readout. I call readPiezo() from the loop functions without any delays. The rest of the functions (temperature, buttons, clock, datalogger) are called with millis().

void readPiezo()
{
  // Read piezo
  Piezo = analogRead(piezoPin);
  Piezo = Piezo - 512;
  Piezo = abs(Piezo);
  // Update piezo
  if (Piezo > piezoThreshold)
  {
    updatePiezo(&piezoHistory, 1);
    // Store max Piezo value
    currentMaxPiezoPerCrack = max(currentMaxPiezoPerCrack, Piezo);
  } else
  {
    updatePiezo(&piezoHistory, 0);
  }
  if (hasCrackOccured(&piezoHistory))
  {
    crackCounter++;
    maxPiezo = max(maxPiezo, currentMaxPiezoPerCrack);
    previousMaxPiezoPerCrack = currentMaxPiezoPerCrack;
    currentMaxPiezoPerCrack = 0;
  }
}

void updatePiezo(uint64_t*history, int value)
{
  *history = *history << 1;
  *history |= value;
}

uint8_t hasCrackOccured(uint64_t*history)
{
  return (*history == 0b0000000000000000000000000000000000000000000000000000000000000001);
}

Could you maybe explain how the small cap on the voltage divider actually makes things worse?

The ADC computes the ratio of the analog reference voltage and the analog input voltage. When the analog reference voltage is noisy and the input voltage is stable, the result is noisy.

in what way does the resistor value in the divider impact the signal

The ADC has an input capacitor that must be charged, and is designed for an input source impedance of 10K or less. If the source impedance is higher, the capacitor will not be fully charged during the measurement cycle, leading to erroneous readings.

All this is discussed in the processor data sheet.

^that.
If supply (default Vref) drops, and voltage on the pin stays the same, then A/D result goes up.
If you let voltage (divider) also drop with the same ratio, then A/D result will stay the same.

I expected dozens or hundreds consecutive A/D samples for a vibration sensor, not just one.
Sudo code

  minValue = 1023; maxValue = 0; // reset
  piezoValue = analogRead(piezoPin); // one dummy read
  for (int i = 0; i < numSamples; i++) {
    piezoValue = analogRead(piezoPin);
    if (piezoValue > maxValue) maxValue = piezoValue;
    if (piezoValue < minValue) minValue = piezoValue;
  }
  piezoValue = maxValue - minValue; // always positive
  if (piezoValue > threshold) // action code here

Leo..

jremington:
The ADC computes the ratio of the analog reference voltage and the analog input voltage. When the analog reference voltage is noisy and the input voltage is stable, the result is noisy.
The ADC has an input capacitor that must be charged, and is designed for an input source impedance of 10K or less. If the source impedance is higher, the capacitor will not be fully charged during the measurement cycle, leading to erroneous readings.

Thanks for the clarification! I will try changing the resistors to 10K and I will remove the cap. Will report back with any improvements.

Wawa:
^that.
If supply (default Vref) drops, and voltage on the pin stays the same, then A/D result goes up.
If you let voltage (divider) also drop with the same ratio, then A/D result will stay the same.

I expected dozens or hundreds consecutive A/D samples for a vibration sensor, not just one.
Sudo code

Ah I get it. So basically what I did was I stabilised the signal from the Piezo but left the reference voltage noisy so the result is noisy?

Regarding you pseudo code, you are checking for the maximum difference between the lower and higher spikes. So what you get is roughly twice the amplitude within the measurement window. That's a nice alternative, I will see if I can use something similar in my own code in combination with the debouncer.

Wawa:
^that.
If supply (default Vref) drops, and voltage on the pin stays the same, then A/D result goes up.
If you let voltage (divider) also drop with the same ratio, then A/D result will stay the same.

I expected dozens or hundreds consecutive A/D samples for a vibration sensor, not just one.

I did two sets of measurements, one with USB power and one with 9V powered through the jack with a switching adapter.

Before these measurements, I removed the 10uF cap, changed the resistors of the voltage divider to 5.1K (didn't have 10K at hand). I also modified my code to take 100 samples according to your suggested method.
USB

9V

Piezo_9V.png

Piezo_USB.png

The plot labeled "9V" suggests that the analog input is picking up electrical interference from the environment (e.g. capacitive coupled AC hum from the house wiring).

And using shielded wire without one end of the shield at true common ground does absolutely nothing and may even make things worse.

Paul

Paul_KD7HB:
And using shielded wire without one end of the shield at true common ground does absolutely nothing and may even make things worse.

Paul

This was the key, I connected the shield to GND and it solves my issues. I still find it strange that I don't see the same problems when using USB power. Thanks for the insight!