Apple Remote mit Arduino - universeller IR Empfang

vor 3 years 5 days

Okay, das ist also mein erstes richtiges Projekt. Ich hatte mir bei Seeedstudio das Dangershield als Bausatz bestellt, hatte aber in der Zwischenzeit meinen Lötkolben zerschossen. Glücklicherweise enthielt meine Bestellung auch die Breadboard freundlicheren IR Receiver Module, so dass ich erstmal was zum spielen hatte. Bei meinem ersten Projekt war es mein Ziel, mit einer beliebigen IR Fernbedienung eine LED ein- und auszuschalten. Das ganze sollte mit der Apple Remote durchgeführt werden, einfach weil ich sie noch hier rumliegen habe. Mein Verfahren ist aber austauschbar und sollte mir jeder Fernbedienung funktionieren. Das Hardware Setup ist recht simpel. In der Illustration (mit Fritzing erstellt). Zeigt der Sensor nach oben. Lediglich ein Widerstand wird als zusätzliche Komponente benötigt. Apple Remote Fritzing Setup

1. Aufzeichnung der IR Signale

Wer ein Oszilloskop sein eigen nennt ist hier klar im Vorteil, aber wir können uns auch einen ausreichenden Ersatz selber bauen. Alles was wir brauchen ist eine Routine, die jeden Wechsel von HIGH und LOW mit der Zeit des Ereignisses protokolliert. Infrarotsignale von Fernbedienungen sind nichts anderes als diese Wechsel nach einer festgelegten Sequenz. Aber dazu später mehr. Zum Glück hat schon jemand einen Sketch geschreiben, der genau dieses macht. Nach der Aufzeichnung des IR-Signals werden diese Daten über die serielle Schnittstelle gesendet. Im Arduino Playground hab ich den Code für den IR Analyzer gefunden:

 
/*  
*  File....... IRanalyzer.pde   
*  Purpose.... Records up to 128 signal changes  
*  Author..... Walter Anderson   
*  E-mail..... <a href="mailto:wandrson@walteranderson.us">wandrson@walteranderson.us</a>   
*  Started.... 18 May 2007   
*  Updated.... 18 May 2007   
*   
*  
*/  
#include
#include
#define TIMER_RESET  TCNT1 = 0
#define SAMPLE_SIZE  64
int IRpin = 2;
unsigned int TimerValue[SAMPLE_SIZE];
char direction[SAMPLE_SIZE];
byte change_count;
long time;
void setup() {   
    Serial.begin(115200);
    Serial.println("Analyze IR Remote");
    TCCR1A = 0x00;
          // COM1A1=0, COM1A0=0 =&gt; Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 =&gt; PWM Operation disabled   // ICNC1=0 =&gt; Capture Noise Canceler disabled -- ICES1=0 =&gt; Input Capture Edge Select (not used) -- CTC1=0 =&gt; Clear Timer/Counter 1 on Compare/Match   // CS12=0 CS11=1 CS10=1 =&gt; Set prescaler to clock/64   TCCR1B = 0x03;
          // 16MHz clock with prescaler means TCNT1 increments every 4uS
   // ICIE1=0 =&gt; Timer/Counter 1, Input Capture Interrupt Enable -- OCIE1A=0 =&gt; Output Compare A Match Interrupt Enable -- OCIE1B=0 =&gt; Output Compare B Match Interrupt Enable   // TOIE1=0 =&gt; Timer 1 Overflow Interrupt Enable   TIMSK1 = 0x00;
             pinMode(IRpin, INPUT);
 }  void loop() {   Serial.println("Waiting...");
   change_count = ;
   while(digitalRead(IRpin) == HIGH) {}                                    TIMER_RESET;   
TimerValue[change_count] = TCNT1;
   direction[change_count++] = '0';
   while (change_count &lt; SAMPLE_SIZE) {
     if (direction[change_count-1] == '0') {
       while(digitalRead(IRpin) == LOW) {}
       TimerValue[change_count] = TCNT1;
       direction[change_count++] = '1';
     } else {       while(digitalRead(IRpin) == HIGH) {}       TimerValue[change_count] = TCNT1;
       direction[change_count++] = '0';
     }   }   Serial.println("Bit stream detected!");
   change_count = ;
   time = (long) TimerValue[change_count] * 4;
   Serial.print(time);
   Serial.print("\t");
   Serial.println(direction[change_count++]);
   while (change_count &lt; SAMPLE_SIZE) {
     time = (long) TimerValue[change_count] * 4;
     Serial.print(time);
     Serial.print("\t");
     Serial.println(direction[change_count-1]);
     Serial.print(time);
     Serial.print("\t");
     Serial.println(direction[change_count++]);
       }   Serial.println("Bit stream end!");
   delay(2000);
 } 

