Gamepad mit verschiedenen Funkmodulen



Das Gamepad dient hauptsächlich zur Steuerung eines Heliumluftschiffs mit einem Qaudrocoptergerüst, soll aber auch in der Lage sein mit seinen verschiedenen Funkmodulen andere Fahrzeuge/Geräte zu steuern. Hierbei werden hauptsächlich die Analog-Sticks des Gamepads zur Steuerung verwendet, jedoch ist die Implementierung weiterer Funktionen/Tasten dank des Einbaus eines ATmega328 kein großes Problem.Über eines der drei zur Verfügung stehenden Funkmodule soll eine  stabile Verbindung zum Luftschiff bzw. seinen Motoren hergestellt werden. Das Gamepad kann zwischen einem Nordic-Modul, einem Xbee und einem Deltang-Funkmodul wechseln und agiert hauptsächlich als Sender. Das Luftschiff hat die entsprechenden Empfängermodule installiert und steuert seine Motoren über das ausgewählte entsprechende Modul.

Prinzipieller Aufbau und Funktion des Gamepads:

Als Vorlage und Entwicklungsbasis dient ein handelsübliches Gamepad für PC oder Konsole, in diesem Fall eines der Marke Speedlink. Vorteilhaft sind hierbei nicht nur die Kosten, sondern auch die Möglichkeit, neben zwei Thumbsticks bis zu 16 Funktionen (ohne Tastenkombinationen) zu implementieren. Der oben erwähnte Microcontroller liest die Eingaben am Joystick und an einer Tastenmatrix aus und gibt diese an die verschiedenen Funkmodule weiter. Da die Platine des Speedlink-Gamepads weder die gewünschten Funkmodule besitzt, noch umprogrammierbar sind ist es notwendig, eine neue Platine zu entwerfen, welche die gewünschten Funktionen besitzt.

Funktionsweise der Tastenmatrix:

Das innere des Speedlink-Gamepad bestand insgesamt aus zwei Platinen. Obwohl die Hauptplatine, welche den eingebauten Mikrocontroller und ein Funkmodul beherbergt neu entwickelt werden musste, konnte die zweite Platine, welche mit den Gamepadtasten verbunden ist, für eine 4x4-Tastenmatrix wiederverwendet werden. Dies reduziert den Platz im Gamepadgehäuse und ist relativ einfach zu implementieren, großer Nachteil bei der Verwendung der Tastenplatine ist die fehlende Mögllichkeit Tastenkombnationen mit mehr als zwei Tasten einzubinden. Allgemein beruht eine Tastenmatrix auf folgendem Prinzip: Wichtig ist,dass vier Spalten an ausgabefähige Pins des Mikrocontrollers angeschlossen werden (Ausgabeport), vier Zeilenpins dienen zum Auslesen der Signale (Eingabeport). Vor jeder Zeile werden Widerstände benötigt, diese sind im ATmega328 schon integriert. Da die integrierten Widerstände jedoch Pull-Up Widerstände sind, wird bei der Tastenmatrix mit low-aktiven Signalen gearbeitet. Eine Spalte nach der anderen wird nun auf low geschaltet, die restlichen Spalten werden auf High gestellt, um Kurzschlüsse zu vermeiden. Wird eine Spalte umgestellt, werden die einzelnen Zeilen abgefragt. Drückt man nun eine Taste, bei welcher die Spalte Low ist, wird die mit der Taste verbundenen Zeile auf Low gezogen, was der Mikrocontroller ausliest. Ist nun die Spalte und Zeile bekannt, an welchen ein Low-Signal anlegt so kann die gedrückte Taste bestimmt werden. mithilfe der Tastenplatine sind Tastenfunktionen mit bis zu zwei Tasten möglich. Tastenkombinationen mit mehr als zwei Tasten können mithilfe von Entkopplungsdioden umgesetzt werden, erfordern allerdings den Neuentwurf einer Tastenplatine, was eventuell Schwierigkeiten beim Wiedereinbau erzeugen kann. 

 

Bei der Programmierung der Tasten bzw. Funktionen kann die Tastenentprellung ein Problem werden. Dieses kann zwar mithilfe einer zusätzlichen Schaltung gelöst werden, es reicht aber in diesem Falle, bei Verwendung von 16 Tasten, aus, die Entprellung mithilfe von Software umzusetzten. Hierbei nutzt man einfache Flankenerkennung, d.h. der Mikrocontroller gibt für die erste „steigende“ Flanke den Wert 1 zurück. Danach werden die Zeitabstände zu den nächsten Flanken abgefragt. Sind diese Zeitwerte kleiner als eine vorgegebene Zeit, so werden diese nicht registriert. 

Pinbelegungen am ATmega32:

Für die 4x4 Tastenmatrix sind insgesamt 8 Pins notwendig. Für die Thumbsticks werden vier analogfähige Pins benötigt (Roll, Pitch, Jaw, Throttle). Die Nordic-Module bilden eine SPI- Schnittstelle, sechs Pins(SCK, CE, CSN, MISO, MOSI, IRQ) werden mit dem ATmega verbunden. Die Rx/Tx-Pins des Xbeemoduls werden mit den entsprechenden Pins am ATmega verbunden. Xbees bilden eine serielle Schnitstelle.

Bei der Stromversorgung der verschiedenen Bauteile muss darauf geachtet werden, dass nicht immer jedes Bauteil mit der gleichen Spannung versorgt werden kann. Für den Mikrocontroller  wird eine Spannung zwischen 4,2 und 3,7 Volt verwendet, für die Nordic- und Xbeefunkmodule ist eine Versorgungsspannung von 3,3 Volt nötig. Auf die Platine wird deshalb ein Spannungsregler implementiert (Microchip MIC5219).

Verwendete Fukmodule:

Die Hauptaufgabe des Gamepads ist die Übertragung der Auslenkung der Analog-Sticks. Hierbei wird die Auslenkung eines Sticks in eine Richtung auf ein Wert zwischen 0 bis 255 abgebildet. Somit ergeben sich insgesamt 4 Stickwerte (jeweils ein x und y-Wert pro Stick), die übertragen werden müssen. Neben diesen 4 Stickwerten können auch Tastenbetätigungen übertragen werden. 

Deltang Tx1M Sender/Rx Empfänger:

Dieses Funkmodul basiert auf eine DSM2-Verbindung. Vorteil hierbei ist dank einem auf dem Chip eingebauten Microcontroller der geringe Programmieraufwand. Der Sender kann mit wenig Aufwand auf einen vorprogrammierten Modus eingestellt werden. Die Rolle von Sender und Empfänger ist fest vorgelegt, beide müssen vor dem Betrieb aufeinander eingestellt werden (Binding). Der Sender besitzt sieben Input- Pins,wobei nur der Pin7 für die Übertragung notwendig ist. Die restlichen Pins sind zum Einstellen des Senders auf den richtigen Modus. Einstellungen des Empfängers können über den Sender vorgenommen werden. Der Sender überträgt ein PPM - Signal. 

 Nordic NRF24L01-Funkmodule:


Das Nordic-Modul basiert auf eine 2,4GHz Verbindung zur Übertragung von Daten. Die Übertragung ist sehr praktisch, da man mehrere Bytes aufeinmal übertragen kann.
Eine gute Einführung zu Nordics ist auf mikrocontroller.net zu finden. 
http://www.mikrocontroller.net/articles/NRF24L01_Tutorial

Bei der Übertragung mittels Nordic-Module werden jeweils 9 Byte große Pakete verschickt. Hierbei gibt es zwei Modi.
Der erste Modus ist der Normale-Modus indem die Stickwerte verschickt werden, in dem Normalen-Modus werden permanent Pakete mit den zugehörigen Stickwerten verschickt. Dazu werden die Stickwerte codiert, sodass pro Stickwert 2Bytes gebraucht werden. Im gesendeten Paket stehen die Stickwerte somit vom 1. bis 8. Byte. Der 9.Byte hat den Wert Null. Im empfänger werden die Stickwerte anschließend wieder decodiert.
Der zweite Modus ist die Tasten-Modus, dieser Modus tritt nur dann ein wenn eine Taste auf dem Gamepad betätigt wird. In dieser Modus wird der Normale-Modus abgebrochen. Und es wird ein Paket mit dem entsprechenden Tastenwert verschickt. Hierbei enthalten die ersten zwei Bytes den Tastenwert, die 3 und 4 Byte enthalten den ACK-Wert - welcher vom Empfänger zur Bestätigung, dass das Paket erhalten wurde, wieder zurückgesendet wird, die Bytes 5 bis 8 haben den Wert 0, der 9.Byte hat den Wert 1. Nachdem ein Paket verschickt wurde wird der Normale-Modus wieder aktiv. Falls die Bestätigung von dem Empfänger nicht erhalten wird, wird der Tasten-Modus aktiv und nachdem wieder ein Paket verschickt wurde wird der Normale-Modus aktiv. Dies wiederholt sich solange bis die Bestätigung vom Empfänger eintrifft. 

