issue with custom class

I am writing a class that filters out some values, for better readings and its having some issues. The original sketch works perfect with one mic, but alas I need several, so I am starting with two and hence need a class.

here is the original:

const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
 
void setup() 
{
   Serial.begin(9600);
   pinMode(12, OUTPUT);
}
 
 
void loop() 
{
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level
 
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
 
   // collect data for 50 mS
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(0);
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   double volts = (peakToPeak * 3.3) / 1024;  // convert to volts
 
   if(volts > 0.16){
    digitalWrite(0, HIGH);
   } 
   else { digitalWrite(0, LOW); }
   Serial.println(volts);
}

and here is the one with classes I am writing now:

main.ino:

#include "mic.h"

const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
const int threshold = 0.07; 
 
Mic micOne;
Mic micTwo;

void setup() 
{
   Serial.begin(9600);
   //pinMode(11, OUTPUT);
   //pinMode(12, OUTPUT);
   micOne.setPin(0);
   micTwo.setPin(1);
}
 
 
void loop() 
{
   micOne.setMicLevel();
   micTwo.setMicLevel();
   Serial.print(micOne.getMicLevel());
   Serial.print(", ");
   Serial.println(micTwo.getMicLevel());
}

mic.h:

#ifndef MIC_H
#define MIC_H

class Mic {
  public:
    Mic();
    int pin;
    void setPin(int);
    void setMicLevel();
    double getMicLevel();
    double currentMicLevel;
    double volts;
  private: 
    unsigned long startMillis;
    unsigned int peakToPeak;   // peak-to-peak level
    unsigned int signalMax;
    unsigned int signalMin;
};

#endif

mic.ino:

#include "mic.h"

Mic::Mic(){
  currentMicLevel = 0;
  volts = 0;
}


void Mic::setPin(int _pin) {
 pin = _pin; 
 Serial.print("pin set to: "); Serial.println(pin);
}

