making an audio auto switch question

Hello,
First of all i love this site. I started with arduino when my lady bought me an arduino based 3d printer last week.
I have since gotten an UNO board and some other stuff and started learning the ways of the code.

I have designed and built some gauges and monitors for my race car and im having so much fun.

Now i have a new project i want to do. I'm making an input sensing line switcher. Basically switch two line inputs from audio devices to one output. A priority switcher is the correct name.

My test code right now just fires 4 LED's based if the audio is playing or not. 2 if it is and 2 if it is not. Im having issues with stability though. IT works except i get random 0 data in the serial monitor and it changes the led output.

Here is my code so far.

const int ledout1 = 2;
const int ledout12 = 3;
const int ledout2 = 8;
const int ledout22 = 9;
const int line1 = A0;
const int pot2 = A1;

void setup() {
// put your setup code here, to run once:
analogReference(INTERNAL);
pinMode(ledout1, OUTPUT);
pinMode(ledout12, OUTPUT);
pinMode(ledout2, OUTPUT);
pinMode(ledout22, OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int line1 = analogRead(0);
int pot2 = analogRead(1);
analogRead(line1);
analogRead(pot2);
if (line1 < 70 ){ digitalWrite (ledout1, HIGH); digitalWrite(ledout12, HIGH); digitalWrite(ledout2, LOW); digitalWrite(ledout22, LOW);}
else {digitalWrite(ledout1, LOW); digitalWrite(ledout12,LOW); digitalWrite(ledout2, HIGH); digitalWrite(ledout22, HIGH);}

//float voltage = pot1 *(0.3/1023);

Serial.println(line1);
delay(1000);

I am using INTERNAL reference voltage as the line voltage varies from .05-1.1 volt.
Is there a way to have the lights turn on from only 40-60 and the other set turn on at all other values.

Or better yet is there a way to stablize the data stream. I tried a smoothing code but did not work as expected and was still jumpy. I need a 4 or 5 second delay between the data stream on the final product so that the audio doesnt switch during a song break.

Any ideas or suggestions. Thanks

}

int line1 = analogRead(0);
int pot2 = analogRead(1);
 analogRead(line1);
 analogRead(pot2);

WTF? You read a value from pin 0, and then use that value to determine what other analog pin to read from? What were you thinking?

 if (line1 < 70  ){ digitalWrite (ledout1, HIGH); digitalWrite(ledout12, HIGH); digitalWrite(ledout2, LOW); digitalWrite(ledout22, LOW);}
 else {digitalWrite(ledout1, LOW); digitalWrite(ledout12,LOW); digitalWrite(ledout2, HIGH); digitalWrite(ledout22, HIGH);}

DoNOTdothis;onestatementperline;nothingfollowsthe{andnothingonthesamelineasthe}.

melsy:
A priority switcher is the correct name.
...
Any ideas or suggestions.

For a "priority switcher" it should be enough to evaluate one of the signals, not both:

  • default --> not switched
  • if signal at input2 detected --> switch

So in case there is either "no signal" or only "input1 signal", the unit is not switched.
And in case of input2 signal detected, the unit is switched

Would that programming logic be OK?

const int line1 = A0;
...
 if (line1 < 70  ){ digitalWrite (ledout1, HIGH);

Switching is based on the pin number of the input? I don't think so.

The pot2 is in the code from the beginning write. I am using only analog one to change led state. Analog one receiving higher than a 70 value switches the led state. Ill clean the trash out of the code and try again. It works for the most part just random 0's on the serial monitor. Thanks

const int ledout1 = 2;
const int ledout12 = 3;
const int ledout2 = 8;
const int ledout22 = 9;
const int line1 = A0;




void setup() {
  // put your setup code here, to run once:
analogReference(INTERNAL);
pinMode(ledout1, OUTPUT);
pinMode(ledout12, OUTPUT);
pinMode(ledout2, OUTPUT);
pinMode(ledout22, OUTPUT);
pinMode(line1, INPUT);
Serial.begin(9600);
}
void loop() {
  // put your main code here, to run repeatedly:
int line1 = analogRead(0);
 analogRead(line1);

 if (line1 < 70  ){ digitalWrite (ledout1, HIGH); digitalWrite(ledout12, HIGH); digitalWrite(ledout2, LOW); digitalWrite(ledout22, LOW);}
 else {digitalWrite(ledout1, LOW); digitalWrite(ledout12,LOW); digitalWrite(ledout2, HIGH); digitalWrite(ledout22, HIGH);}


 
 //float voltage = pot1 *(0.3/1023);

  Serial.println(line1);
  delay(1000);

this is the new code.

You create nothing like trouble when using the same variable name for different things with a different scope of visibility:

const int line1 = A0;
...
int line1 = analogRead(0);

And you will most likely always get in trouble not naming pin numbers with something like 'pin' as part of the variable name, so that you later on in your code will know whether a variable name is a pin number or perhaps a pin value.

Perhaps use more intuitive names, so that you can distinguish pin numbers from values that you read from a pin:

const int line1pin = A0;
...
int line1value = analogRead(line1pin);
// now 'line1value' has a value can be compared against something
int line1 = analogRead(0);
 analogRead(line1);

You have a local variable and a global variable with the same name. Knock that shit off.

Why are you reading from the pin whose number is stored in line1, when that value came from the potentiometer attached to pin 0? Which pin are you reading from, if the potentiometer is set about 1/4 of the way from one stop to the other? Why are you discarding the value read from that most-likely-nonexistant pin?

I added the int line 1 = analog read only on my last revision. Not sure why i did. I'll change line1 to linepin. But i don't think this will solve my issue. The random 0 will still happen

I made the code look pretty and changed a few things. No idea why you are using internal reference with a pot. I would delete that line.

There's no prize for writing less lines of code. I skipped your post a few times as I couldn't be bothered to scroll across the screen to read it.

const int ledout1 = 2;
const int ledout12 = 3;
const int ledout2 = 8;
const int ledout22 = 9;
const int potPin = A0;


void setup() {

  analogReference(INTERNAL); //1.1v range ?
  //using a pot ? why ?
  pinMode(ledout1, OUTPUT);
  pinMode(ledout12, OUTPUT);
  pinMode(ledout2, OUTPUT);
  pinMode(ledout22, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  int line1 = analogRead(potPin);

  if (line1 < 70  ) {
    digitalWrite (ledout1, HIGH);
    digitalWrite(ledout12, HIGH);
    digitalWrite(ledout2, LOW);
    digitalWrite(ledout22, LOW);
  }
  else {
    digitalWrite(ledout1, LOW);
    digitalWrite(ledout12, LOW);
    digitalWrite(ledout2, HIGH);
    digitalWrite(ledout22, HIGH);
  }

  Serial.println(line1);
  delay(1000);
}

There is no pot. I'm using analog input from audio line it's 0 through 1.5 volt . I'm using 1.1 as reference for scaling. 5 volt scaling had the resolution off. With 1.1 I'm getting 1023 at anything above 1.1 volt. But stable no signal is at 40-60.

You do realize that the instantaneous value of a sound wave is not at all a reliable indication of the average sound level, right?

Yes that's why I'm using a reference line in. The actual line will go through relays. The output will fire the relays and pass the line signal through.

All I need is a way to stop the code from responding to zeros. Or a way to set the first relay to work only between 40 and 70 and the other to work all other numbers
Like

If line1 >= 40 <= 75. Then work relay 1
If line 1 any other figure then work relay 2

melsy:
All I need is a way to stop the code from responding to zeros.

If your code reads zero, then your coupling of the audio signal is wrong.

Typically an audio signal is am ALTERNATING VOLTAGE which is half of the time a positive voltage above GND and half of the time a negative voltage below GND.

So with GND as a reference voltage your audio signal may be in the range -0.7V ... +0.7V.

But your Arduino can only operate in the range 0V ... 5V!

Show your schematics how you are coupling your audio signal to your Arduino analog pin!

When done correctly, you should get half range readings of about 512 when no audio signal is active, and the louder the audio signal, the higher above or below 512 will be the analog reading you get.

jurs:
When done correctly, you should get half range readings of about 512 when no audio signal is active, and the louder the audio signal, the higher above or below 512 will be the analog reading you get.

However, if you take a reading at some arbitrary time, the reading will give you absolutely no indication of average amplitude because you have no idea what phase of the audio wave you have measured. So, multiple sampling and averaging or peak reading is necessary.

I will post the schematic and Current code when i get home from work in a bit. Thanks everyone so far

here is the drawing of the circuit with basic wiring.

melsy:
here is the drawing of the circuit with basic wiring.

The coupling of the audio signal is wrong.
That will limit the signal detection.

Audio is AC voltage, sometimes positive voltage above GND and sometimes negative voltage below GND, level is switching with audio frequency.

When measuring with your circuit, all the negative voltages (below GND) will read as zero.

Anyway, if you want to keep your wrong circuit, you could use this code:

#define SWITCHPIN 13
#define AUDIOPIN A0
#define AUDIOLIMIT 40
#define TIMEOUT 15000

void setup() {
  pinMode(SWITCHPIN,OUTPUT);
}

unsigned long timeAudioDetected;
boolean on=false;
void loop() {
  if (analogRead(AUDIOPIN)>AUDIOLIMIT)
  {
    timeAudioDetected=millis();
    on=true;
  }
  if (on && millis()-timeAudioDetected>TIMEOUT) on=false;
  digitalWrite(SWITCHPIN,on);  
}

The code will work with a "peak voltage detection" and a "timeout".

Set the AUDIOLIMIT as a peak voltage to the expected minimum analogRead() voltage for a valid signal.
Set the TIMEOUT in milliseconds.

If there is a signal above the AUDIOLIMIT, the pin-13 LED will switch ON. And if no signal above AUDIOLIMIT could be detected within TIMEOUT (=15 seconds), the pin-13 LED will switch OFF automatically.

OK this is what i have done so far now.

the schematic is the same except i used resistors on the line in pins to step the voltage up to all positive volts and running it on a 3.3 volt setup.
the new code i wrote works ok but I'm having one small issue that i don't know the correct way to fix.

The problem.

When no audio is detected the analog read number sits between 640 and 670.
When audio is detected the analog read number waves between 850 and 450ish.
I need a way to make the code check the analog read three times if it is in the 640 to 670 range
so if the audio detected wave hits a number in the 640 to 670 range it will be ignored unless it is seen three times.
I tried a delay then a new "if" check but the second if always read the same number as before the delay.

Does anyone know how to do this?

Here is the newest code

const int ledout1 = 2;
const int ledout12 = 3;
const int ledout2 = 8;
const int ledout22 = 9;
const int line1 = A0;




void setup() {

  
  pinMode(ledout1, OUTPUT);
  pinMode(ledout12, OUTPUT);
  pinMode(ledout2, OUTPUT);
  pinMode(ledout22, OUTPUT);

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

  int line1 = analogRead(A0);
 
  Serial.println(line1);
  delay(1000);

  if
  ( line1 >= 635  && line1 <= 675)
  
{ digitalWrite (ledout1, HIGH);
    digitalWrite(ledout12, HIGH);
    digitalWrite(ledout2, LOW);
    digitalWrite(ledout22, LOW);}
 

  else
 
  {digitalWrite(ledout1, LOW);
    digitalWrite(ledout12, LOW);
    digitalWrite(ledout2, HIGH);
    digitalWrite(ledout22, HIGH);}

  
  delay (1000);

}

just read the post above the last one i made. going to try to incorporate that into it as it looks like that is the code change i need.

melsy:
OK this is what i have done so far now.

the schematic is the same except i used resistors on the line in pins to step the voltage up to all positive volts and running it on a 3.3 volt setup.

And now you are feeding back a DC voltage you create in the Arduino circuit back into the output of the audio device? Full circuit drawing for that?

From the description I'm afraid that your Arduino now is feeding your audio device output with voltage, which should not be the case. Perhaps you'd better also use an additionally DC decoupling capacitor.

I'm not an audio expert, but perhaps something like that:

            analog input
                 |
                 |
         _____   |   _____
5V -----|_____|--+--|_____|----- GND
                 |
                 |
                 +----||-------- audio signal

Resistor values perhaps 47K ... 100K
Capacitor value perhaps 1µF ... 100µF
The capacitor will not let through DC from the Arduino circuit to the audio input and block it.

melsy:
the new code i wrote works ok but I'm having one small issue that i don't know the correct way to fix.

The code needs two changes:

1st: As the "zero signal voltage" is not 0 any longer, you will have to find out which voltage is a zero signal in your circuit. The zero signal is the average voltage over time: Take all readings and create a long time average, this is calles low-pass filtering I think.

2nd: The 'peak signal voltage' is then the absolute value of the difference between the current value and average value of the signal.

Please let me know if you need help in code changes to create the average and peak values with your new circuit.