Aufbau des Nordic-NRF24L01-Moduls:

Ein Funkmodul besitzt insgesamt 8 Anschlüsse, diese sind:
Versorgung Pins:
VCC und GND (Normal verträgt der Chip Spannungen zwischen 1,9V und 3,6V)
SPI-Schnittstellen:
Die SPI-Schnittstellen sind zur Kommunikation von Mikrocontrollern mit anderen Apparaten vorgesehen. Hierbei gibt es den Master(in unserem Fall der Mikrocontroller) und den Slave (in unserem fall die Nordic-Module). Dabei findet die Übertragung Bit weise in Bytes über einen sogenannten shift register statt.
Beispiel:
Angenommen im shift register des Masters steht ein Wort(dieser muss wie bereits erwähnt ein Byte breit sein) drin, mit den Bitwerten: A0 A1 A2 A3 A4 A5 A6 A7

Takt Master Register Slave Regsiter
x Bit0 | Bit1 | Bit2 | Bit3 | Bit4 | Bit5 | Bit6 | Bit7 Bit0 | Bit1 | Bit2 | Bit3 | Bit4 | Bit5 | Bit6 | Bit7
0 A0   | A1   | A2   |  A3  | A4   | A5   | A6   | A7 x      |   x    |   x   |   x    |   x    |  x    |   x    |   x
1 x      | A0   | A1   | A2   |  A3  | A4   | A5   | A6 A7   |   x    |   x   |   x    |   x    |  x    |   x    |   x
2 x      |  x     | A0   | A1   | A2   |  A3  | A4   | A5 A6   |  A7  |   x   |   x    |   x    |  x    |   x    |   x
... ... ...
8 x      |   x    |   x   |   x    |   x    |  x    |   x    |   x A0   | A1   | A2   |  A3  | A4   | A5   | A6   | A7

Das oben gezeigte Beispiel läuft über den MOSI(Master Out, Slave In) ab. Umgekehrt, wenn man nun von Slave Register in Master Register schreiben will, würde der Vorgang über den MISO(Master In, Slave Out) ablaufen. In beiden Fällen gibt der SCK-Pin den Takt für beide an.
Die Nordic-Module haben zusätzlich zu den 3 gängigen SPI-Schnittstellen einen Zusätzlichen Pin, nämlich den CSN-Pin. Dieser Pin ist standart mäßig auf high gelegt, falls ein Kommando vom Mikrocontroller übernommen werden soll wird der CSN-Pin auf low gelegt. Jedes Kommando an den Nordic-Modul wird durch ein von high auf low Schalten des CSN-Pins eingeleitet.
Hier zur Übersicht nochmal die einzelnen SPI-Schnittstellen:
MISO(Master In Slave Output): Eingang des Master shift registers und Ausgang des Slave shif registers
MOSI(Master Output Slave In): Ausgang des Master shift registers und Eingang des Slave shift registers
SCK(Serial Clock): Takgeber für Master sowie Slave
Nordic eigene Pins:
CE-Pin: Der CE-Pin definiert, ob der angeschlossene Nordic Modul sich im TX-Modus(Sender) oder im RX-Modus(Empfänger) befindet.
IRQ-Pin: Der IRQ-Pin ist der Interruptpin des Funkmoduls.

 

 Programmierung des Nordic NRF24L01 mit der Mirf.h Bibliothek

Hier ist der Code für einen Sender: (Die Nordic Module können als Empfänger sowie als Sender tätig sein, sie können jedoch nicht gleichzeitig senden und empfangen.)

Zuerst void setup() :

void setup(){

        Mirf.spi=&MirfHardwareSpi;
        Mirf.cePin=9;
        Mirf.csnPin=10;
        Mirf.init();
        Mirf.setTADDR((byte*)"Kanal");
        Mirf.payload=8;
        Mirf.channel=90;
        Mirf.config();

}


Erklärung zum Void:
1:die SPI-Schnittstellen werden Initialisiert
2 & 3: Änderung der ce und csn Anschlusspins auf dem Arduino auf die Pins 9 und 10
4: Initialisierung des NRF24L01
5. Setzt das Modul als Sender für "Kanal"
6.Setzt fest wieviel byte aufeinmal gesendet wird, payload muss sowohl beim Sender als auch beim Empfänger den gleichen wert haben (payload kann werte zwischen 1 und 32 annehmen)
7.Setzt den Channel fest (der Empfänger muss auch den gleichen Channelwert besitzen)
8. Initialisiert die Einstellungen für NRF24L01

Jetzt kommt die loop-Schleife hier werden die Daten gesendet:

void loop(){

    Mirf.send(data);
    while(Mirf.isSending);

}

Erklärung zum loop:
1. Sendet die den Array data, data muss als ein array mit der größe von payload definiert werden also z.b. byte data[payload] in unserem fall data[8]. Data muss ein Array von bytes sein, da die Module nur Arrays von Bytes senden und empfangen können.
2. Setzt die boolsche Variable Mirf.isSending auf 1 während der Modul sendet.

Als nächstes kommt ein Programmcode für einen Empfänger:

Zuerst die void setup:

void setup(){

        Mirf.spi = &MirfHardwareSpi;
        Mirf.csnPin = 10;
        Mirf.cePin = 9;
        Mirf.init();
        Mirf.setRADDR((byte *) "Kanal" );
        Mirf.payload = 8;
        Mirf.channel = 90;
        Mirf.config();

}

1:die SPI-Schnittstellen werden Initialisiert
2 & 3: Änderung der ce und csn Anschlusspins auf dem Arduino auf die Pins 9 und 10
4: Initialisierung des NRF24L01
5. Setzt das Modul als Empfänger für "Kanal"
6.Setzt fest wieviel byte aufeinmal gesendet wird, payload muss sowohl beim Sender als auch beim Empfänger den gleichen wert haben (payload kann werte zwischen 1 und 32 annehmen)
7.Setzt den Channel fest (derSender muss auch den gleichen Channelwert besitzen)
8. Initialisiert die Einstellungen für NRF24L01

void loop(){

    if (!Mirf.isSending()) {
             Mirf.getData(data);
    }

}

1.Falls Mirf.isSending nicht gleich Wahr ist werden die Daten empfangen
2.Mirf.getData(data) schreibt die empfangenen Werte in data rein data ist ein Byte Array und hat die Größe von Payload, in unserem Fall 8 also byte data[8].
Eine gute Übersicht über die Mirf-Library ist hier zu finden:
http://playground.arduino.cc/InterfacingWithHardware/Nrf24L01

CRC(Cyclic redundancy check)

Im Rahmen unserer Aufgabe mussten wir bei der Übertragung mit den Nordic-Modulen auch erkennen können, ob die gesendeten Daten auch richtig übertragen worden sind. Hierfür benutzen wir ein CRC-Feld. CRC bedeutet Cyclic redundancy check (Zyklische Redundanzprüfung). Die Idee der CRC ist, der gesendeten Information zusätzliche Redundanz anzufügen und diese beim Empfänger zu überprüfen, damit kann man Übertragungsfehler detektieren. Zur Verständnis betrachten wir die einzelnen übertragenen Bits als Polynome.
Beispiel(aus dem Buch Kanalcodierung von André Neubauer):
Wir senden die Information mit einem Payload von 1(8 Bit breite Information, also Zahlen zwischen 0 und 255). Unsere Information sei 120, Binär:  0 0 0 1 1 1 1 0 (insgesamt nur 8 Stellen da 8-Bit breit). Jetzt zur besseren Verständnis betrachten wir die Binäre-Zahl als ein Polynom:
0*x0 + 0*x1 + 0*x2 + 1*x3 + 1*x4 + 1*x5 + 1*x6 +0*x7  

