Aux Signal lesen

Hey ich wollte mir nen kleinen Controller basteln der automatisch auf die aktive Audioquelle umschaltet. Jetzt habe ich nur das Problem, zu prüfen ob es ein Audiosignal gibt. Hat einer von euch vielleicht eine simple Lösung?

Mit dem ADC (analogRead) messen?

Braucht nur einen Kondensator und Spannungsteiler um das Wechselspannungssignal anzuheben, da man nur von 0-5V messen kann:
http://fftarduino.blogspot.de/2011/02/color-organ-spectrum-analyzer-on.html (das Bild unten rechts)
Hier ist es im Prinzip genauso, aber du brauchst den Offset nicht einstellbar (zweites Bild, linke Seite):
http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/

Wenn du dann z.B. 10 Messungen alle paar ms machst und schaust dass alle unter einem bestimmten Wert sind sollte das gehen. Oder grob sowas in der Art. Da muss man rumspielen was zuverlässig läuft.
Auf genau 0 solltest du nicht abfragen, da der ADC eine Auflösung von knapp unter 5mV hat und das daher wahrscheinlich nicht Null ist. Aber da kannst du erst mal messen was bei "kein Signal" genau anliegt indem du das auf Serial ausgibst.

Das würde auch mit einem ATtiny85 o.ä. gehen :slight_smile: Ein Atmega328 nur dafür ist vielleicht etwas Overkill.

Perfekt DANKE! Ich werde das sofort ausprobieren :smiley:

Ok funktioniert alles so weit :wink: Jetzt habe ich nur das Problem das die ausgelesenen Werte stark variieren.... Das heißt wenn ich am Anfang die Messung starte hab ich durchschnittlich den wert 0. Wenn ich die Musik starte habe ich einen wert von ca.300-500. soweit so gut. Wenn ich die Musik jetzt aber wieder stoppe, bleibt der ausgelesene wert bei ca.300. Wenn ich den Arduino resete habe ich wieder 0 :fearful:

Ok, das hört sich insgesamt realistisch an. Du hast hier praktisch einen DC-Anteil auf eine Wechselspannung addiert und Audio hat eine sehr niedrige Spannung. Allgemein ist das so wie dem Dreicksignal in der Mitte:
http://www2.ife.ee.ethz.ch/~rolfz/digiprakt/geraete/amplitude_offset_symmetrie.gif

Durch den Spannungsteiler wird es nach oben gehoben. Wenn sich dann die Amplitude des Signals erhöht werden die gemessenen Minimal- und Maximalwerte höher.

Wegen dem Problem: bleibt da vielleicht der Sample and Hold Kondensator des ADCs aufgeladen bleibt wenn man einfach so das Signal wegnimmt?

Du könntest vielleicht einen der anderen analog-Eingänge auf Masse legen (vorher es da wahrscheinlich gut den generell auf INPUT zu schalten) und dann nach der Messung einmal diesen Messen.

Einfacher geht es rein laut Datenblatt wenn man die unteren 4 Bits (MUX0 bis MUX3) im ADMUX Register auf 1 setzt. Dadurch wird der ADC Eingang intern auf Masse gelegt. Siehe Atmega328 Datenblatt, Table 23-4 auf Seite 263.
Wenn man dann wieder analogRead() machte, sollte die Funktion das wieder überschreiben, da die ja den entsprechenden Kanal wählen muss.
EDIT: dann müsste da aber glaube ich auch erst mal eine Messung starten. Nur den Kanal auszuwählen reicht wahrscheinlich doch nicht. Das ist zwar auch kein Problem, aber du sparst die da nur den anderen Pin zu belegen, falls das geht.

Ist aber geraten ob das hilft.

Ok aber wie mache ich das mit den unteren 4 Bytes?
Irgendwie so?

ADMUX = _BV(MUX0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);

Hier mein Code falls das hilft :blush:

int state[10];
int statepos=0;
int val;
boolean an =false;
int relaipin=7;

void setup()
{
  Serial.begin(9600);  
  pinMode(relaipin, OUTPUT);
}

void loop()
{
  if(statepos<10)
  {
    state[statepos]=analogRead(0);
    statepos=statepos+1; 
  } 
  else
  {
    statepos=0;
    val=state[0]+state[1]+state[2]+state[3]+state[4]+state[5]+state[6]+state[7]+state[8]+state[9];
    if(val>10)
    {
      if(an==false)
      {
        Serial.println("AN");
        digitalWrite(relaipin, HIGH);
        an=true;
      }  
    }
    else
    {
      if(an==true)
      {
        Serial.println("AUS");
        digitalWrite(relaipin, LOW);
        an=false;  
      }
    }
    Serial.println(val);
  }
  delay(100);
}

ADMUX |= _BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3);

Das Compound Oder damit die anderen Bits bleiben. Und es sind nur 4 Bits. Nicht 5.

Aber wie gesagt, ist mir noch eingefallen dass das wahrscheinlich nicht reicht. Damit ist der S&H Kondesator glaube ich immer noch auf dem ADC Eingang ohne dass sich was geändert hat. Du müsstest noch das machen:

ADCSRA |= _BV(ADSC);   //Konvertierung starten
delay(1);                             //warten

Genaugenomen ist die Messung fertig wenn ADSC (ADC Start Conversion) wieder 0 ist, aber so genau muss das hier nicht sein. Deshalb reicht es da eine Millisekunde zu warten.

