Uno and Piezo sensor as a switch

Total Newbie!!!

I am trying to use the Arduino Uno with a Piezo Sensor to simply turn a LED light on when the Piezo detects a vibration over a certain threshold and then off right away. I want the light to simply blink when the vibration is detected. Currently, the light comes on when the vibration is detected but does not turn off until it is detected again.

int piezoPin = A0;         // the number of the input pin
int LED = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

void setup()
{
  pinMode(piezoPin, INPUT);
  pinMode(LED, OUTPUT);
}

void loop()
{
  reading = analogRead(piezoPin);


if (reading > 0.5 && previous == 0) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

  }


  digitalWrite(LED, state);

  previous = reading;
}

Thanks for the help!!!

what's the type and range of values returned by analogRead(piezoPin)??

do you think if ([color=red]reading > 0.5 [/color]&& previous == 0) { makes sense?

Here is a sample from when i smack the table it is sitting on.

0.04
0.01
0.00
0.00
0.00
0.00
0.06
0.00
0.00
0.04
0.05
0.00
0.00
0.06
0.00
0.00
0.00
0.00
0.00
0.02
0.00
0.00
0.04
0.00
0.00
0.00

I don't believe you... analogRead returns an integer between 0 and 1023... not a floating point...

That is what I am seeing when I use this test code from sparkfun. I also have a 1MΩ load resistor dampening the voltage so it doesn't blow our the board.

const int PIEZO_PIN = A0; // Piezo output

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

void loop() 
{
  // Read Piezo ADC value in, and convert it to a voltage
  int piezoADC = analogRead(PIEZO_PIN);
  float piezoV = piezoADC / 1023.0 * 5.0;
  Serial.println(piezoV); // Print the voltage.
}

I suppose you understand the maths here

  int piezoADC = analogRead(PIEZO_PIN);
  float piezoV = piezoADC / 1023.0 * 5.0;

is not the same as

 reading = analogRead(piezoPin);
if (reading > 0.5 && previous == 0) {

right?

try this code to see exactly what you get

const int PIEZO_PIN = A0; // Piezo output

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

void loop() 
{
  int piezoADC = analogRead(PIEZO_PIN);
  Serial.println(piezoADC); // Print the value.
}

OK, this is me banging on the table. And no, didn't really understand the math. I have changed the number in my code to 5 instead of 0.5, but this only makes it harder to trigger the light. It doesn't, however, help with my issue. The light still stays on once it comes on. Any ideas?

0
1
3
5
5
1
0
0
0
0
9
17
8
0
0
0
0
0
11
15
6
0
0
0
0
5
13
10
0
0
0
0
0
0
7
10
5
0

if (reading > 5 && previous == 0) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

  }

Thanks for your help!!!

the math where just changing the value you read (which is between 0 and 1023) into voltage between 0 and 5V

well with the code I gave you you see the true output of the analogRead... so when you "bang" on the table your value varies between 0 and 17. an analog read can go all the way to 1023... so see you're not getting much of a meaning full signal there.... (unsurprising with a bare piezzo)

for the light staying on, think again about your logic...

Well, I guess that what I need help with, my logic.

I am trying to use the Arduino Uno with a Piezo Sensor to simply turn a LED light on when the Piezo detects a vibration over a certain threshold and then off right away. I want the light to simply blink when the vibration is detected

I don't understand what you are trying to achieve

if you want the LED to light on when Piezo is over a certain threshold then just read the value and if above threshold turn on, otherwise turn off.

what do you mean by "blink" when vibration is detected?

for example with your input above and a threshold at >= 3 that would do this.

0 Turn off
1
3 Turn on
5
5
1 Turn off
0
0
0
0
9 Turn on
17
8
0 Turn off
0
0
0
0
11 Turn on
15
6
0 Turn off
0
0
0
5 Turn on
13
10
0 Turn off
0
0
0
0
0
7 Turn on
10
5
0 Turn off

given it's going fast ON and OFF, you won't see much besides a barely bright LED

The problem is, my code is not working. The light comes on when the threshold is above what I define, but it does NOT turn off unless the threshold goes over what I defined for a second time. If I hit the table, it comes on and stays on until I hit the table again. It should, only blink when I hit the table.

Again - Define "blink"... where do you see your code blink ?

The LED light should blink.

Blink how fast ? How long will it on ? How long will it off ?

Couple of things...

Why go through the waste of cycles converting analog read 0 to 1023 to anything else?
If you have a threshold, it will be in that range, it's not as if determining volts is your goal is it?

Piezo hit or tapped directly can make spikes I wouldn't put on my Arduino pins. A few times, 100 times, the possible damage might not be noticed. You can run your PC without a ground too if you like replacing parts every week or two.

Try feeding your piezo output to an NPN transistor gate. The piezo will open the gate for time equal to how hard it is flexed. In my experiments I had the transistor feed current to a wire connected to a digital pin. The pin went HIGH, reading the pin over and over drained the charge to LOW and the number of reads told me how hard I hit the piezo. Arduino can read that pin 50,000 times per second, a hard smack with a screwdriver handle would take about 2000 reads while a very soft touch took about 20. That was with 5V through a 2.2K resistor feeding the transistor, the resistor "tunes" the sensitivity of that circuit.

You can amplify the piezo output, changing voltage to current to make pin-safe input.

On youtube search for ants amplified. It's extreme, the piezo picks up ants stepping on it.

OK, I apologize. I was trying to just us the LED light as a test, but it seemed to add some confusion and perhaps over complicated things.

All I really want to do is send a signal to a WAV Trigger board when the Piezo sensor detects a signal.

The Piezo sensor part of this code is working fine. The WAV board is also getting a signal and triggering the sound. The problem is, it's triggering all the sounds on the board instead of one. I know the WAV board is setup correctly because when a switch is connected, instead of the Uno, it works perfectly. It chooses randomly between 3 different audio files to play. It plays one sound just once.

This is why I thought that using a LED light as a test would be better because if it would turn on and right back off that would act more like a switch.

Here is my code again:

int piezoPin = A0;         // the number of the input pin
int LED = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin


void setup()
{
  pinMode(piezoPin, INPUT);
  pinMode(LED, OUTPUT);
} 

void loop()
{
  reading = analogRead(piezoPin);


if (reading > 1 && previous == 0) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

  }


  digitalWrite(LED, state);
//  delay(100);  

  previous = reading;
}