Wenn wir jetzt eine Zahl senden wollen, müssen wir sie codieren. Bei der Codierung wird eine Redundanz, die durch ein Generatorpolynom von der Information erhalten wird, am Anfang der Information hinzugehängt. Damit wir aber keine Informaiton verlieren muss die Anzahl der übertragenen Bits größer sein als die Anzahl der Informationsbits, somit erhalten wir eine Informationswortbreite k, eine Redundanzbreite m und die Gesamtlänge n=k+m. Um die Redundanz zu erhalten teilen wir den Informationswert durch den Generatorpolynom mit Rest. Den erhaltenen Rest fügen wir als least significant bits zur Information hinzu und überprüfen beim Empfänger, ob die Übertragung fehlerfrei abgelaufen ist, indem wir einfach das Empfangene Wort durch den Generator mit Rest teilen und überprüfen ob der Rest gleich Null ist. (Falls ungleich 0 dann ist ein Fehler aufgetreten).
Beispiel zur Codewortgeneration:
Es sei:
Informationsbreite k=4, Codewortlänge n=7, Redundanzlänge m=3
Generatorpolynom: g(x)=1+x1+x3
Informationspolynom: i(x)= 1+x3

Schrittweise Entwicklung des Codewortes:
1. Schritt: xn-k= x7-4= x3 und i(x)*x3= x3 +x6 , dieser Schritt entspricht Binär der Verschiebung des Zahls um 3 stellen nach rechts. Also im ersten Schritt verschieben wir den Informationswert, um m Stellen binär nach rechts.

2. Schritt: Um die Redundanz zuerhalten teilen wir nun das erhaltene Polynom x6+ x3 binär durch den Generatorpolynom mit Rest. Hierbei müssen wir drauf achten, dass die Codierung im Galois-Raum statt findet. Galois-Raum besteht nur aus zwei Werten also aus 1 und 0. Es existiert im Galois-Raum kein Übertrag dies führ dazu, dass Addition und Substraktion die gleichen Operationen sind. Galois-Raum ist definier als 1+1=0, 1+0=1, 0+1=1, 0+0=0 (entspricht dem Binärweise XOR-Operation).
Division vom Polynom x6 + x3 durch g(x) im Galois-Raum:
x6 + 0*x5 + 0*x4 + x3 + 0*x2 + 0*x1 + 0*x0  /  x3 + 0*x2 + x1 + x0 = x3+x
x6 + 0*x5 +     x4 + x3 + 0*x2 + 0*x1 + 0*x0
x4
x4 +x2+x
x2 +x

3.Schritt: Nun setzen wir den Codewort aus dem Informationswort sowie aus dem Rest von der vorherigen Division zusammen. Dabei wird der Rest und das verschobene Informationswert einfach zusammen gehängt. also kommt für den Codewort raus:
c(x)=x +x2 +x3 +x6
Binär c = 0 1 1 1 0 0 1
Die Redundanz sind nun die ersten zwei Stellen im binären Code. Die Stellen 3 bis 7 enthalten die Information, die gesendet wird.

4.Schritt: Beim Empfänger wird jetzt der Codewort mit Rest durch den Generatorpolynom geteilt. Falls der Rest gleich Null ist betrachten wir die Stellen im Codewort, welche die Informationswort enthalten, also in unserem Fall die Stellen 3 bis 7.

Wir können nicht ein beliebiges Polynom als Generatorpolynom verwenden. Hierzu gibt es eine Liste von gültigen Generatorpolynomen auf dem zugehörigen Wikipedia-Artikel:
http://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung#Polynome_und_Typen
Quellen zu CRC: Kanalcodierung von André Neubauer, Wikipedia

 

Serielle Übertragung

Die Serielle Übertragung wird im Gamepad durch die XBee-Module realisiert. Hierbei dienen die XBee-Module als eine kabellose Verbindung der seriellen Schnittstellen des Arduinos.

Zur Datenübertragung wird der Arduino interne Seriellespeicher beschrieben. Hierbei wird vom Sender in den Speicher 7 Bytes geschrieben und ein "\n", welches das Ende des übertragenen Wortes darstellt. In den Bytes 1 bis 4 stehen die Stickwerte, die Bytes 5 bis 7 sind nur dann ungleich 0 wenn eine Taste betätigt wurde. In diesem Fall enthält der 5. Byte den Tastenwert, der 6. Byte enthält den Zählerwert(ACK-Wert) und der 7. Byte hat den Wert 1. Der 7. Byte gibt an, ob ein Tastenwert übertragen wird oder nicht und wird beim Empfänger als erstes geprüft. Der Zählerwert wird beim Sender generiert, dieser kann Werte zwischen 0 bis 255 annehmen. Falls eine Taste betätigt wird, wird der Zählerwert um eins erhöht und mit dem zugehörigen Tastenwert zum Empfänger geschickt. Der Empfänger schreibt den Zählerwert in den Seriellenspeicher und dieser wird anschließend vom Sender gelesen. Falls der Zählerwert, der vom Sender gelesen wird mit dem gesendeten übereinstimmt werden die übertragenen Bytes 5 bis 7 wieder auf 0 gesetzt.  

 

Aktueller Quellcode Empfänger:

#include <Servo.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <Mirf.h>
#include <MirfSpiDriver.h>

word wertbin(word infwert){
  for(int i=0; i<16; i++){
    if(bitRead(infwert,i)){
      Serial.print("1");
    }else{
      Serial.print("0");
    }
  }
  Serial.println(" Ende zahl");
}


byte flag_sendeart=1;

//Deklerationen von Servo
Servo motor[4];