Nach dem Upload des Sketches auf den Arduino und der Aktivierung der Überwachung der seriellen Kommunikation erhält man im Falle der Apple Remote die folgende Daten. Dies sind nur die Daten für den 'Menü' Button, die vollständigen Daten sind am Ende dieses Postings als Anhang beigefügt.

 	
 9140	
 9140	1
 13592	1
 13592	
 14260	
 14260	1
 14764	1
 14764	
 15428	
 15428	1
 17048	1
 17048	
 17712	
 17712	1
 19340	1
 19340	
 20000	
 20000	1
 21628	1
 21628	
 22292	
 22292	1
 22796	1
 22796	
 23460	
 23460	1
 25084	1
 25084	
 25748	
 25748	1
 27372	1
 27372	
 28036	
 28036	1
 29660	1
 29660	
 30324	
 30324	1
 31948	1
 31948	
 32612	
 32612	1
 34236	1
 34236	
 34900	
 34900	1
 36524	1
 36524	
 37188	
 37188	1
 37688	1
 37688	
 38356	
 38356	1
 38892	1
 38892	
 39524	
 39524	1
 40024	1
 40024	
 40688	
 40688	1
 41192	1
 41192	
 41856	
 41856	1
 43484	1
 43484	
 44152	
 44152	1
 44656	1
 44656	
 45320	
 45320	1
 46940	1
 46940	
 47608	
 47608	1
 48108	1
 48108	
 48772	
 48772	1
 49272	1
 49272	
 49940	
 49940	1
 50444	1
 50444	
 51104	
 51104	1
 51608	1
 51608	
 52272	
 52272	1
 52776	1
 52776	
 53440	
 53440	1
 53944	1
 53944	
 54604	
 54604	1
 56228	1
 56228	
 56892	
 56892	1
 58516	1
 58516	
 59180	
 59180	1
 60808	1
 60808	
 61468	
 61468	1
 61976	1
 61976	
 62644	
 62644	1
 63140	1
 63140	
 63804	
 63804	1
 64308	1
 64308	
 64968	
 64968	1 

Schaut man sich die Daten genauer an, so sieht man in der linken Spalte einen fortlaufenden Zeitindex. Zu einem Zeitpunkt gibt es jeweil zwei Zustände in der rechten Spalte (1=HIGH oder 0=LOW). Dies mag erst merkwürdig erscheinen, bedeutet aber nur, dass dies genau die Zeitpunkte des Wechsels der Zustände sind. Ohne sich von der Zahlenflut erschlagen zu lassen kann man diese einach in einen Funktionsplotter füttern und bekommt ein viel deutlicheres Bild.

2. Analyse der IR Signale

Als MAC User verwende ich die wunderbare Freeware Software Plot. Gnuplot ist eine andere, plattformübergreifende Software zum Visualieren der Daten. Die Datensätze kann ich bei Plot einfach als ASCII Datei importieren und erhalte folgende Diagramme. Zur Visualisierung wurden nur die Flächen unter dem Graphen in grau ausgefüllt. Plot IR Signatur 'Menü' Taste
Plot IR Signatur 'Menü' Taste

  Plot IR Signatur 'Play' Taste