I think I tried to say that multiple times... run your code manually to see what it does, remembering that your loop will execute thousands of times per second and that analogRead might not return 0 even if there is no "hit" (the value can be between 0 and 1023)

(Your switch is super stable for hundreds of milliseconds at minimum and you likely keep it on or off - here you have probably hundreds of HIGH/LOW per second)

OK, I understand what you are saying, but I am not a programmer so I do not know how to write the code to implement what you are saying.

notasium:
OK, I apologize. I was trying to just us the LED light as a test, but it seemed to add some confusion and perhaps over complicated things.

All I really want to do is send a signal to a WAV Trigger board when the Piezo sensor detects a signal.

The Piezo sensor part of this code is working fine. The WAV board is also getting a signal and triggering the sound. The problem is, it's triggering all the sounds on the board instead of one. I know the WAV board is setup correctly because when a switch is connected, instead of the Uno, it works perfectly. It chooses randomly between 3 different audio files to play. It plays one sound just once.

This is why I thought that using a LED light as a test would be better because if it would turn on and right back off that would act more like a switch.

The led is good but your eyes are too slow to see it flicker faster than 24x a second.

This sketch will show the raw reads at about 20 per second just to give ballpark data figures.
With those we have step one in converting the data into different midi sound triggers.

int piezoPin = A0;         // the number of the input pin
int LED = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin


void setup()
{
  Serial.begin( 250000 ); // as fast as it can be, change Serial Monitor to match

  pinMode(piezoPin, INPUT);
  pinMode(LED, OUTPUT);
} 

void loop()
{
  reading = analogRead(piezoPin);
  Serial.println( reading);


if (reading > 1 && previous == 0) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

  }


  digitalWrite(LED, state);
  delay(50); // it will now show almost 20 reads a second   

  previous = reading;
}

What you've shown is that one hit makes the table vibrate for some period of time. To your or my senses it is a moment. To 16MHz Arduino it is a good while. If you want 1 hit makes 1 sound then the code will need to watch the whole event, record the highest value in a variable and/or with how many reads in the group above some low threshold to determine how hard the table was hit. A good look at the data will tell. For that you don't want to mess with the data.

Where you have the piezo connect to the pin, do you also have a pulldown to drain the wire? With my digital read-and-count method I did not since I used the reads to drain the wire, but I was reading that pin more than 100x in the time it would take to make a single analog read. 10 bit analog read takes 105 micros, a digital read takes less than 1 micro.

I give you these facts to try and shed light on what you are doing. The data will put numbers on that. You are not so far from different sounds for different hits as may seem.

Wow! I can't thank you enough for the help and the explanation. This is very helpful, and I think I even understand it!!! I am not able to work on it today, but will back at it tomorrow. I am not sure what you mean by "pulldown" but I do have a resistor in parallel with the sensor and Uno.

Thanks again!