/**********************************************/
/*Funktion zur Rückgabe von Infowert TABELLE*/
word get_info(word code){
 word infowert;
 switch(code){ 
   case 0:  infowert=0;
   break;
   case 38:  infowert=1;
   break;
   case 76:  infowert=2;
   break;
   case 106:  infowert=3;
   break;
   case 139:  infowert=4;
   break;
   case 173:  infowert=5;
   break;
   case 199:  infowert=6;
   break;
   case 225:  infowert=7;
   break;
   case 261:  infowert=8;
   break;
   case 291:  infowert=9;
   break;
   case 329:  infowert=10;
   break;
   case 367:  infowert=11;
   break;
   case 398:  infowert=12;
   break;
   case 424:  infowert=13;
   break;
   case 450:  infowert=14;
   break;
   case 484:  infowert=15;
   break;
   case 522:  infowert=16;
   break;
   case 556:  infowert=17;
   break;
   case 582:  infowert=18;
   break;
   case 608:  infowert=19;
   break;
   case 641:  infowert=20;
   break;
   case 679:  infowert=21;
   break;
   case 717:  infowert=22;
   break;
   case 747:  infowert=23;
   break;
   case 783:  infowert=24;
   break;
   case 809:  infowert=25;
   break;
   case 835:  infowert=26;
   break;
   case 869:  infowert=27;
   break;
   case 900:  infowert=28;
   break;
   case 930:  infowert=29;
   break;
   case 968:  infowert=30;
   break;
   case 1006:  infowert=31;
   break;
   case 1031:  infowert=32;
   break;
   case 1057:  infowert=33;
   break;
   case 1099:  infowert=34;
   break;
   case 1133:  infowert=35;
   break;
   case 1164:  infowert=36;
   break;
   case 1194:  infowert=37;
   break;
   case 1216:  infowert=38;
   break;
   case 1254:  infowert=39;
   break;
   case 1282:  infowert=40;
   break;
   case 1316:  infowert=41;
   break;
   case 1358:  infowert=42;
   break;
   case 1384:  infowert=43;
   break;
   case 1417:  infowert=44;
   break;
   case 1455:  infowert=45;
   break;
   case 1477:  infowert=46;
   break;
   case 1507:  infowert=47;
   break;
   case 1549:  infowert=48;
   break;
   case 1579:  infowert=49;
   break;
   case 1601:  infowert=50;
   break;
   case 1639:  infowert=51;
   break;
   case 1670:  infowert=52;
   break;
   case 1696:  infowert=53;
   break;
   case 1738:  infowert=54;
   break;
   case 1772:  infowert=55;
   break;
   case 1800:  infowert=56;
   break;
   case 1838:  infowert=57;
   break;
   case 1860:  infowert=58;
   break;
   case 1890:  infowert=59;
   break;
   case 1923:  infowert=60;
   break;
   case 1957:  infowert=61;
   break;
   case 1999:  infowert=62;
   break;
   case 2025:  infowert=63;
   break;
   case 2062:  infowert=64;
   break;
   case 2088:  infowert=65;
   break;
   case 2114:  infowert=66;
   break;
   case 2148:  infowert=67;
   break;
   case 2181:  infowert=68;
   break;
   case 2211:  infowert=69;
   break;
   case 2249:  infowert=70;
   break;
   case 2287:  infowert=71;
   break;
   case 2315:  infowert=72;
   break;
   case 2349:  infowert=73;
   break;
   case 2375:  infowert=74;
   break;
   case 2401:  infowert=75;
   break;
   case 2432:  infowert=76;
   break;
   case 2470:  infowert=77;
   break;
   case 2508:  infowert=78;
   break;
   case 2538:  infowert=79;
   break;
   case 2564:  infowert=80;
   break;
   case 2594:  infowert=81;
   break;
   case 2632:  infowert=82;
   break;
   case 2670:  infowert=83;
   break;
   case 2703:  infowert=84;
   break;
   case 2729:  infowert=85;
   break;
   case 2755:  infowert=86;
   break;
   case 2789:  infowert=87;
   break;
   case 2817:  infowert=88;
   break;
   case 2855:  infowert=89;
   break;
   case 2893:  infowert=90;
   break;
   case 2923:  infowert=91;
   break;
   case 2954:  infowert=92;
   break;
   case 2988:  infowert=93;
   break;
   case 3014:  infowert=94;
   break;
   case 3040:  infowert=95;
   break;
   case 3081:  infowert=96;
   break;
   case 3119:  infowert=97;
   break;
   case 3141:  infowert=98;
   break;
   case 3171:  infowert=99;
   break;
   case 3202:  infowert=100;
   break;
   case 3236:  infowert=101;
   break;
   case 3278:  infowert=102;
   break;
   case 3304:  infowert=103;
   break;
   case 3340:  infowert=104;
   break;
   case 3370:  infowert=105;
   break;
   case 3392:  infowert=106;
   break;
   case 3430:  infowert=107;
   break;
   case 3463:  infowert=108;
   break;
   case 3489:  infowert=109;
   break;
   case 3531:  infowert=110;
   break;
   case 3565:  infowert=111;
   break;
   case 3587:  infowert=112;
   break;
   case 3621:  infowert=113;
   break;
   case 3663:  infowert=114;
   break;
   case 3689:  infowert=115;
   break;
   case 3720:  infowert=116;
   break;
   case 3758:  infowert=117;
   break;
   case 3780:  infowert=118;
   break;
   case 3810:  infowert=119;
   break;
   case 3846:  infowert=120;
   break;
   case 3872:  infowert=121;
   break;
   case 3914:  infowert=122;
   break;
   case 3948:  infowert=123;
   break;
   case 3981:  infowert=124;
   break;
   case 4011:  infowert=125;
   break;
   case 4033:  infowert=126;
   break;
   case 4071:  infowert=127;
   break;
   case 4111:  infowert=128;
   break;
   case 4137:  infowert=129;
   break;
   case 4163:  infowert=130;
   break;
   case 4197:  infowert=131;
   break;
   case 4228:  infowert=132;
   break;
   case 4258:  infowert=133;
   break;
   case 4296:  infowert=134;
   break;
   case 4334:  infowert=135;
   break;
   case 4362:  infowert=136;
   break;
   case 4396:  infowert=137;
   break;
   case 4422:  infowert=138;
   break;
   case 4448:  infowert=139;
   break;
   case 4481:  infowert=140;
   break;
   case 4519:  infowert=141;
   break;
   case 4557:  infowert=142;
   break;
   case 4587:  infowert=143;
   break;
   case 4613:  infowert=144;
   break;
   case 4643:  infowert=145;
   break;
   case 4681:  infowert=146;
   break;
   case 4719:  infowert=147;
   break;
   case 4750:  infowert=148;
   break;
   case 4776:  infowert=149;
   break;
   case 4802:  infowert=150;
   break;
   case 4836:  infowert=151;
   break;
   case 4864:  infowert=152;
   break;
   case 4902:  infowert=153;
   break;
   case 4940:  infowert=154;
   break;
   case 4970:  infowert=155;
   break;
   case 5003:  infowert=156;
   break;
   case 5037:  infowert=157;
   break;
   case 5063:  infowert=158;
   break;
   case 5089:  infowert=159;
   break;
   case 5128:  infowert=160;
   break;
   case 5166:  infowert=161;
   break;
   case 5188:  infowert=162;
   break;
   case 5218:  infowert=163;
   break;
   case 5251:  infowert=164;
   break;
   case 5285:  infowert=165;
   break;
   case 5327:  infowert=166;
   break;
   case 5353:  infowert=167;
   break;
   case 5389:  infowert=168;
   break;
   case 5419:  infowert=169;
   break;
   case 5441:  infowert=170;
   break;
   case 5479:  infowert=171;
   break;
   case 5510:  infowert=172;
   break;
   case 5536:  infowert=173;
   break;
   case 5578:  infowert=174;
   break;
   case 5612:  infowert=175;
   break;
   case 5634:  infowert=176;
   break;
   case 5668:  infowert=177;
   break;
   case 5710:  infowert=178;
   break;
   case 5736:  infowert=179;
   break;
   case 5769:  infowert=180;
   break;
   case 5807:  infowert=181;
   break;
   case 5829:  infowert=182;
   break;
   case 5859:  infowert=183;
   break;
   case 5895:  infowert=184;
   break;
   case 5921:  infowert=185;
   break;
   case 5963:  infowert=186;
   break;
   case 5997:  infowert=187;
   break;
   case 6028:  infowert=188;
   break;
   case 6058:  infowert=189;
   break;
   case 6080:  infowert=190;
   break;
   case 6118:  infowert=191;
   break;
   case 6145:  infowert=192;
   break;
   case 6183:  infowert=193;
   break;
   case 6221:  infowert=194;
   break;
   case 6251:  infowert=195;
   break;
   case 6282:  infowert=196;
   break;
   case 6316:  infowert=197;
   break;
   case 6342:  infowert=198;
   break;
   case 6368:  infowert=199;
   break;
   case 6404:  infowert=200;
   break;
   case 6434:  infowert=201;
   break;
   case 6472:  infowert=202;
   break;
   case 6510:  infowert=203;
   break;
   case 6543:  infowert=204;
   break;
   case 6569:  infowert=205;
   break;
   case 6595:  infowert=206;
   break;
   case 6629:  infowert=207;
   break;
   case 6667:  infowert=208;
   break;
   case 6701:  infowert=209;
   break;
   case 6727:  infowert=210;
   break;
   case 6753:  infowert=211;
   break;
   case 6784:  infowert=212;
   break;
   case 6822:  infowert=213;
   break;
   case 6860:  infowert=214;
   break;
   case 6890:  infowert=215;
   break;
   case 6926:  infowert=216;
   break;
   case 6952:  infowert=217;
   break;
   case 6978:  infowert=218;
   break;
   case 7012:  infowert=219;
   break;
   case 7045:  infowert=220;
   break;
   case 7075:  infowert=221;
   break;
   case 7113:  infowert=222;
   break;
   case 7151:  infowert=223;
   break;
   case 7174:  infowert=224;
   break;
   case 7200:  infowert=225;
   break;
   case 7242:  infowert=226;
   break;
   case 7276:  infowert=227;
   break;
   case 7309:  infowert=228;
   break;
   case 7339:  infowert=229;
   break;
   case 7361:  infowert=230;
   break;
   case 7399:  infowert=231;
   break;
   case 7427:  infowert=232;
   break;
   case 7461:  infowert=233;
   break;
   case 7503:  infowert=234;
   break;
   case 7529:  infowert=235;
   break;
   case 7560:  infowert=236;
   break;
   case 7598:  infowert=237;
   break;
   case 7620:  infowert=238;
   break;
   case 7650:  infowert=239;
   break;
   case 7692:  infowert=240;
   break;
   case 7722:  infowert=241;
   break;
   case 7744:  infowert=242;
   break;
   case 7782:  infowert=243;
   break;
   case 7815:  infowert=244;
   break;
   case 7841:  infowert=245;
   break;
   case 7883:  infowert=246;
   break;
   case 7917:  infowert=247;
   break;
   case 7945:  infowert=248;
   break;
   case 7983:  infowert=249;
   break;
   case 8005:  infowert=250;
   break;
   case 8035:  infowert=251;
   break;
   case 8066:  infowert=252;
   break;
   case 8100:  infowert=253;
   break;
   case 8142:  infowert=254;
   break;
   case 8168:  infowert=255;
   break;
   case 8205:  infowert=256;
   break;
   case 8235:  infowert=257;
   break;
   case 8257:  infowert=258;
   break;
   case 8295:  infowert=259;
   break;
   case 8326:  infowert=260;
   break;
   case 8352:  infowert=261;
   break;
   case 8394:  infowert=262;
   break;
   case 8428:  infowert=263;
   break;
   case 8456:  infowert=264;
   break;
   case 8494:  infowert=265;
   break;
   case 8516:  infowert=266;
   break;
   case 8546:  infowert=267;
   break;
   case 8579:  infowert=268;
   break;
   case 8613:  infowert=269;
   break;
   case 8655:  infowert=270;
   break;
   case 8681:  infowert=271;
   break;
   case 12808: infowert=400;
   break;
   default: infowert=300;
   break;
 }
 return(infowert);
}
/*Ende Funktion zur Rückgabe von Infowert TABELLE*/
/*************************************************/