Oder mach erst mal als Test eine Messung mit analogRead() auf einem anderen Kanal der auf Masse liegt. Das ist das gleiche. Wenn das geht (wobei ich mir gar nicht sicher bin!), dann kann man immer noch versuchen das noch optimieren, wenn es dich stört dass der Pin belegt ist. :slight_smile:

Ok das funktioniert beides irgendwie nicht so gut :smiley: Allerdings habe ich gerade festgestellt das wenn ich in dem Skatch nur analogRead habe und alles andere nicht, dass es dann ziemlich gut funktioniert also wenn ich Musik anmache schlägt er aus und wenn ich sie ausmache fädelt er sich ziemlich schnell wieder konstant bei 0 ein :astonished: Wenn ich aber in dem anderen Skatch(oben gepostet) analogRead mache geht das nicht :fearful: Das ergibt für mich überhaupt keinen Sinn

Sollte nicht ohne anliegendes Audiosignal eine Analogwert um 512 ausgegeben werden? Ich verstehe nicht, warum der bei dir bei 0 liegt. Kannst du mal ein Foto von deinem Aufbau machen?

Ist schon auf einer Europlatiene XD Willst du das wirklich sehen?

sth77:
Sollte nicht ohne anliegendes Audiosignal eine Analogwert um 512 ausgegeben werden?

Jetzt wo des sagst ja. Man sollte eigentlich die Offset Spannung messen. Oops. Ganz vergessen. :confused:

Dann würde der Sketch nicht gehen, da der Vergleichswert falsch ist. Aber der Sketch passt zu dem was er mit einer permanenten Messung hat...

Ich bin so ein Idiot .... ich hatte einen Lötpunkt vergessen :sweat_smile:

jetzt kommt sowas rauß bei anliegender Musik

408
388
492
487
370
357
629
614
536
499
482
567
553
486
570
445
645
492
375
614
439
646
425
439
556
508
361
415
653
450
448
621
411
482
594
402
469
398

Und ohne Musik immer um 511/512 ...

Und was hast du wenn die aus ist? Da hatte ich einen Fehler gemacht. Sorry. Die ist nicht Null, sondern dadurch dass du den Spannungsteiler auf die Hälfte der Betriebsspannung hast, sollten da ca. 2.5V anliegen oder 1023 / 2 = 512

An USB sind es weniger als 2.5V, aber dadurch dass damit auch die Referenzspannung sinkt sollte der Wert gleich sein.

EDIT: Ah sehe es jetzt unten :slight_smile:

Dann scheint es zu passen.

Das mit dem Lötpunkt hätte mir vorher auch auffallen können :~
Ja jetzt habe ich ohne Musik immer so 511/512

Jetzt muss ich nur den Code anders machen. Jetzt kann ich ja nicht einfach gucken ob der durchschnittswert höher ist weil die Werte ja durch die Dreieckskurve (<--- XD) ja auch tiefer als 512 sein können.

Genau für solche Zwecke bietet sich ein Foto ja an. Sowas in der Richtung habe ich nämlich erwrtet, dass da eine Verbindung fehlen wird. Und jetzt mal fleißig weiterbasteln!

Ein Dreieck ist es nicht real. Das hatte ich nur schnell als Illustration gefunden :slight_smile:

Du könntest es so machen, dass du x mal misst und wenn alle x letzten Messungen innerhalb eines Bereichs von 512 - y und 512 + y sind, dann betrachtest du das als AUS.

z.B. nach dem alle Messungen gelaufen sind:

const int fenster = 5;
boolean alleImBereich = true;


for(int i < 0; i < 10; i++)
{
     if(status[i] < 512 - fenster || status[i] > 512 + fenster)
     {
          alleImBereich = false;
          break;
     }
}

Da biegt die zwar schon ein Ausreißer die Variable auf false, aber das kann man auch noch verbessern, z.B. das zwei Werte außerhalb liegen müssen.

Gibt aber sicherlich einige Optionen hier :slight_smile:

Was vielleicht auch noch problematisch ist, wenn da mal längere Pausen in dem Audiosignal sind. Da ist dann sogar gut wenn man länger misst.

Jo genau so versuche ich das grade :wink:

Ok jetzt funktioniert alles soweit, außer das analogRead nach dem beenden nicht immer zurück auf ca.512 geht sondern manchmal auch bei z.B. 470 "hängen bleibt".

int state[10];
int statepos=0;
int var=0;
int an=false;
int relaipin=7;

void setup()
{
  Serial.begin(9600);  
  pinMode(relaipin, OUTPUT);
}

void loop()
{
  if(statepos<10)
  {
    state[statepos]=analogRead(0);
    statepos=statepos+1;
  }  
  else
  {
    statepos=0;
    for (int i=0; i < 9; i++)
    {  
      if(state[i]>514 || state[i]<509)
      {
        state[i]=1;
      } 
      else
      {
        state[i]=0;  
      }   
    }
    for (int i=0; i < 9; i++)
    {
      var=var+(state[i]*10); 
    }
    var=var/10;
    if(var>1)
    {
      if(an==false)  
      {
        Serial.println("AN");
        digitalWrite(relaipin, HIGH);
        an=true;  
      }
    }
    else
    {
      if(an==true)
      {
        Serial.println("Aus");
        digitalWrite(relaipin, LOW);
        an=false;
      }  
    }
  }
  Serial.println(analogRead(0));
  delay(10);
}