Plot IR Signatur 'Play' Taste

  Plot IR Signatur 'Forward' Taste
Plot IR Signatur 'Forward' Taste

  Plot IR Signatur 'Rewind' Taste
Plot IR Signatur 'Rewind' Taste

  Plot IR Signatur 'Plus' Taste
Plot IR Signatur 'Plus' Taste

Plot IR Signatur 'Minus' Taste
Plot IR Signatur 'Plus' Taste

Die Visualisierung der Daten hat mich als allererstes an Barcodes erinnert. Ich denke der Umgang mit IR Signalen aus der Fernbedienung und Daten aus Barcodelesern ist fast identisch. So identisch, dass man wahrscheinlich die selben Sketche verwenden kann. Dem geübten Auge fallen eventuell schon in allen Fällen übereinstimmende Muster auf. Dies kann man noch deutlicher Machen, wenn man die Graphen übereinander legt. Animated GIFs haben mich jahrelang genervt, jetzt endlich hab ich mal einen Nutzen dafür.

3. Interpretation der IR Signale

Apple IR Remote Sequence

In der Überlagerung der einzelnen Signale sieht man deutlich, dass sie sich nur in einem sehr geringen Abschnitt unterscheiden. Zur Weiterverarbeitung muss das IR Signals in Binäre Daten umgerechnet werden. Die Signale kann man deutlich in lange und kurze HIGH Pegel unterscheiden. Die kurzen stellen dabei eine 0 und die langen eine 1 dar. Am Anfang jeder Sequenz sieht man einen HIGH-Zustand der deutlich länger ist als alle folgenden Signale. Dieser dient zur Initialisierung der dadrauf folgenden Sendesequenz. Wandelt man die einzelnen Tasten Signale in Binärcode um so erhält man diese Ergebnisse:

 

Button Code
Menü 0111011111100001 0100 0000111000
Play 0111011111100001 0010 0000111000
Forward 0111011111100001 1110 0000111000
Rewind 0111011111100001 0001 0000111000
Plus 0111011111100001 1101 0000111000
Minus 0111011111100001 1011 0000111000

Wie man nochmal sieht unterscheiden sich die Signale nur in einer 4 Bit breiten Sequenz.

4. Verarbeitung der IR Signale

Bei der Auswertung der Signal ist mir aufgefallen, dass die Ergebnisse zum Teil recht störanfällig sind. Ich denke es liegt an dem Verzicht auf den Kondensator, der bei den Herstellern der Sensoren immer in den vorgeschlagenen Schaltkreisen vorkommt. Diese Filtern Störungen aus der Stromversorgung heraus. Ich muss den Schaltkreis anpassen, weil ich mit den Ergebnissen nicht zufrieden bin. Hier auf jeden Fall mein bisheriges Ergebniss. Es funktioniert allerdings mit Störungen, was denke ich genug Proof Of Concept ist. In meinem Code sieht man den Versuch durch die Verwendung einer Schlüsselsequenz für das Triggern der Bitschlüssels die Störungen zu evringern. Ich denke eine komplette Auswertung des Sequenz ist die sauberere und universellere Methode. Ich werde diese auch noch posten wenn ich dazu komme das Setup wieder aufzubauen.