/****************************************************/
/*Anfang ACK_SendeFunktion für Rückerkennung*/
void ACK_Ruecksend(byte erkennungswert){
  byte data[9]={0};
  data[8]=erkennungswert;
  Mirf.send(data);
  while(Mirf.isSending());
}
/*Ende ACK_SendeFunktion für Rückerkennung*/
/******************************************************/


/*************************************************/
/*Anfang ACK_Funktion Tastenerkennung*/
void tastenerkennung(int tastenwert){
  switch(tastenwert){
    case 257: tastenwert=1;
    break;
    case 258: tastenwert=2;
    break;
    case 259: tastenwert=3;
    break;
    case 260: tastenwert=4;
    break;
    case 261: tastenwert=5;
    break;
    case 262: tastenwert=6;
    break;
    case 263: tastenwert=7;
    break;
    case 264: tastenwert=8;
    break;
    case 265: tastenwert=9;
    break;
    case 266: tastenwert=10;
    break;
    case 267: tastenwert=11;
    break;
    case 268: tastenwert=12;
    break;
    case 269: tastenwert=13;
    break;
    case 270: tastenwert=14;
    break;
    case 271: tastenwert=15;
    break;
  }
  if(tastenwert!=300){
    Serial.print("Taste: ");
    Serial.println(tastenwert);
  }
}
/*Ende ACK_Funktion Tastenerkennung*/
/************************************************/

/*************************************************/
/*Servosteuerung*/
byte servorun(word in[4]){
  int time[4];
  for(int i=0;i<4;i++){
    Serial.print(in[0]);
    Serial.print("    ");
    Serial.print(in[1]);
    Serial.print("    ");
    Serial.print(in[2]);
    Serial.print("    ");
    Serial.print(in[3]);
    Serial.println("    ");
    time[i]=map(in[i],0,255,0,179);
    motor[i].write(time[i]);
  }
  return(0);
}
/*Ende Servosteuerung*/
/**********************************************/


/*********************************************/
/*Nordic Datei Empfang-Funktion*/
void Nordic_getData(){
  byte data[9];
  word codewort[4];
  if(!Mirf.isSending()){
    Mirf.getData(data);
    //Codewortrekonstruktion
    codewort[0] = (unsigned int)data[0];
    codewort[0] += ((unsigned int)data[1])<<8;
    codewort[1] = (unsigned int)data[2];
    codewort[1] += ((unsigned int)data[3])<<8;
    codewort[2] = (unsigned int)data[4];
    codewort[2] += ((unsigned int)data[5])<<8;
    codewort[3] = (unsigned int)data[6];
    codewort[3] += ((unsigned int)data[7])<<8;
    for(int i=0;i<4;i++){
      codewort[i]=get_info(codewort[i]);
    }
    if((codewort[0]<256)&&(codewort[1]<256)&&(codewort[2]<256)&&(codewort[3]<256)){
      servorun(codewort); 
    }
    if(data[8]==1){
      Serial.println(" data 8 ist nicht 0" );
      Serial.println(data[8]);
      tastenerkennung(codewort[0]);
      ACK_Ruecksend(codewort[1]);
    }
  }
}
/*Ende Nordic Datei Empfang-Funktion*/
/***********************************************/


/*********************************************/
/*Anfang ACK_Serielltasten*/
void ACK_Serielltasten(byte erkennungswert){
  for(int i=0;i<7;i++){
    if(erkennungswert<16){
      Serial.print(0,HEX);
    }
    Serial.print(erkennungswert,HEX);
    Serial.print(" ");
  }
  Serial.print("\n");
}
/*Ende ACK_Serielltasten*/
/*********************************************/


/**********************************************/
/*Seriell Empfangen*/

void serial_empfang(){
  int i;
  byte buffer[23]={0}; 
  byte tastenwert, erkennungswert, Tasten_flag;
  word infowert[7]={0},motorwert[4]={0};
  
  if(Serial.available()>21){
    i=0;
    while(i<23){
      buffer[i]=Serial.read();
      if(buffer[i]=='\n'){
        i=23;
      }
      i++;
    }
    sscanf((char*)buffer, "%2x %2x %2x %2x %2x %2x %2x ",&infowert[0],&infowert[1],&infowert[2],&infowert[3],&infowert[4],&infowert[5],&infowert[6]);
    if(infowert[6]){
      Serial.println("Taste erhalten");
      Serial.print("Tastenwert: ");
      Serial.println(infowert[4]);
      Serial.print("erkennungswert: ");
      Serial.println(infowert[5]);
      ACK_Serielltasten(infowert[5]);
    }
    for(int i=0;i<4;i++){
      motorwert[i]=infowert[i];
    }
    servorun(motorwert);
  }
}
/*Ende Seriell Empfangen*/
/***********************************************/
    

/*SETUP*/
void setup(){
  
  //Für die serielle Schnittstelle
  Serial.begin(19200);
  
  //Einfügen von Mirf-library
  Mirf.spi = &MirfHardwareSpi;
  Mirf.csnPin = 10;
  Mirf.cePin = 9;
  Mirf.init(); 
  Mirf.setRADDR((byte *) "Kanal");
  Mirf.setTADDR((byte *) "Kanal_ACK");
  Mirf.payload = 9;
  Mirf.channel = 90;
  Mirf.config();
  
  //Motor deklaration
  motor[0].attach(3,1000,2000);
  motor[1].attach(4,1000,2000);
  motor[2].attach(5,1000,2000);
  motor[3].attach(6,1000,2000);
}

/*LOOP*/
void loop(){
   flag_sendeart=1;
   if(flag_sendeart){
     Nordic_getData();
   }else{
     serial_empfang();
   }
 }
    

Aktueller Quellcode Sender:

#include <SPI.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <Mirf.h>
#include <MirfSpiDriver.h>

//PINS für Matrix
#define PINZ_1 A4
#define PINZ_2 A5
#define PINZ_3 7
#define PINZ_4 6

#define PINS_1 5
#define PINS_2 4
#define PINS_3 3
#define PINS_4 2

//Flags für ACK
volatile byte empfang_counter, sende_counter, zeahler=1, list_length=0;
volatile boolean empfang_flag=0, sende_flag=0, connection_lost=0, interrupt_flag=0, Serielltaste_flag=0;
volatile boolean Serielltaste_ACKflag=0;
volatile int timeout;

//Werte zum Umschalten von XBee und Nordic
volatile byte flag_sendeart=1;

//Matrix-Pins
volatile int pinZ[4] = {PINZ_1,PINZ_2,PINZ_3,PINZ_4};
volatile int pinS[4] = {PINS_1,PINS_2,PINS_3,PINS_4};

//Analog Pin-Deklarationen
volatile int analogpin1Y=A0;
volatile int analogpin1X=A1;
volatile int analogpin2X=A2;
volatile int analogpin2Y=A3;

