I Can't Figure This Out... It Seems Sooooo Simple!! Code Included

Hi All,

I am new to the Arduino world. I am using a Mega 2560 R3. Below is my code. I know my code is wrong and I have tried so many things to get it to where I want it. I have an Op Amp circuit that is connected to pin A0. All I want to do is to have the LED on pin 13 light up when A0 senses sound. Then if pin A0 continues to sense sound, I DO NOT want pin 53 to turn on yet. If pin A0 does not sense any sound for 5 seconds, I want pin 53 to come on for 1 second and go off.

Right now, when pin A0 senses sound, the LED on pin 13 turns on for 5 seconds then goes off. Then pin 53 turns on for 1 second and goes off. If it senses sound again, the same thing happens.

This seems so simple but since I am new to this, I do not know what all the functions, variables, structures, etc are.

Please help me... Thanks!

const int microphonePin = 0; //the microphone positive terminal will connect to analog pin A0 to be read
const int ledPin = 13; //the code will flash the LED connected to pin 13

int sample; //the variable that will hold the value read from the microphone each time

const int threshold = 800; //the microphone threshold sound level at which the LED will turn on

void setup() {
  pinMode (ledPin, OUTPUT);
  pinMode (53, OUTPUT);
}

void loop() {
  sample = analogRead(microphonePin);
  Serial.println(sample);
  if (sample > threshold)
  {
    digitalWrite (ledPin, HIGH); //if the reading is greater than the threshold value, LED turns on
    delay (5000);
    {
      digitalWrite (ledPin, LOW);
      digitalWrite (53, HIGH);
      delay (1000);
      digitalWrite (53, LOW);
    }
  } else
  {
    digitalWrite(ledPin, LOW);
  }
}

First of all: reformat your code with proper indentation, the IDE can do that for you. This will help everybody understand your code better. Also use code tags </> to present code, you can edit your post accordingly. See the top entries on this forum.

You want to build a finite state machine (automaton). Draw a diagram with all states and all transitions between the states. A transition can occur when a signal changes, or after some time has elapsed. Different states do not only reflect different output pin states, but also can wait for different events to happen. Based on that diagram you can describe much preciser what you want to do, and you can write your code almost yourself.

Also it's very unlikely that you read just the audio peaks. I.e. you have to detect the peak analog values over some time, before comparing that peak to the threshold. Also make sure that the opamp output is always within the allowed range of the analog inputs.

OK, Everything has been reformatted with code tags used. The Op Amp circuit is well within range.

I just do not know what kind of commands to use to get this going. I have written diagrams and have done a ton of research. I think I may be the only one trying to do such a thing in the whole entire world. I'm very frustrated.

Thanks!

Your code spends a lot of time in delays. During those delays you can do nothing useful.

Read Using millis for timing

What sort of "Op amp circuit"? For what you're trying to do you really need an envelope follower/detector not just an amplifier.

Also you are not going to be able to do what you want using delay()s. At the moment you detect a sound and switch ledPin high then your delay(5000) stops the processor from doing anything for 5 seconds. In particular it never reads microphonePin again so it has no idea if the sound is still going or if it stopped 4.9 seconds ago.

You're going to want to use millis() for the timing and a simple state machine where you can remember when sound started and when it stopped. Fortunately there are a lot of good tutorials available. Have a look at Several things at a time and Using millis() for timing to get you started.

Steve

Did you already read a tutorial on state machines? Would you be more familiar with tasks?

What sort of "Op amp circuit"? For what you're trying to do you really need an envelope follower/detector not just an amplifier.

Also you are not going to be able to do what you want using delay()s. At the moment you detect a sound and switch ledPin high then your delay(5000) stops the processor from doing anything for 5 seconds. In particular it never reads microphonePin again so it has no idea if the sound is still going or if it stopped 4.9 seconds ago.

You're going to want to use millis() for the timing and a simple state machine where you can remember when sound started and when it stopped. Fortunately there are a lot of good tutorials available. Have a look at Several things at a time and Using millis() for timing to get you started.

Steve

The OP Amp Circuit is posted here --> http://www.learningaboutelectronics.com/Articles/Sound-detector-circuit.php

It is just the run-of-the-mill Op Amp Circuit. I will look into the follower/detector you suggest. I looked into millis() and I am more confused as ever. Like I said, I do not have a lot of experience in Arduino coding. I feel like a dumbass.

Did you already read a tutorial on state machines? Would you be more familiar with tasks?

I have read/watched a bunch of tutorials and state machines were part of a couple of them and so were tasks. I cannot understand what is going on yet. I do not know enough of the finer details to put everything together. I'm very confused.

I have updated my code (below) and I got closer to what I want. However, I cannot seem to keep my audio sample within any real range. My question right now is how do I make my sample larger than what it is now? I would like the Arduino to take a longer audio sample and then determine if the threshold was met during that time. That will work for me if its possible and that's my only hurdle yet. I know what I need, but do not know how to get there. I have tried to use sizeof() and its not doing anything for me. I am probably using it wrong.

//these define the pin connections
const int microphonePin = 0; //the microphone positive terminal will connect to analog pin A0 to be read
const int ledPin = 13; //the code will flash the LED connected to pin 13


