I want to detect the tap/sound, I am using piezo transducer (circular) and connected it to raspberry pi using ADC (MCP3008, SPI communication). When I tap on the transducer the output value should increase somewhere between 0 to 1023 depending on the tap vibrations. But I am getting reverse output values, the output value read is 1023 when I do not tap and when I tap it continuously the output value reaches to 0(Zero). Could anyone tell me the reason for this? I have connected red wire (+ve) of transducer to the CH0 (channel 0) of ADC and black wire of transducer to GND of raspberry pi. I think the connection is perfect. Is that characteristic of Piezo transducer, to send output low signal when tap is detected and high signal when no tap? Below is the code


import spidev
import time
import os

# Open SPI bus
spi = spidev.SpiDev()

# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7
def ReadChannel(channel):
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Function to convert data to voltage level,
# rounded to specified number of decimal places.
def ConvertVolts(data,places):
  volts = (data * 3.3) / float(1023)
  volts = round(volts,places)
  return volts

# Define sensor channels
piezo_channel = 0
piezo_level = ReadChannel(light_channel)
piezo_volts = ConvertVolts(light_level,2)

  # Print out results
  print "--------------------------------------------"
  print("Light: {} ({}V)".format(piezo_level ,piezo_volts ))

  # Wait before repeating loop
  • \$\begingroup\$ Umm, won't 1023 - x work fine here? \$\endgroup\$ – fizzle Jun 11 '16 at 14:30
  • \$\begingroup\$ What specific transducer are you using? \$\endgroup\$ – Peter Smith Jun 11 '16 at 15:04
  • \$\begingroup\$ @PeterSmith I am using this type of transducer but I have not ordered from here. I have ordered it from ebay. \$\endgroup\$ – pradeep Jun 11 '16 at 16:14

Piezo-electric transducers approximate, to a first order analysis, a capacitor.

Assuming you have hooked up the device like this:


simulate this circuit – Schematic created using CircuitLab

As a transducer of this type has no current flow in a static situation, then with no vibration at the transducer, the voltage read in the ADC is indeed the voltage at the positive side of the transducer.

The reason you even see other readings when you tap the device lies in the input circuitry of the ADC you are using:

MCP3008 Input Stage

On the first measurement (no tapping) the input sampling capacitor will charge up to Vpos; when you tap the transducer (assuming the channel is connected for sampling), a small ac current will flow from Vpos and the sampling capacitor in the ADC, changing the voltage on the sampling capacitor, so you read a value other than full scale.

Note that the sensitivity of the input will depend on the sampling frequency (which I do not know); the sampling capacitor is in circuit for 1.5 clock cycles.

Tap it often enough and the sampling capacitor will completely discharge (where you will read 0 from the ADC result).

To properly read it, you should really hook it up like this:


simulate this circuit

The value of resistor here is not necessarily accurate; there are only small currents induced in most of these devices.

| improve this answer | |
  • \$\begingroup\$ you are explaining the exact scenario as I am facing here... I have connected +ve end of transducer to 1K resistor and other end of resistor to ADC CH0, in simple words I have 1K resistor in between ADC and Transducer. But still I am facing same problems.. Do I need to connect 1K resistor between ADC and power supply? \$\endgroup\$ – pradeep Jun 14 '16 at 15:21
  • \$\begingroup\$ used resistors up to mega 25 mega ohms.. still getting same readings.. the technique you suggested id it pull up? I think I should try pull down.. what do you say? \$\endgroup\$ – pradeep Jun 15 '16 at 0:15

You are using a piezo transducer that is designed to be a 6.5KHZ buzzer. Tapping it can generate a series of decaying pulses, not just one pulse. Also the tin coating on them will corrode quickly if not coated in polyurethane spray.

As for the reverse reading, use 'piezo_buff' to store the reverse value, then take that value and subtract it from 1023 and that would be your output to 'piezo_volts' (be sure to init 'piezo_volts' to '0' first). If your code is working correctly with a just a reversed output, fix it at the output stage so you do not need to tamper with your main code.

By the way, did you init your variables correctly before using them?

| improve this answer | |
  • \$\begingroup\$ you are advising me to adjust code to get the required output which I would follow in worst case. But here I want to know the reason behind the problem. \$\endgroup\$ – pradeep Jun 14 '16 at 15:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.