//Verkette Liste zur Nutzung als Puffer
typedef struct knoten {
        byte pinwert, count;
        struct knoten *next;
        }Knoten;
     
Knoten *head=NULL;

// serial ...
unsigned long previousMillis_senden = 0;
unsigned long previousMillis_empfangen=0;

/**************************************/
/*Anfang Funktionen für ACK bzw. Tasten*/


/****************************************/
/*Anfang Knoten hinzufügen*/
void knoten_hinzufuegen(word wert){
//  Serial.println("in knoten hinzufuegen");
  Knoten *element;
  element=(Knoten *)malloc(sizeof(Knoten));
  element->next=NULL;
  if(head==NULL){
    head=element;
    head->pinwert=wert;
    if(zeahler==0){
      zeahler=1;
    }
    head->count=zeahler;
    zeahler=zeahler+1;
  }else{
    Knoten *var;
    var=head;
    while(var->next!=NULL){
      var=var->next;
    }
    var->next=element;
    element->pinwert=wert;
    if(zeahler==0){
      zeahler=1;
    }
    element->count=zeahler;
    zeahler=zeahler+1;
  }
  list_length=list_length+1;
//  Serial.print("list length ");
//  Serial.println(list_length);
}
/*Ende Knoten hinzufügen*/
/**********************************************/


/****************************************/
/*Anfang Start der Liste löschen*/
int delete_start(){
  Serial.println("in delete");
  Knoten *tmp;
  tmp=head;
  head=head->next;
  free(tmp);
  list_length=list_length-1;
  connection_lost=0;
  Serial.print("list length ");
  Serial.println(list_length);
  timeout=0;
  Serielltaste_flag=0;
}
/*Ende Start der Liste löschen*/
/****************************************/


/**************************************/
/*Anfang ACK_Tasten Empfangen*/
void ACK_Tasten_empfangen(){
  Serial.println("in Empfangen");
  byte data[9];
  byte erkennungswert;
  if(flag_sendeart){
    if(!Mirf.isSending()){
      Mirf.getData(data);
    }
    if(data[8]==head->count){
      delete_start();
    }
  }else{
    if(Serial.available()){
      Serial.readBytes((char*) erkennungswert, 1);
      if(erkennungswert==head->count){
        delete_start();
      }
    }
  }
}
/*Ende ACK_Tasten Empfangen*/
/**************************************/


/**************************************/
/*Anfang Timeout-Funktion*/
void timeout_function(){
  Serial.println("Connection Lost");
  interrupt_flag=0;
//  ping_senden();
//  while(connection_lost){
//    //Blink LED Blink!!!
//  }
}
/*Ende Timeout-Funktion*/
/***************************************/


/*Ende Funktionen für ACK bzw. Tasten*/
/**************************************/