void Mic::setMicLevel() {
   unsigned long startMillis= millis();
   unsigned int peakToPeak = 0;   // peak-to-peak level
 
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   // collect data for 50 mS
   //
   while (millis() - startMillis < sampleWindow)
   {
     //Serial.println("test");
      sample = analogRead(pin);
      //Serial.println(sample);
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   volts = (peakToPeak * 3.3) / 1024;  // convert to volts
}

double Mic::getMicLevel(){
  return volts; 
}

I am getting some really weird output from it that doesn't seem to make sense here is idle reading:

0.15, 0.18
0.14, 0.15
0.19, 0.17
0.15, 0.14
0.11, 0.16
0.15, 0.18
0.17, 0.22
0.17, 0.13
0.20, 0.15
0.14, 0.17
0.14, 0.21
0.19, 0.23

then a reading from when mics are peaking:

3.30, 3.29
3.29, 3.30
3.30, 3.30
3.30, 3.30
3.29, 3.29
3.30, 3.29
3.30, 3.30
3.29, 3.30
3.30, 3.30

Problem is that they seem to both be linked, when one goes up they both do, in example above I am blowing into only one mic.

here is how I have it wired:

hmm, found one global that should have been moved to class, but still no luck:

#include "mic.h"

const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
//const int threshold = 0.07; 
 
Mic micOne;
Mic micTwo;

void setup() 
{
   Serial.begin(9600);
   //pinMode(11, OUTPUT);
   //pinMode(12, OUTPUT);
   micOne.setPin(0);
   micTwo.setPin(1);
}
 
 
void loop() 
{
   micOne.setMicLevel();
   Serial.print(micOne.getMicLevel());
   micTwo.setMicLevel();
   Serial.print(", ");
   Serial.println(micTwo.getMicLevel());
}

mic.h:

#ifndef MIC_H
#define MIC_H

class Mic {
  public:
    Mic();
    int pin;
    unsigned int sample;
    void setPin(int);
    void setMicLevel();
    double getMicLevel();
    double volts;
  private: 

};

#endif
#include "mic.h"

Mic::Mic(){;
  volts = 0;
}


void Mic::setPin(int _pin) {
 pin = _pin; 
 Serial.print("pin set to: "); Serial.println(pin);
}

void Mic::setMicLevel() {
   unsigned long startMillis= millis();
   unsigned int peakToPeak = 0;   // peak-to-peak level
 
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   // collect data for 50 mS
   //
   while (millis() - startMillis < sampleWindow){
     //Serial.println("test");
      sample = analogRead(pin);
      //Serial.println(sample);
      if (sample < 1024) {   // toss out spurious readings 
         if (sample > signalMax) {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin) {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   volts = (peakToPeak * 3.3) / 1024;  // convert to volts
}

double Mic::getMicLevel(){
  return volts; 
}

Delta_G:
I can't see the problem in that code. Maybe it is wiring or hardware? Are the mics as close together in real life as they are in the diagram? Maybe they're both picking up.

I will add a couple of comments about your class though I don't think they're causing this problem they'll save you a couple of pitfalls later with the code.

I would make the variable sample local to the setMicLevel method. It's not used anywhere else and that method will be updating the value and then just leaving you with the last value it read as a member. I don't think that will be very useful so why keep it around.

The other thing I would do is move the global sampleWindow into the class. I guess you made it global so all Mic objects have to share the same value. Have a look at the static keyword. You can put it in the class and make it static and all objects will share the same value. You can even have static methods to get and set the value. It doesn't really affect the performance of this sketch so much, but it's always good to encapsulate things together if they go together. Otherwise every time you use this class you'll have to remember that you need to declare that variable.

Also, it's not clear whether this is the case or not, but all the code in the last window of the prior post should be in a .cpp file in the folder with the .h file. From the first post it looks like it might be in a .ino. Maybe I'm reading it wrong, but just in case.

mics are definitely not close enough to pick up each other with that kind of sensitivity, so its not that. I can unplug one and blow into it and it turns both up, then plug it back in and unplug other one (separate pins) and do same and both numbers go up. So it seems to be something in the code.

that last file is a .ino file, so yeah I think pretty much the same.

I am currently changing those suggestions around too, thanks for advice.

tried to implement those changes, no luck.

main.ino

#include "mic.h"

 
Mic micOne;
Mic micTwo;

void setup() 
{
   Serial.begin(9600);
   micOne.setPin(0);
   micTwo.setPin(1);
}
 
 
void loop() 
{
   micOne.setMicLevel();
   Serial.print(micOne.getMicLevel());
   micTwo.setMicLevel();
   Serial.print(", ");
   Serial.println(micTwo.getMicLevel());
}

mic.h

#ifndef MIC_H
#define MIC_H

class Mic {
  public:
    Mic();
    int pin;
    void setPin(int);
    void setMicLevel();
    double getMicLevel();
    double volts;
    static const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
  private: 

};

#endif

mic.ino

#include "mic.h"

Mic::Mic(){
  volts = 0;
}


void Mic::setPin(int _pin) {
 pin = _pin; 
 Serial.print("pin set to: "); Serial.println(pin);
}

void Mic::setMicLevel() {
   unsigned long startMillis= millis();
   unsigned int peakToPeak = 0;   // peak-to-peak level
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   while (millis() - startMillis < sampleWindow){
      unsigned int sample = analogRead(pin);
      if (sample < 1024) {   // toss out spurious readings 
         if (sample > signalMax) {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin) {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   volts = (peakToPeak * 3.3) / 1024;  // convert to volts
}

double Mic::getMicLevel(){
  return volts; 
}
   micOne.setPin(0);
   micTwo.setPin(1);

Bit of a shot in the dark but shouldn't that be A0 and A1? I always thought 0 and 1 were digital pins and A0 and A1 the first two analog pins for which 13 and 14 would also work. Which is what your wiring diagram shows.

I'm not sure why it would seem to work though.

Well, a little rudimentary testing shows that I was wrong about that. I guess analogRead() is smart enough to only use analog pins.

mic.ino

Why isn't this (properly) mic.cpp?

What does setMicLevel() do? Why does that need to be called every pass trough loop?

      unsigned int sample = analogRead(pin);
      if (sample < 1024) {   // toss out spurious readings

Please describe the circumstances under which this statement would NOT be true.

After looking at setMicLevel(), that is a crappy name for the function. There is no reason at all to have one function compute a value for a member variable and then have another function get the value of that member variable. setMicLevel() should return the value that it computes, and getMicLevel() should make a resounding thud when it hits the bit bucket.

Of course, then calling the function that gets the value setXXX looks pretty silly.

Delta_G:
He's using analogRead, so he's got the pin numbers right. Although I think A0 and A1 would still work. I think analogRead can handle either way.

I knew those changes wouldn't fix your current problem, it was just some tips for the class as a whole.

You say when you unplug one they still both go up. What is the analog pin connected to when it is not plugged to the mic? Nothing? That would be a floating pin and you'll never explain why you get any particular reading out of a floating pin. I'm no expert on hooking up microphones so I don't know if they need to be pulled to ground or anything like that, but it's starting to sound like hardware. If the crosstalk was in the software, I would expect to see the same numbers for both mics every time. But that isn't the case. Maybe the crosstalk is on the wires.

when I was unplugging I just unplugged A0 and A1 one by one, left ground in then plugged them back in, so A0 was in and A1 was out then A0 was out and A1 was in-- just to see if both mics were working. They both seem to pick up sound on separate pins, but the values are crossing somewhere.

hmm. well odd thing happened. Finally got chance to go through this again, and on a whim used a different arduino with exact same code, It fixed the problem. Wiring exactly the same, except it was a Leonard instead of a DUE. works perfect now, no setup change. Very strange.