Strange Piezo Readings (I've searched before making this topic)

Hello,

I’m using this exact scheme from the knock tutorial with Arduino Due (the resistor is 1mohm) >

…and this code to test the piezo while observing the serial monitor:

int piezo = A0;
int threshold = 200;//anything over 200 means I've hit the piezo

void setup(){
  Serial.begin(9600);
}




//this part checks if the threshold has been reached and then writes the strenght of the signal 

void loop(){
  int piezoVal = analogRead(piezo);
  if (piezoVal>threshold){
    Serial.println(piezoVal);
    delay(10); //delay is used to prevent from getting multiple values one after another, usually 3-4
  }
}

The things that bother me are:

  • if I do not use threshold, then I am constantly getting readings from the piezo, even if the threshold is slightly below 200.

  • if I do not use delay, then I’m getting getting multiple values one after another

  • and the strangest thing is while I hit the mouse pad that covers the piezo, the readings in the serial monitor are not matching the force being used to trigger the piezo. Sometimes they stay the same, sometimes they reach 6-700 after I directly touch the piezo, sometimes I hit really hard and I only get some slight increase (for ex. from 225 to 229).

This doesn’t make sense to me. I think the stronger the vibration, the higher the values should be. Cause I’ve tried with two different piezos and different resistors (1mOhm, 1.2 mOhm and 1.5 mOhm) and I’m still getting the same result. I bought the Due few days ago in order to build a drum kit, and I have no problem with sending midi notes to a DAW, but this piezo sensitivity thing is driving me crazy. Any suggestions?

try this variation… which doesn’t use delay().

int state = LOW;

void setup()
{
  Serial.begin(115200);
}


void loop()
{
  int piezoVal = analogRead(piezo);
  if ((piezoVal > threshold) && (state == LOW))
  {
    state = HIGH;
    Serial.print(millis());
    Serial.print("\t");
    Serial.println(piezoVal);
  }
  if ((piezoVal < threshold) && (state == HIGH))
  {
    state = LOW;
    Serial.print(millis());
    Serial.println("\tLOW");
  }
}

@robtillaart, still same result. I’ll probably need some filtering to keep the peaks only, and ignore the increasings and decreasings of the piezo puls. Any idea of how that could be accomplished?

Before you go any further can I suggest you remove everything from pin 0 and use pin 2 instead. Naturally you'll have to change int piezo = A0; to int piezo = A2; as well.

Pin 0 is used for Serial communication and may be having an effect on your outcomes.

your remark about port 0 and 1 makes sense in general, but A0 is really the first analog port and not the Serial one...

I would suggest to change the 1MB resistor with a 4K7 or so to pull the signal much faster to GND level.
maybe you need to use a potmeter to find to the optimal value.

robtillaart:
your remark about port 0 and 1 makes sense in general, but A0 is really the first analog port and not the Serial one...

Yes you're quite right. Just me having a moment :slight_smile:

robtillaart:
your remark about port 0 and 1 makes sense in general, but A0 is really the first analog port and not the Serial one...

I would suggest to change the 1MB resistor with a 4K7 or so to pull the signal much faster to GND level.
maybe you need to use a potmeter to find to the optimal value.

You mean change the 1megaOhm with 47kiloOhms or 470kiloOhms?

I was suggested to use a peak hold circuit and from I'm seeing that would be the only way to filter out the increasings-decreasings of the piezo pulse and eliminate them being sent as midi notes and keep only the highest one as a valid.
I'm kinda noob for electronics so could anyone instruct me how to build one for this particular situation?

Thanks

4K7 == 4700 ohm == 4.7K

I’m getting the same results using Arduino Due.

When I use Arduino Uno, I get readings for a period of time, until the signal decays and I stop getting the readinds, as it would be expected.

Using the same circuit but on the Due, I get constant readings even without hitting the piezo. Even if I increase my threshold value, I keep getting readings.

My circuit is a 10K resistor and a BAT85 diode, both in parallel to the piezo. Any one understands why this happens?

This is the code I’m using for both Uno and Due:

int analogPins[12] = {A0, A1, A2, A3, A4, A5, 4, 6, 8, 9, 10, 12};
int anaPin = 0;
unsigned long TIME;

// 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



void setup() {
 
Serial.begin(115200);
 
#if defined(__AVR__)
// set prescale to 8
cbi(ADCSRA,ADPS2);
sbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS0);
#endif

#if defined(__arm__)
//REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00030000; //0x00020000; #MICRODRUM#
//REG_ADC_MR = (REG_ADC_MR & 0xFFFFFF0F) | 0x00000080; //enable FREERUN mode

REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000;
analogReadResolution(12);
#endif
  
Serial.flush();
Serial.println("Ready!");
}


void loop() {

 for(anaPin = 0; anaPin < 1; anaPin++)
 {
 
   int sensorValue = analogRead(anaPin);
   if (sensorValue > 140) { //UNO = 1023 & 35 || DUE = 4095 & 140
TIME = millis();
   

Serial.print(TIME);
Serial.print(" > ");
Serial.println(sensorValue);
   //delay(50);
   }
 }
}