int ir_pin = 2;				//Sensor pin 1 wired through a 220 ohm resistor</p><p>int led_pin = 13;			//"Ready to Recieve" flag, not needed but nice int debug = 1;				//Serial connection must be started to debug int start_bit = 2000;			//Start bit threshold (Microseconds) int bin_1 = 1000;			//Binary 1 threshold (Microseconds) int bin_0 = 400;			//Binary 0 threshold [code](Microseconds)    void setup() {   pinMode(led_pin, OUTPUT);		//This shows when we're ready to receive   pinMode(ir_pin, INPUT);   digitalWrite(led_pin, LOW);	        //not ready yet   Serial.begin(9600); }  void loop() {   int key = getIRKey();		        //Fetch the key   Serial.println(result);              //sends result to serial for debugging }   int getIRKey() {   int data[31];   int keysequence[5];   digitalWrite(led_pin, HIGH);	   //Ok, i'm ready to recieve   while(pulseIn(ir_pin, HIGH) &lt; start_bit) { //Wait for a start bit   }   for(int i=0;i&lt;31;i++) {   data[i] = pulseIn(ir_pin, HIGH);	//Start measuring bits, I only want high pulses   }    digitalWrite(led_pin, LOW);    for(int i=0;i&lt;31;i++) {		  //Parse them     if(data[i] &gt; bin_1) {		  //is it a 1? 	data[i] = 1;     }  else { 	if(data[i] &gt; bin_0) {		  //is it a 0? 	  data[i] = 0; 	} else { 	 data[i] = 2;			  //Flag the data as invalid; I don't know what it is! 	}     }    }    for(int i=0;i&lt;31;i++) {		  //Pre-check data for errors     if(data[i] &gt; 1) { 	return -1;			     //Return -1 on invalid data     }   }           for(int i=0;i&lt;31;i++){                //monitors the bit sequence for the specified key 111100001         if(data[i-9] == 1 &amp;&amp; data[i-8] == 1 &amp;&amp; data[i-7] == 1 &amp;&amp; data[i-6] == 1 &amp;&amp; data[i-5] == 0 &amp;&amp; data[i-4] == 0 &amp;&amp; data[i-3] == 0 &amp;&amp; data[i-2] == 0 &amp;&amp; data[i-1] == 1 ) {              for(int j=0;j&lt;5;j++) {        //if found the key sequence, copy the following 5 bits to to new array keysequence                 keysequence[j] = data[i+j]; //matches the both arrays over each other for copy             }         }     }    int result = 0;   int seed = 1;   for(int i=0;i&lt;5;i++) {		  //Convert bits to integer     if(keysequence[i] == 1) { 	result += seed;     }     seed = seed * 2;   }   return result;			     //Return key number } 

 

AttachmentSize
apple_ir_rewind.txt1.11 KB
apple_ir_forward.txt1.11 KB
apple_ir_minus.txt1.11 KB
apple_ir_plus.txt1.11 KB
apple_ir_play.txt1.11 KB
apple_ir_menu.txt1.11 KB

5 Antworten auf “Apple Remote mit Arduino - universeller IR Empfang”


  1. Philip (not verified) sagt:

    Interessantes Projekt, dazu sehr gut dokumentiert. Kommt gleich mal mit auf meine "was man noch so alles machen könnte"-Liste.

    Tipp: Screenshots wie von Fritzing immer als gif oder png speichern, dann werden sie nicht von der Kompression zerstört.

    Login or register to post comments

  1. Philip (not verified) sagt:

    Für den Kauf in Deutschland ist dann wohl das hier das entsprechende IR-Empfangsmodul bei Reichelt (0,71 Euro).

    Login or register to post comments

  1. Jan sagt:

    Du hast recht mit der kompression. habe zuletzt immer einfach mit skitch screenshots gemacht ohne export in fritzing. muss mal in den settings rumwühlen, da gibts sicherlich auch ne einstellung für.

    Login or register to post comments

  1. Moe (not verified) sagt:

    Handelt es sich bei der Infrarot Fernbedienung um die von Apell im unibody aluminium?
    Ich würde die sehr gerne als Fernbedienung verwenden und laut internet verwendet apell das nec protokoll

    Login or register to post comments

  1. Jan sagt:

    ne, die alte aus plastik, aber der prozess der hier beschreiben wird geht für jede fernbedienung auf der welt, apple oder nicht apple.

    Login or register to post comments