int sample; //the variable that will hold the value read from the microphone each time
const int threshold = 600; //the microphone threshold sound level at which the LED will turn on

void setup() {
  pinMode (ledPin, OUTPUT);//sets digital pin 13 as output
  pinMode (53, OUTPUT);
  Serial.begin(9600); //sets the baud rate at 9600 so we can check the values the microphone is obtaining on the Serial Monitor
}

void loop() {
  sample = analogRead(microphonePin); //the arduino takes continuous readings from the microphone
  Serial.println(sample);
  if (sample > threshold)
  {
    digitalWrite (ledPin, HIGH); //if the reading is greater than the threshold value, LED turns on
    delay (10000);
    digitalWrite (53, LOW);
  }
  else
  {
    digitalWrite (53, HIGH);
    delay (1000);
    digitalWrite (53, LOW);
  }
}

It is just the run-of-the-mill Op Amp Circuit.

No it isn't. That page shows an LM386 which is NOT an opamp. The circuit diagram also requires you to choose a few components. You cannot build that circuit as shown without at least selecting a value for R1. Why keep your circuit a secret?

The circuit does allow adjustment of volume and you could even select a different value for C2 to adjust the gain. What happens when you make those adjustments?

C5 appears to be some attempt at smoothing or averaging the output. What happens if you change this value?

Try just printing the analogRead() values and use the Arduino Serial Plot to see what is going on.

Quote

❝It is just the run-of-the-mill Op Amp Circuit.

No it isn’t. That page shows an LM386 which is NOT an opamp. The circuit diagram also requires you to choose a few components. You cannot build that circuit as shown without at least selecting a value for R1. Why keep your circuit a secret?

You’re right about the Op-Amp issue… I mis-typed/spoke. The value for R1 is 2.2K. I forgot to mention it. That’s what the data sheet states the microphone needs.

The circuit does allow adjustment of volume and you could even select a different value for C2 to adjust the gain. What happens when you make those adjustments?

C5 appears to be some attempt at smoothing or averaging the output. What happens if you change this value?

I haven’t made some of those adjustments yet. Thanks for the insight. I will experiment with that. As far as the volume, I have it dialed in as best I can so when using the serial monitor, the values aren’t changing drastically. They stay pretty steady. But sometimes the serial monitor shows 0 even if audio is playing. As an example, it’ll go from 400 right to 0 sometimes. I am thinking that has something to do with digital audio rather than analog. I have yet to experiment with analog audio.

Try just printing the analogRead() values and use the Arduino Serial Plot to see what is going on.

I have never heard of a serial plotter. I will look into that as well.

Like I said, I am not very good with this yet. But does anybody know how I could broaden my audio sample?? I would like the audio sample to last, at least, 5 seconds.

“Last at least 5 seconds” is not really a useable specification. The Arduino Uno does not have enough memory to record 5 seconds of audio at a useful bitrate. Fortunately you aren’t trying to record and play back sounds.

The envelope detector type circuit can do this in the analog circuit. You would have to adjust resistors and capacitors to get a time-constant that matches your 5-second specification.

But I think you are nearly there. Your hardware is probably working well enough that we can fix it in software.

The basic problem with the code you have shown is the use of delays. You need to work without delays. Find the post at the top of the programming forum “Using millis for timing”. That may not seem like a solution but it is the first step to take on the path.

The next concept you need is a fixed sample period. You could just take readings as fast as possible for 5 seconds and count how many are over the threshold. Maybe 10,000 over-threshold will turn your LED on. But then you will add something more to the code and the whole thing runs a little slower. You no longer get the same number of samples in 5 seconds. So you should slow down to a pace you can control. Maybe one sample every 4 milliseconds.

const unsigned long samplePeriod = 4; //milliseconds, don't sample faster than this

void loop() {
  sample = analogRead(microphonePin);

  /* lots of processing here */

  static unsigned long lastSample;
  while(millis()-lastSample < samplePeriod) {
    //wait. Maybe process incoming Serial data here
  }
  lastSample = millis();
}

Thanks Everyone for trying to help. I still do not get the concept of using millis(). I think I will have to know more about the coding of an Arduino before I go any further using only code with no other IC chips.

What I did was hooked up a binary counter IC with the clock on one of the Arduino outputs. This will give me leeway on all those 0s I have been encountering when the Arduino gets a sound sample. I also have the counter's reset hooked up to the LedPin. It will reset the counter every time a sound is sensed. I never get more than four or five 0s consecutively. I would have to get sixteen 0s before it resets. That never happens unless I want it to. Also, I have the outputs of the counter hooked to a 4 input AND gate. Once all pins on the counter are high, I will get a high out of the output. This works for me.

I have a feeling I am using the same concept as millis(), but I am doing it in a totally different way. I know I should only be using the Arduino and nothing else for this sort of thing, but I was getting frustrated.

This works for me and I can use my delays as well. I added a few more lines of code for this, but nothing really complicated. If anybody is curious, Ill post the schematic and the code.

Millis is like using the clock on the wall. If you want to bake a cake for 1 hour, write down the time when you start. (12:27) Look at the clock thousands of times. When (now)-12:27 is more than 1 hour, take the cake out of the oven. That will be at 1:28.

The magic of unsiged arithmetic lets you subtract a big number from a small number and get a positive result.