Piezoelectric Sensor Knock

Hi,

I have a piezoelectric ribbon sensor that I am trying to get to turn on an LED when a force is applied and a "knock" is detected. It seems to work every so often but not consistently. When I have the force values printed it is showing that it seems to be reading force values even when I am not touching the sensor. It'll start at the negative value of the baseline from calibration then steadily increase without any force applied. I am using a 1M ohm resistor for it. I'll post my code and setup below. Any help would be appreciated.

// Constants 
const int piezoPin = A0;    // Analog pin connected to the piezo sensor
const int ledPin = 13;      // Digital pin connected to the LED
const int numReadings = 100;  // Number of readings for calibration
const int knockThreshold = 100; // Threshold for detecting a knock

// Variables
int readings[numReadings];  // Array to store sensor readings
int readIndex = 0;          // Index of the current reading
int total = 0;              // Total of all readings
int average = 0;            // Average of the readings
int baseline = 0;           // Baseline value for calibration

void setup() {
  Serial.begin(9600);       // Initialize serial communication
  pinMode(piezoPin, INPUT); // Set the piezo pin as input
  pinMode(ledPin, OUTPUT);  // Set the LED pin as output

  // Initialize all readings to 0
  for (int i = 0; i < numReadings; i++) {
    readings[i] = 0;
  }

  // Calibrate the sensor
  Serial.println("Calibrating sensor...");
  calibrateSensor();
  Serial.println("Calibration complete.");
  Serial.print("Baseline value: ");
  Serial.println(baseline);
}

void loop() {
  // Subtract the last reading
  total = total - readings[readIndex];

  // Read the sensor
  int sensorValue = analogRead(piezoPin);
  readings[readIndex] = sensorValue;

  // Add the reading to the total
  total = total + readings[readIndex];

  // Advance to the next position in the array
  readIndex = readIndex + 1;

  // If we're at the end of the array, wrap around to the beginning
  if (readIndex >= numReadings) {
    readIndex = 0;
  }

  // Calculate the average
  average = total / numReadings;

  // Calculate the force
  int force = average - baseline;
  Serial.begin(9600);       // Initialize serial communication
  Serial.print("force value");
  Serial.print(force);

  // Detect a knock
  if (force > knockThreshold) {
    Serial.println("Knock detected!");
    digitalWrite(ledPin, HIGH); // Turn on the LED
    delay(5);                 // Keep the LED on for 200 milliseconds
    digitalWrite(ledPin, LOW);  // Turn off the LED
  }

  // Wait 50 milliseconds before the next loop
  delay(200);
}

void calibrateSensor() {
  long sum = 0;
  
  // Take multiple readings to determine the baseline
  for (int i = 0; i < numReadings; i++) {
    int reading = analogRead(piezoPin);
    sum += reading;
    delay(50);  // Short delay between readings
  }

  // Calculate the baseline
  baseline = sum / numReadings;
}

Force outputs:

Circuit Setup:
image

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

https://docs.arduino.cc/built-in-examples/sensors/Knock/

Don't use a LED without current limiting resistor.
You will burn pin13 the way you have connected it.

It seems you have the the resistor connected in series, which is wrong.
Please post a clearer picture of the breadboard.

An int can only hold 32 readings of 1023 before it overflows.
Leo..

image

This is how I originally had the board set up and it was doing the same things. I have a 330 ohm resistor on the LED

I have used this example exactly and I'm not getting the same results. I am using a piezoelectric ribbon sensor which is a bit different from the discs, so I don't know if that changes things.

const int piezoPin = A0;    // Analog pin connected to the piezo sensor
const int ledPin = 13;      // Digital pin connected to the LED
const int knockThreshold = 50; // Threshold for detecting a knock
const int numReadings = 100;  // Number of readings for calibration

int baseline = 0;           // Baseline value for calibration

void setup() {
  Serial.begin(115200);       // Initialize serial communication
  pinMode(piezoPin, INPUT); // Set the piezo pin as input
  pinMode(ledPin, OUTPUT);  // Set the LED pin as output

  Serial.println("Calibrating sensor...");
  calibrateSensor();
  Serial.println("Calibration complete.");
  Serial.print("Baseline value: ");
  Serial.println(baseline);
}

void loop() {
  int sensorValue = abs(analogRead(piezoPin) - baseline);

  if (sensorValue > knockThreshold) {
    digitalWrite(ledPin, HIGH);
    delay(15);
    digitalWrite(ledPin, LOW);
  }

  delay(10);
}

void calibrateSensor() {
  long sum = 0;

  // Take multiple readings to determine the baseline
  for (int i = 0; i < numReadings; i++) {
    int reading = analogRead(piezoPin);
    sum += reading;
    delay(50);  // Short delay between readings
  }

  // Calculate the baseline
  baseline = sum / numReadings;
}
1 Like

I think I still see the resistor in series with the piezo, which is wrong.
The 1Meg resistor goes across the piezo.

So resistor connected to A0 and ground,
and piezo also connected to pin and ground.
Leo..

This code worked but it turns the LED on when I kind of pull the sensor rather than just when I touch it. I don't know if there is a way to fix that. Thanks!

try threshold 10

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.