/**************************************/
/* Funktionen zum Ablesen der Position*/
//2. Stick y-Achse
float pin2YWertNormiertLesen(float wert){
  wert=analogRead(wert);
  wert=map(wert,0,990,0,255);
  return(wert);
}
//2.Stick x-Achse
float pin2XWertNormiertLesen(float wert){
  wert=analogRead(wert);
  wert=map(wert,0,981,0,255);
  return(wert);
}
//1.Stick x-Achse
float pin1XWertNormiertLesen(float wert){
  wert=analogRead(wert);
  wert=map(wert,0,995,0,255);
  return(wert);
}
//1.Stick y-Achse
float pin1YWertNormiertLesen(float wert){
  wert=analogRead(wert);
  wert=map(wert,0,992,0,255);
  return(wert);
}
/*Ende für Funktionen zum Ablesen der Position*/
/**********************************************


/*****************************************/
/* Funktion zur Rückgabe von Codewort TABELLE */
word gen_code(word infowert){
  word code;
  switch(infowert){
    case 0: code=0; 
    break;
    case 1: code=38; 
    break;
    case 2: code=76; 
    break;
    case 3: code=106; 
    break;
    case 4: code=139; 
    break;
    case 5: code=173; 
    break;
    case 6: code=199; 
    break;
    case 7: code=225; 
    break;
    case 8: code=261; 
    break;
    case 9: code=291; 
    break;
    case 10: code=329; 
    break;
    case 11: code=367; 
    break;
    case 12: code=398; 
    break;
    case 13: code=424; 
    break;
    case 14: code=450; 
    break;
    case 15: code=484; 
    break;
    case 16: code=522; 
    break;
    case 17: code=556; 
    break;
    case 18: code=582; 
    break;
    case 19: code=608; 
    break;
    case 20: code=641; 
    break;
    case 21: code=679; 
    break;
    case 22: code=717; 
    break;
    case 23: code=747; 
    break;
    case 24: code=783; 
    break;
    case 25: code=809; 
    break;
    case 26: code=835; 
    break;
    case 27: code=869; 
    break;
    case 28: code=900; 
    break;
    case 29: code=930; 
    break;
    case 30: code=968; 
    break;
    case 31: code=1006; 
    break;
    case 32: code=1031; 
    break;
    case 33: code=1057; 
    break;
    case 34: code=1099; 
    break;
    case 35: code=1133; 
    break;
    case 36: code=1164; 
    break;
    case 37: code=1194; 
    break;
    case 38: code=1216; 
    break;
    case 39: code=1254; 
    break;
    case 40: code=1282; 
    break;
    case 41: code=1316; 
    break;
    case 42: code=1358; 
    break;
    case 43: code=1384; 
    break;
    case 44: code=1417; 
    break;
    case 45: code=1455; 
    break;
    case 46: code=1477; 
    break;
    case 47: code=1507; 
    break;
    case 48: code=1549; 
    break;
    case 49: code=1579; 
    break;
    case 50: code=1601; 
    break;
    case 51: code=1639; 
    break;
    case 52: code=1670; 
    break;
    case 53: code=1696; 
    break;
    case 54: code=1738; 
    break;
    case 55: code=1772; 
    break;
    case 56: code=1800; 
    break;
    case 57: code=1838; 
    break;
    case 58: code=1860; 
    break;
    case 59: code=1890; 
    break;
    case 60: code=1923; 
    break;
    case 61: code=1957; 
    break;
    case 62: code=1999; 
    break;
    case 63: code=2025; 
    break;
    case 64: code=2062; 
    break;
    case 65: code=2088; 
    break;
    case 66: code=2114; 
    break;
    case 67: code=2148; 
    break;
    case 68: code=2181; 
    break;
    case 69: code=2211; 
    break;
    case 70: code=2249; 
    break;
    case 71: code=2287; 
    break;
    case 72: code=2315; 
    break;
    case 73: code=2349; 
    break;
    case 74: code=2375; 
    break;
    case 75: code=2401; 
    break;
    case 76: code=2432; 
    break;
    case 77: code=2470; 
    break;
    case 78: code=2508; 
    break;
    case 79: code=2538; 
    break;
    case 80: code=2564; 
    break;
    case 81: code=2594; 
    break;
    case 82: code=2632; 
    break;
    case 83: code=2670; 
    break;
    case 84: code=2703; 
    break;
    case 85: code=2729; 
    break;
    case 86: code=2755; 
    break;
    case 87: code=2789; 
    break;
    case 88: code=2817; 
    break;
    case 89: code=2855; 
    break;
    case 90: code=2893; 
    break;
    case 91: code=2923; 
    break;
    case 92: code=2954; 
    break;
    case 93: code=2988; 
    break;
    case 94: code=3014; 
    break;
    case 95: code=3040; 
    break;
    case 96: code=3081; 
    break;
    case 97: code=3119; 
    break;
    case 98: code=3141; 
    break;
    case 99: code=3171; 
    break;
    case 100: code=3202; 
    break;
    case 101: code=3236; 
    break;
    case 102: code=3278; 
    break;
    case 103: code=3304; 
    break;
    case 104: code=3340; 
    break;
    case 105: code=3370; 
    break;
    case 106: code=3392; 
    break;
    case 107: code=3430; 
    break;
    case 108: code=3463; 
    break;
    case 109: code=3489; 
    break;
    case 110: code=3531; 
    break;
    case 111: code=3565; 
    break;
    case 112: code=3587; 
    break;
    case 113: code=3621; 
    break;
    case 114: code=3663; 
    break;
    case 115: code=3689; 
    break;
    case 116: code=3720; 
    break;
    case 117: code=3758; 
    break;
    case 118: code=3780; 
    break;
    case 119: code=3810; 
    break;
    case 120: code=3846; 
    break;
    case 121: code=3872; 
    break;
    case 122: code=3914; 
    break;
    case 123: code=3948; 
    break;
    case 124: code=3981; 
    break;
    case 125: code=4011; 
    break;
    case 126: code=4033; 
    break;
    case 127: code=4071; 
    break;
    case 128: code=4111; 
    break;
    case 129: code=4137; 
    break;
    case 130: code=4163; 
    break;
    case 131: code=4197; 
    break;
    case 132: code=4228; 
    break;
    case 133: code=4258; 
    break;
    case 134: code=4296; 
    break;
    case 135: code=4334; 
    break;
    case 136: code=4362; 
    break;
    case 137: code=4396; 
    break;
    case 138: code=4422; 
    break;
    case 139: code=4448; 
    break;
    case 140: code=4481; 
    break;
    case 141: code=4519; 
    break;
    case 142: code=4557; 
    break;
    case 143: code=4587; 
    break;
    case 144: code=4613; 
    break;
    case 145: code=4643; 
    break;
    case 146: code=4681; 
    break;
    case 147: code=4719; 
    break;
    case 148: code=4750; 
    break;
    case 149: code=4776; 
    break;
    case 150: code=4802; 
    break;
    case 151: code=4836; 
    break;
    case 152: code=4864; 
    break;
    case 153: code=4902; 
    break;
    case 154: code=4940; 
    break;
    case 155: code=4970; 
    break;
    case 156: code=5003; 
    break;
    case 157: code=5037; 
    break;
    case 158: code=5063; 
    break;
    case 159: code=5089; 
    break;
    case 160: code=5128; 
    break;
    case 161: code=5166; 
    break;
    case 162: code=5188; 
    break;
    case 163: code=5218; 
    break;
    case 164: code=5251; 
    break;
    case 165: code=5285; 
    break;
    case 166: code=5327; 
    break;
    case 167: code=5353; 
    break;
    case 168: code=5389; 
    break;
    case 169: code=5419; 
    break;
    case 170: code=5441; 
    break;
    case 171: code=5479; 
    break;
    case 172: code=5510; 
    break;
    case 173: code=5536; 
    break;
    case 174: code=5578; 
    break;
    case 175: code=5612; 
    break;
    case 176: code=5634; 
    break;
    case 177: code=5668; 
    break;
    case 178: code=5710; 
    break;
    case 179: code=5736; 
    break;
    case 180: code=5769; 
    break;
    case 181: code=5807; 
    break;
    case 182: code=5829; 
    break;
    case 183: code=5859; 
    break;
    case 184: code=5895; 
    break;
    case 185: code=5921; 
    break;
    case 186: code=5963; 
    break;
    case 187: code=5997; 
    break;
    case 188: code=6028; 
    break;
    case 189: code=6058; 
    break;
    case 190: code=6080; 
    break;
    case 191: code=6118; 
    break;
    case 192: code=6145; 
    break;
    case 193: code=6183; 
    break;
    case 194: code=6221; 
    break;
    case 195: code=6251; 
    break;
    case 196: code=6282; 
    break;
    case 197: code=6316; 
    break;
    case 198: code=6342; 
    break;
    case 199: code=6368; 
    break;
    case 200: code=6404; 
    break;
    case 201: code=6434; 
    break;
    case 202: code=6472; 
    break;
    case 203: code=6510; 
    break;
    case 204: code=6543; 
    break;
    case 205: code=6569; 
    break;
    case 206: code=6595; 
    break;
    case 207: code=6629; 
    break;
    case 208: code=6667; 
    break;
    case 209: code=6701; 
    break;
    case 210: code=6727; 
    break;
    case 211: code=6753; 
    break;
    case 212: code=6784; 
    break;
    case 213: code=6822; 
    break;
    case 214: code=6860; 
    break;
    case 215: code=6890; 
    break;
    case 216: code=6926; 
    break;
    case 217: code=6952; 
    break;
    case 218: code=6978; 
    break;
    case 219: code=7012; 
    break;
    case 220: code=7045; 
    break;
    case 221: code=7075; 
    break;
    case 222: code=7113; 
    break;
    case 223: code=7151; 
    break;
    case 224: code=7174; 
    break;
    case 225: code=7200; 
    break;
    case 226: code=7242; 
    break;
    case 227: code=7276; 
    break;
    case 228: code=7309; 
    break;
    case 229: code=7339; 
    break;
    case 230: code=7361; 
    break;
    case 231: code=7399; 
    break;
    case 232: code=7427; 
    break;
    case 233: code=7461; 
    break;
    case 234: code=7503; 
    break;
    case 235: code=7529; 
    break;
    case 236: code=7560; 
    break;
    case 237: code=7598; 
    break;
    case 238: code=7620; 
    break;
    case 239: code=7650; 
    break;
    case 240: code=7692; 
    break;
    case 241: code=7722; 
    break;
    case 242: code=7744; 
    break;
    case 243: code=7782; 
    break;
    case 244: code=7815; 
    break;
    case 245: code=7841; 
    break;
    case 246: code=7883; 
    break;
    case 247: code=7917; 
    break;
    case 248: code=7945; 
    break;
    case 249: code=7983; 
    break;
    case 250: code=8005; 
    break;
    case 251: code=8035; 
    break;
    case 252: code=8066; 
    break;
    case 253: code=8100; 
    break;
    case 254: code=8142; 
    break;
    case 255: code=8168; 
    break;
    case 256: code=8205;
    break;
    case 257: code=8235;
    break;
    case 258: code=8257;
    break;
    case 259: code=8295;
    break;
    case 260: code=8326;
    break;
    case 261: code=8352;
    break;
    case 262: code=8394;
    break;
    case 263: code=8428;
    break;
    case 264: code=8456;
    break;
    case 265: code=8494;
    break;
    case 266: code=8516;
    break;
    case 267: code=8546;
    break;
    case 268: code=8579;
    break;
    case 269: code=8613;
    break;
    case 270: code=8655;
    break;
    case 271: code=8681;
    break;
    case 400: code=12808;
    break;
    default: code=9000;
    break;
  }
   return(code);
}
/*Ende Funktion zur Rückgabe von Codewort TABELLE*/
/*******************************************/


/**************************/
/* Nordic Sende-Funktion */
void NordicSenden(int wert){
  byte data[9]={0};
  int pinwert[4]={0};
    switch(wert){
    //Ablesen der Joysticwerte
    case 1:
              pinwert[0]=pin1YWertNormiertLesen(analogpin1Y);
              pinwert[1]=pin1XWertNormiertLesen(analogpin1X);
              pinwert[2]=pin2XWertNormiertLesen(analogpin2X);
              pinwert[3]=pin2YWertNormiertLesen(analogpin2Y);
              data[8]=0;
              break;
    case 2:   
              pinwert[0]=head->pinwert;
              pinwert[1]=head->count;
              pinwert[2]=0;
              pinwert[3]=0;
              data[8]=1;
              break;    
  }
  
  //Deklaration und berechnen der Kodierung für Senden
  word infwert[4], codewort[4];
  for(int i=0; i<4; i++){
    infwert[i]=pinwert[i];
    codewort[i]=gen_code(infwert[i]);
  }
      
    Serial.print(codewort[0]);
    Serial.print("    ");
    Serial.print(codewort[1]);
    Serial.print("    ");
    Serial.print(codewort[2]);
    Serial.print("    ");
    Serial.print(codewort[3]);
    Serial.println("    ");
    
  //Codewort in Data schreiben
  for(int z=0;z<8;z++){
    if(bitRead(codewort[0],z)){
      bitSet(data[0],z);
    }
    if(bitRead(codewort[0],z+8)){
      bitSet(data[1],z);
    }
  }
  for(int z=0;z<8;z++){
    if(bitRead(codewort[1],z)){
      bitSet(data[2],z);
    }
    if(bitRead(codewort[1],z+8)){
      bitSet(data[3],z);
    }
  }
  for(int z=0;z<8;z++){
    if(bitRead(codewort[2],z)){
      bitSet(data[4],z);
    }
    if(bitRead(codewort[2],z+8)){
      bitSet(data[5],z);
    }
  }
  for(int z=0;z<8;z++){
    if(bitRead(codewort[3],z)){
      bitSet(data[6],z);
    }
    if(bitRead(codewort[3],z+8)){
      bitSet(data[7],z);
    }
  }
  //Senden
  Mirf.send(data);
  while(Mirf.isSending());
}
/* Ende Nordic-Sende-Funktion */
/******************************/


