Contact microphone pinMode problem

Status
Not open for further replies.

bryan5555

New member
I'm trying to use the "knock" example code on a Teensy 3.2. It works as expected unless I include "pinMode(knockSensor, INPUT);" in the setup in which case the pin hangs on a higher value (different every time) and does not return to 0. Ultimately I'd like to use this in a situation where a single pin will sometimes be used as a button and sometimes as a contact mic input which means I will need to switch the pin mode between INPUT and INPUT_PULLUP otherwise I guess I don't even need to set the pinMode initially.

What am I doing wrong?
 
As the forum rules say: give enough information (code, schematics, etc.) so that others may easily reproduce your problem. IMHO, it is basically not a good idea using one pin with different peripherals and changing the pin configuration “on the fly”. PinMode(x, INPUT) will put the pin into a high Z CMOS logic input which expects defined signals (LOW <=0.3V or HIGH >= 2.7V) fed from outside. If these conditions aren’t satisfied, undefined behavior is the logical consequence.
 
What am I doing wrong?

Maybe you're using analogRead()? That's just a blind guess, but if so, use INPUT_DISABLE to put the pin back to a mode where the digital circuitry (with slight leakage current) is turned off.

Otherwise, as Theremingenieur explained, the way we work here involves questions that give a complete & clear picture of what you're really doing. Don't "tell" us, actually "show" what you're really doing. We can help much more when we can see what's really going on.
 
I have used this knock example, https://www.arduino.cc/en/Tutorial/Knock, with piezo vibration sensor to an analog pin with 1 Mohm resitor in parallel to ground. the example works on UNO and T3.2. you have to tap the piezo or place some mass on sensor (e.g., stapler) to detect taps on the table. You don't want to use any pinMode() for the analog pin. (for debugging you could print out the analog value each time through loop() to see how sensitive sensor/mic is)
vibration sensor: https://www.sparkfun.com/products/10293

what "mic" are you using?
 
You're absolutely right - I'll try to provide better information.

The circuit is as manitou described it- the piezo is between PIN17 and GRD with a 1Mohm resistor between GRD and PIN17. Here's the slightly modified Knock code I'm using which works great

Code:
const int ledPin = 13;      // led connected to digital pin 13
const int knockSensor = 17; // the piezo is connected to analog pin 0
const int threshold = 100;  // threshold value to decide when the detected sound is a knock or not


// these variables will change:
int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;         // variable used to store the last LED status, to toggle the light

void setup() {
  pinMode(ledPin, OUTPUT);
//  pinMode(knockSensor, INPUT);// declare the ledPin as as OUTPUT
  Serial.begin(9600);       // use the serial port
}

void loop() {
  
  sensorReading = analogRead(knockSensor);
  Serial.println(sensorReading);

  if (sensorReading >= threshold) {
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    Serial.println("Knock!");
  }
  delay(100);  // delay to avoid overloading the serial port buffer
}

Here's the code that's not working. The only change is that I added in the commented out line " pinMode(knockSensor, INPUT);"

Code:
const int ledPin = 13;      // led connected to digital pin 13
const int knockSensor = 17; // the piezo is connected to analog pin 0
const int threshold = 100;  // threshold value to decide when the detected sound is a knock or not


// these variables will change:
int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;         // variable used to store the last LED status, to toggle the light

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(knockSensor, INPUT);// declare the ledPin as as OUTPUT
  Serial.begin(9600);       // use the serial port
}

void loop() {
  
  sensorReading = analogRead(knockSensor);
  Serial.println(sensorReading);

  if (sensorReading >= threshold) {
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    Serial.println("Knock!");
  }
  delay(100);  // delay to avoid overloading the serial port buffer
}

This time analogRead does not return to 0- it stays at 893 but it's a slightly different number each time.

--serial window
1
1
2
3
2
1
7
1
1
1
888
Knock!
893
Knock!
893
Knock!
893
Knock!
893
Knock!
893
Knock!
893
Knock!
--end serial window

This is not a real world example. I'll make a simple circuit and some code that better illustrates what I'm trying to do and post it here soon. This INPUT_DISABLE business Paul mentioned might be just what I'm looking for.
 
Hi,
as mentioned you don't need to use <<pinMode(knockSensor, INPUT)>> if you use just analogread().

pinMode(knockSensor, INPUT_DISABLE) is the right way to put pin back to high state before using it for an other purpose.

Maybe you can also change <<const int knockSensor = 17; // the piezo is connected to analog pin 0>>
into <<const int knockSensor = A3; // the piezo is connected to analog pin A3 on teensy 3.2>>
 
Thanks for everyone's help! Here's some test code I came up with using (or trying to use since I don't really understand it) INPUT_DISABLE instead of INPUT. In the end, I may not use this method but I thought I'd put it here for others.

Code:
// testing switching pinMode when using a contact microphone
// if I indicate pinMode INPUT the values from analogRead stay high.
// actually if I only tap the mic slightly things are okay but if I 
// give it a good tap it stays around 893 or something high

int incoming = 0;   // for incoming serial data
int previousIncoming;
int reading;
int ledPin = 13;
int knockSensor = A1;
int n0;
int var = 0;

void setup() {
        pinMode(ledPin, OUTPUT);
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {
// This code uses serial input from the serial window
// 1 switched pinMode to INPUT_PULLUP
// 2 switches pinMode to INPUT
        if (Serial.available() > 0) {
                reading = Serial.read();
                if (reading > 20){
                  incoming = reading;
                } 
        }

// default position -- no pinMode specified
if (incoming == 0){
  digitalWrite(ledPin, LOW);

  n0 = analogRead(knockSensor);
  Serial.println(n0);
}        

// Serial input 1 -- pinMode INPUT_DISABLE
if (incoming == 49){
  if (incoming != previousIncoming){
    digitalWrite(ledPin, LOW);
//    pinMode(knockSensor, INPUT); // this didn't work
    pinMode(knockSensor, INPUT_DISABLE); // this works!
    previousIncoming = incoming;
    var = 0;
  }
  var++;
  if (var > 1){ // filter out the first reading when the pinMode is changed because I was still getting a high number
     n0 = analogRead(knockSensor);    
  }
}

// Serial input 2 -- pinMode INPUT_PULLUP as though I want to use this pin with a button instead of a contact mic now
if (incoming == 50){
    if (incoming != previousIncoming){
    digitalWrite(ledPin, HIGH);
    previousIncoming = incoming;
    }
  pinMode(knockSensor, INPUT_PULLUP);
  n0 = digitalRead(knockSensor);
}

Serial.println(n0);
delay(100); 
  
}
 
Status
Not open for further replies.
Back
Top