/*****************************/
/*Anfang ACK_Tastenerkennung*/
boolean ACK_Seriell_tastenerkennung(){
  Serial.println("ACK_Seriell_Tastenempfang");
  byte buffer[23],infowert[7]={0};
  int i=0;
  if(Serial.available()>21){
    i=0;
    while(i<23){
      buffer[i]=Serial.read();
      if(buffer[i]=='\n'){
        i=23;
      }
      i++;
    }
  }
  sscanf((char*)buffer, "%2x %2x %2x %2x %2x %2x %2x ",&infowert[0],&infowert[1],&infowert[2],&infowert[3],&infowert[4],&infowert[5],&infowert[6]);
  if(infowert[0]==head->count){
    return(1);
  }else{
    return(0);
  }  
}
/*Ende ACK_Tastenerkennung*/
/**********************************/


/***********************************/
/* Anfang Funktion zur Übertragen mit XBee */
void UebertragenSeriell(){
  byte pinwert[7]={0};
  boolean send_flag=1;
  pinwert[0]=pin1YWertNormiertLesen(analogpin1Y);
  pinwert[1]=pin1XWertNormiertLesen(analogpin1X);
  pinwert[2]=pin2XWertNormiertLesen(analogpin2X);
  pinwert[3]=pin2YWertNormiertLesen(analogpin2Y);
  if(Serielltaste_flag){
    pinwert[4]=head->pinwert;
    pinwert[5]=head->count;
    pinwert[6]=1;
  }else{
    pinwert[4]=0;
    pinwert[5]=0;
    pinwert[6]=0;
    Serielltaste_ACKflag=1;
  }
  for(int i=0; i<7; i++){
    if(pinwert[i]<16){
      Serial.print(0,HEX);
    }
    Serial.print(pinwert[i],HEX);
    Serial.print(" ");
  }
  Serial.print("\n");
}
/*Ende Funktion zur Übertragung mit XBee*/
/****************************************/


/******************************************/
/*Anfang Tastenfunktion für die Funktionalitätszuordnung einzelner Tasten*/
void tasten(byte taste){
  if(flag_sendeart){
    sende_flag=1;
    switch(taste){
      case 0:  knoten_hinzufuegen(259);  
      break;
      case 1:  knoten_hinzufuegen(257);
      break;
      case 2:  knoten_hinzufuegen(258);
      break;
      case 3:  sende_flag=0;
               flag_sendeart=0;
      break;
      case 4:  knoten_hinzufuegen(260);  
      break;
      case 5:  knoten_hinzufuegen(261);
      break;
      case 6:  knoten_hinzufuegen(262);
      break;
      case 7:  knoten_hinzufuegen(263);
      break;
      case 8:  knoten_hinzufuegen(264);
      break;
      case 9:  knoten_hinzufuegen(265);
      break;
      case 10: knoten_hinzufuegen(266); 
      break;
      case 11: knoten_hinzufuegen(267); 
      break;
      case 12: knoten_hinzufuegen(268);
      break;
      case 13: knoten_hinzufuegen(269);
      break;
      case 14: knoten_hinzufuegen(270);
      break;
      case 15: knoten_hinzufuegen(271);
      break;
    }
  }else{
    if(taste==3){
      flag_sendeart=1; 
      sende_flag=0;
    }else{
      knoten_hinzufuegen(taste);
      sende_flag=0;
      Serielltaste_flag=1;
    }
  }
}
/*Ende Tastenfunktion für die Funktionalitätszuordnung einzelner Tasten*/     
/**********************************************/    


/***************************************/
/*Anfang der Entprellung*/
void entprellung(byte schalter, byte taste){
    int zeit, steigendeFlanke, fallendeFlanke;
    byte zustand=1;
    boolean flag=1;
while(flag){
  if(flag_sendeart){
    NordicSenden(1);
  }else{
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis_senden > 100) {
      previousMillis_senden=millis();
      UebertragenSeriell();
      sende_flag=0;
    }
  }
    switch(zustand){
    case 1:
           if(digitalRead(schalter) == 0){
             zustand=2;
           }
           break;
    case 2:
           steigendeFlanke=millis();
           if(digitalRead(schalter)==1){
             zustand=3;
           }
           break;
    case 3:
           fallendeFlanke=millis();
           if((fallendeFlanke-steigendeFlanke)>50){
             zustand=4;
             zeit=millis();
           }else if(digitalRead(schalter)==0){
             zustand=2;
           }
           break;
    case 4:
          
           if(digitalRead(schalter)==0){
             zeit=millis();
           }else if((millis()-zeit)>10){
             flag=0;
             zustand=1;
             zeit=0;
           }
           break;
    }
  }
}
/*Ende der Entprellung*/
/*********************************/


/*SETUP*/
void setup(){
  
 //Matrix
  for (int i = 0; i<=3; i++){
    pinMode(pinZ[i], INPUT);
    pinMode(pinS[i], OUTPUT);
    digitalWrite(pinZ[i], HIGH);
  }
  
  //Pins zum Ablesen
  pinMode(analogpin1Y, INPUT);
  pinMode(analogpin1X, INPUT);
  pinMode(analogpin2X, INPUT);
  pinMode(analogpin2Y, INPUT);
  
  //Für die serielle Schnittstelle
  Serial.begin(19200);
  
  //Einfügen von Mirf-library
  Mirf.spi = &MirfHardwareSpi;
  Mirf.csnPin = 10;
  Mirf.cePin = 9;
  Mirf.init(); 
  Mirf.setTADDR((byte *) "Kanal");
  Mirf.setRADDR((byte *) "Kanal_ACK");
  Mirf.payload = 9;
  Mirf.channel = 90;
  Mirf.config();
  
  //Timer 2 Overflow interrupt erlauben
  TIMSK2=1;
  
}

/*LOOP*/
void loop(){
  unsigned long currentMillis_senden = millis();
  unsigned long currentMillis_empfangen=millis();
  /*Übertragung*/
  if(flag_sendeart){
    NordicSenden(1);
  }else{
   if(currentMillis_senden - previousMillis_senden >100) {
      previousMillis_senden=millis();
      UebertragenSeriell();
      sende_flag=0;
    }
  }
  
  //Matrix-Abfrage
  for(int i = 0;i<=3;i++){
    digitalWrite(pinS[i], LOW);
    for(int j = 0; j<=3; j++){
      if(digitalRead(pinZ[j])==0){
        tasten(4*i+j);
        entprellung(pinZ[j],4*i+j);
      }
    }
    digitalWrite(pinS[i], HIGH);
  }
  
  //Abfrage für ACK_Senden der Tasten Nordic
  if(sende_flag&&flag_sendeart){
    NordicSenden(2);
    sende_flag=0;
  }
  if(empfang_flag&&flag_sendeart){
    ACK_Tasten_empfangen();
    empfang_flag=0;
  }
  if(connection_lost&&flag_sendeart){
    timeout_function();
  }
  if(list_length&&flag_sendeart){
    interrupt_flag=1;
  }else if((list_length==0)&&flag_sendeart){
    interrupt_flag=0;
  }
  
  //Abfrage für ACK_Senden der Tasten Seriell
  if(currentMillis_empfangen - previousMillis_empfangen >200){
    if(Serielltaste_flag&&(flag_sendeart==0)){
      if(ACK_Seriell_tastenerkennung()){
        delete_start();
      }
    }
    if(list_length&&(flag_sendeart==0)){
      Serielltaste_flag=1;
    }
    previousMillis_empfangen=millis();
  }
}

//Timer 2 ISR_OVF
ISR(TIMER2_OVF_vect){
  TCNT2=1;
  if(interrupt_flag){
    empfang_counter=empfang_counter+1;
    sende_counter=sende_counter+1;
    if(empfang_counter==10){
      empfang_flag=1;
      empfang_counter=0;
      sende_counter=sende_counter+1;
      if(sende_counter==5){
        sende_flag=1;
        sende_counter=0;
        timeout=timeout+1;
        if(timeout==10){
          connection_lost=1;
        }
      }
    }
  }
}