Forum: Mikrocontroller und Digitale Elektronik Arduino Keypad und Multitasking


von Andreas F. (codecasa)


Lesenswert?

Hallo zusammen

Ich habe folgendes Problem ich bin dabei eine Steuerung für eine 
Maschine zu Programmieren inkl. Display.

Die Maschiene hat folgende Funktionen:
Pumpe - An / Aus
Injektion von Flüssigkeiten - An / Aus
Lufdruck - An/Aus/ Impulsverfahren nach gespeicherten Einstellungen 
(Imp-Dauer & Pause)

Jetzt habe ich das Problem das wenn ich alles mit diesem Blöden Delay 
mache das Der Controller solange garnbicht mehr reargiert.

Wie sieht es Mit Multitasking aus Ich will mit dem Keypad immer Einfluss 
haben können.

z.B ich starte Mit der Impulsetaste Die IMP-Sequenz und will ausschalten 
aber nichts mehr reargiert.

Folgend mal der Code:

// include the library code:
#include <Wire.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include <Menu.h>
#include <LCDMenu2.h>


#include <Keypad.h>

#define CONFIG_START 32

const byte ROWS = 4; //four rows
const byte COLS = 3; //tree columns
//define the cymbols on the buttons of the keypads
char  hexaKeys[ROWS][COLS] = {
{'p','u','m'},
{'l','e','r'},
{'b','d','#'},
{'1','2','3'}
};

//# Own Chars
//# ==================================
    uint8_t arrow_up[8]    = {0x4,0xE,0x15,0x4,0x4,0x4,0x0};
    uint8_t arrow_down[8]  = {0x0,0x4,0x4,0x4,0x15,0xE,0x4};

byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the 
keypad
byte colPins[COLS] = {6, 7, 8}; //connect to the column pinouts of the 
keypad

boolean sysStatus = false;


struct StoreStruct{
    float impPause;
    float impDauer;
} storage = {
0, 0
};


//initialize an instance of class NewKeypad
Keypad keypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, 
COLS);


/*-----( Declare Constants )-----*/
/*-----( Declare objects )-----*/
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27
/*-----( Declare Variables )-----*/

const int pumpe = 9;
const int injektor = 10;
const int v_pneumatik = 12;
const int v_leer = 11;
const int startposX = 5;

    Menu top("Root");

    // menu, lcd, rows, cols, arrow_up_pos, arrow_down_pos
    LCDMenu2 Root(top, lcd , 4, 20, 0, 1);

    Menu Item1("Jobs");
    Menu Item11("Job 01");
    Menu Item12("Job 02");
    Menu Item13("Job 03");
    Menu Item14("Job 04");
    Menu Item15("Job 05");
    Menu Item16("Job 06");
    Menu Item17("Job 07");
    Menu Item2("Einstellungen");
    Menu Item21("Impulse");
    Menu Item211("Pause");
    Menu Item212("IMP-Dauer");
    Menu Item22("Uhr");
    Menu Item23("Auto-Aus");
    Menu Item3("Geraeteinfo");
    Menu Item31("Name:");
    Menu Item32("Impulse-Cleaner");
    Menu Item33("Hersteller:");
    Menu Item34("Muster GmbH");
    Menu Item35("Gewicht:");
    Menu Item36("35 Kg");


String strPumpe = "PMP";
String strSanosil = "SAN";
String strPneumatik = "IMP";

String aktMenu = "main";
int menuPos = 0;
int mAnzMain = 3;
int mAnzSetup = 3;

boolean tmpFF = false;


void setup() {
  loadData();

  // setup Relais
  pinMode(pumpe, OUTPUT);
  pinMode(injektor, OUTPUT);
  pinMode(v_pneumatik, OUTPUT);
  pinMode(v_leer, OUTPUT);

  delay(500);
  lcd.init(); // initialize the lcd
  //lcd.backlight();

        lcd.createChar(0, arrow_up);
        lcd.createChar(1, arrow_down);

  menuinit();

  keypad.addEventListener(keypadEvent); //add an event listener for this 
keypad

}

    //## Menu Init
    void menuinit()
    {
        top.addChild(Item1);
          Item1.addChild(Item11);
          Item1.addChild(Item12);
          Item1.addChild(Item13);
          Item1.addChild(Item14);
          Item1.addChild(Item15);
          Item1.addChild(Item16);
          Item1.addChild(Item17);
        top.addChild(Item2);
          Item2.addChild(Item21);
            Item21.addChild(Item211);
            Item21.addChild(Item212);
          Item2.addChild(Item22);
          Item2.addChild(Item23);
        top.addChild(Item3);
          Item3.addChild(Item31);
          Item3.addChild(Item32);
          Item3.addChild(Item33);
          Item3.addChild(Item34);
          Item3.addChild(Item35);
          Item3.addChild(Item36);
    }


void p_pulse(int ps, int dauer){
  digitalWrite(v_pneumatik, HIGH);
  aktStatus();
  delay(dauer);
  digitalWrite(v_pneumatik, LOW);
  aktStatus();
  delay(ps);
}

void menu(){
  lcd.clear();
  Root.display();


}


// Aktualisiert de Status in der linken Spalte
void aktStatus(){
    lcd.setCursor(0,0);
    if(digitalRead(pumpe)==HIGH) {lcd.print(strPumpe);} else 
{lcd.print("    ");};
    lcd.setCursor(0,1);
    if(digitalRead(injektor)==HIGH) {lcd.print(strSanosil);} else 
{lcd.print("    ");};
    lcd.setCursor(0,2);
    if(digitalRead(v_pneumatik)==HIGH) {lcd.print(strPneumatik);} else 
{lcd.print("    ");};
}




// Steuert Jobablauf ohne Keypad interupt
void job01(){
  digitalWrite(pumpe, HIGH);
  aktStatus();
  delay(7000);

  digitalWrite(injektor, HIGH);
  aktStatus();
  delay(11000);

  int d = 500;
  int p = 200;


  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);
  p_pulse(p,d);

  delay(3000);

  digitalWrite(injektor, LOW);
  aktStatus();
  delay(10000);

  digitalWrite(pumpe, LOW);
  aktStatus();
  delay(3000);
}





//Loop schleife nur für Keypadabfrage
void loop() {
  char key = keypad.getKey();
}



void einschalten(){
  loadData();

  sysStatus = true;
  lcd.init(); // initialize the lcd
  lcd.backlight();

  lcd.clear();
  lcd.setCursor(startposX,0);
  lcd.print("IMP_Cleaner 1.0");
  lcd.setCursor(startposX,1);
  lcd.print("Copyrigth by:");
  lcd.setCursor(startposX,2);
  lcd.print("A.Frauenstein");
  lcd.setCursor(startposX,3);
  lcd.print("Init....");

  delay(500);

  menu();

}


void loadData() {
  for (unsigned int t=0; t<sizeof(storage); t++)
      *((char*)&storage + t) = EEPROM.read(CONFIG_START + t);
}

void saveData() {
  for (unsigned int t=0; t<sizeof(storage); t++)
      EEPROM.write(CONFIG_START + t, *((char*)&storage + t));
}


void ausschalten(){
  saveData();
  sysStatus = false;
  lcd.noBacklight();
}


void aktPause()
{
     lcd.clear();
     lcd.print("Pause");
     lcd.setCursor(0,1);
     lcd.print(storage.impPause);
}

void aktDauer()
{
     lcd.clear();
     lcd.print("Dauer");
     lcd.setCursor(0,1);
     lcd.print(storage.impDauer);
}

    //## Function Check
    boolean funccheck(int action)
    {
           tmpFF = false;

            if(Root.curfuncname == "Pause") {
              if (action==1) {
                aktPause();
              };
              tmpFF = true;
            }
            else if(Root.curfuncname == "IMP-Dauer") {
              if (action==1) {
                aktDauer();
              };
              tmpFF = true;
            }
            else if(Root.curfuncname == "Job 01") {
              if (action==1) {
              job01();
              };
              tmpFF = true;
            }
            return tmpFF;
    }



//take care of some special events
void keypadEvent(KeypadEvent key){
  int mAnz;

if (aktMenu == "main")
{
      mAnz = mAnzMain;
}
else if(aktMenu == "Setup")
{
      mAnz = mAnzSetup;
};


  switch (keypad.getState()){
    case PRESSED:
      switch (key){
        case 'p':
          if(sysStatus) {ausschalten();} else{einschalten();};

        break;

        case 'u':
          if(tmpFF)
          {
            if (Root.curfuncname == "Pause")
            {
              storage.impPause = storage.impPause + 0.1;
              aktPause();
            }
            else if (Root.curfuncname == "IMP-Dauer")
            {
              storage.impDauer = storage.impDauer + 0.1;
              aktDauer();
            };

          }
          else
          {
            Root.goUp();
            aktStatus();
          };
        break;
        case 'd':
          if(tmpFF)
          {
            if (Root.curfuncname == "Pause")
            {
              storage.impPause = storage.impPause - 0.1;
              aktPause();
            }
            else if (Root.curfuncname == "IMP-Dauer")
            {
              storage.impDauer = storage.impDauer - 0.1;
              aktDauer();
            };

          }
          else
          {
            Root.goDown();
            aktStatus();
          };
        break;
        case 'm':
          Root.goMenu(top);
          aktStatus();
        break;

        case '1':
          if(digitalRead(pumpe) == HIGH) {digitalWrite(pumpe, LOW);} 
else{digitalWrite(pumpe, HIGH);};
          aktStatus();
        break;
        case '2':
          if(digitalRead(injektor) == HIGH) {digitalWrite(injektor, 
LOW);} else{digitalWrite(injektor, HIGH);};
          aktStatus();
        break;
        case '3':
          if(digitalRead(v_pneumatik) == HIGH) 
{digitalWrite(v_pneumatik, LOW);} else{digitalWrite(v_pneumatik, 
HIGH);};
          aktStatus();
        break;
        case 'b':
          Root.goBack();

          aktStatus();
        break;
        case 'e':
          Root.goEnter();
          aktStatus();
          funccheck(1);
       break;
      }
    break;
    case RELEASED:
      switch (key){
        case '*':
        break;
      }
    break;
    case HOLD:
      switch (key){
        case '*':

        break;
      }
    break;
  }
}

von TestX .. (xaos)


Lesenswert?

ohne deinen code gelesen zu haben (pack sowas bitte nächstes mal in den 
anhang) gehören delays generell nicht in solche programme rein!
das ganze realisiert man mit timern und interrupts - schau dir hier im 
forum in der artikelsammlung einmal bitte die entsprechenden stellen an 
;)

von gffdg (Gast)


Lesenswert?

Sorry, aber Arduino kann ich nicht ernst nehmen..
Die Abstraktionsebene ist ja der Hammer, wenn ich den Code mal 
überfliege :-)

Wenn du auf eine Eingabe reagieren willst, dann per Interrupt oder 
Polling. MIT Betriebssystem kannst du das in einen anderen Task packen. 
Ein Prozessor kann immer nur einen Befehl gleichzeitig ausführen.

Gruß

von Andreas F. (codecasa)


Lesenswert?

Okay erstmal danke für die Antworten. Sorry wegen dem Langen Code

Ich habe gehört das Interrupt nicht funktionieren wenn ein Delay 
abgearbeitet wird.
Das heist das ich alles mit Interrupts und timern machen muss oder?

Es gibt aber doch nur zwei Timer.

- Ich dacht das Mit der Keypadlibary ist schon ein Interrupt ist dem so 
?

Dann habe ich noch eine Frage:
Was meinst du mit Betriebssystem kann man auf den Arduino ein 
Betriebssystem laden oder wie ?

von Purzel H. (hacky)


Lesenswert?

Nochmals. Schmeiss die Delays raus, die sind Schrott. Nimm einen Timer 
und eine Zustandsmaschine. In einer anderen Zustandsmaschine 
verarbeitest du die Tasten.

interrupt timer
{
 reload timer
 timercame=true
}

main
{
 Zustand=0;

 while true
{
 if timercame
 {
  timercame=false;
  switch zustand
  {
  0: irgendwas; zustand=1; |
  1: irgendwas; zustand=2; |
  2: irgendwas; zustand=3; |
  3: irgendwas; zustand=..; |
  ..
  }
 }

}

von Peter D. (peda)


Lesenswert?


von Hanson (Gast)


Lesenswert?

ich hoffe du hast nicht eines dieser keypads

http://arduino.cc/forum/index.php/topic,96747.0.html

von Andreas F. (codecasa)


Lesenswert?

Nein ich habe folgendes mit 7 Anschlüssen einer davon ist 5V

http://www.voelkner.de/products/261525/Tastatur-3x4-M.Beschriftungsstr.-Ac3560.html

Das Problem ich raffe diese keypadlibary nicht.

Warum muss mann wen mann ein Keypadevent declariert:

keypad.addEventListener(keypadEvent); //add an event listener for this



noch in der Loop schleife den Folgenden Befehl ausführen?

//Loop schleife nur für Keypadabfrage
void loop() {
  char key = keypad.getKey();
}

Und dann Diese Delays keine Idee Wie ich das mit dur Zwei Timern 
Umsetzten kan.

von Peter D. (peda)


Lesenswert?

Andreas Frauenstein schrieb:
> Das Problem ich raffe diese keypadlibary nicht.

Kann man sich diese Lib irgendwo ansehen (Quellcode)?
Zu ner Lib sollte es ja auch ein Manual geben, wo alle Funktionen 
beschrieben sind.

Ne 3*4 Matrix einlesen, da gibt es haufenweise Quellcode. Man muß dazu 
keine spezielle Lib benutzen.
Es schad auch nix, wenn man versteht, wie eine Matrix ausgelesen und 
entprellt wird (das sind 2 separate Aufgaben).


Peter

von Purzel H. (hacky)


Lesenswert?

>Und dann Diese Delays keine Idee Wie ich das mit dur Zwei Timern
Umsetzten kan.

Ein einziger Timer genuegt. Hab ich doch oben gezeigt.

von Andreas F. (codecasa)


Lesenswert?

Habe sie von hier:
http://arduino.cc/playground/Code/Keypad

Das ist aber nichts mit Interrups

von Purzel H. (hacky)


Lesenswert?

>Habe sie von hier:
>http://arduino.cc/playground/Code/Keypad
>
>Das ist aber nichts mit Interrups


Dann ist ja auch gut...

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Tja durch die hohe Abstraktionsebene vom Failduino weis man eben nicht 
was es wirklich macht und kanns nur qick n dirty hinhacken ;)

Zum warten:
Bastel dir nen Timer, der alle x ms nen Interrupt auslöst und in der ISR 
wird ne Variable hochgezählt.
Die Warteprozedur guckt ob die Variable hoch genug gezählt wurde und 
löst dann aus.

Richtiges Multitaskings ist auf AVRs dann doch SEHR aufwändig.

von Hanson (Gast)


Lesenswert?

Was has(s)t du denn gegen den Arduino?

von Andreas F. (codecasa)


Lesenswert?

Okay aber was auslösen Tastaturabfrage oder Impulsechange.

Ich brauche so etwas wie eine Blinklicht ohne die blöden delays
Bsp. 2 sec an 1 sec aus und Paralles soll der Prozessor diese 
Folientastur abfragen damit ich die Impulse sequenz wieder ausschalten 
kann.

Ich Brauche also sowas wie eine Delayprozedur mit Timer
Und Ein Interrupt.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Frauenstein schrieb:
> Okay aber was auslösen Tastaturabfrage oder Impulsechange.
>
> Ich brauche so etwas wie eine Blinklicht ohne die blöden delays
> Bsp. 2 sec an 1 sec aus und Paralles soll der Prozessor diese
> Folientastur abfragen damit ich die Impulse sequenz wieder ausschalten
> kann.
>
> Ich Brauche also sowas wie eine Delayprozedur mit Timer
> Und Ein Interrupt.

Ganz genau.

Und du brauchst keine 'Delayprozedur' sondern lediglich EINEN Timer, der 
dafür sorgt, dass in regelmässigen Zeitabständen eine bestimmte Funktion 
(die Timer-ISR) aufgerufen wird.

Alles andere ist dann nur noch abzählen von Aufrufen.
Wenn deine Timer-ISR alle (hausnummer) 10 Millisekunden aufgerufen wird, 
dann  zählt man halt in dieser ISR einen Zähler bei jedem Aufruf um 1 
hoch (oder runter) und wenn der Zähler bei 100 angelangt ist, ist eine 
Sekunde vergangen.

Du musst nicht 10 Sekunden 'am Stück' auf etwas warten. Du kannst auch 
10 mal 1 Sekunde auf etwas warten. Und wenn du eine Uhr hast, die jede 
Sekunde 1 mal tickt, dann zählst du eben 10 dieser Uhrenticks ab und 
hast auch wieder deine 10 Sekunden.


Und ja: Es ist nicht verboten, dass ein und dieselbe Timer-ISR sich um 
mehrere Dinge kümmert.

Und wenn du dich mit Timern und ISR noch nicht auskennst, dann wäre das 
jetzt ein guter Zeitpunkt, um dein Projekt erst mal zur Seite zu legen 
ein Testprojekt anzufangen, in dem du dich einfach nur mit Timern und 
wie man mit ihnen arbeitet vertraut machst. Wenn du da dann ein wenig 
experimentiert hast, schmeisst du dein Testprojekt weg und mit dem was 
du in diesem Testprojekt alles gelernt hast, gehst du dann erneut an 
dein eigentliches Projekt ran.
So wie überall anders auch: Ehe man als Arbeitskraft in die Produktion 
übernommen wird, macht man erst mal in der Lehrwerkstatt ein paar 
Lehrstücke. Nur in der Programmierung glauben immer alle, man müsse 
nicht im Vorfeld seine Hausaufgaben machen und nicht üben.

von Plopp (Gast)


Lesenswert?

Vielleicht war's zu kompliziert :


interrupt timer
{
 reload timer
 timercame=true
}

main
{
 Delaytimer=100;
 timercame=false;


 while true
{


 if timercame
 {
  timercame=false;
  if (delaytimer !=0)
  {
   delaytimer--;
   if delaytimer==0
   {
    .. timer abgelaufen
   }
  }
 }

}

von Karl H. (kbuchegg)


Lesenswert?

Yep.
Entweder so oder aber wenn die Aktion schnell durchführbar ist (wie zb 
eine LED ein/ausschalten, einen Motor ausschalten, die Uhrzeit 
hochzählen etc.), kann man die Aktion durchaus auch in die ISR selbst 
verlagern.

interrupt timer
{
 timercame=true

 delaytimer--;
 if delaytimer == 0
 {
   LED umschalten;
   delaytimer = 100;
 }

 if motortimer > 0
 {
   motortimer--;
   if motortimer == 0
     Motor ausschalten;
 }
}

main
{
 delaytimer =100;
 timercame=false;


 while true
 {
   if Taste gedrückt
   {
     Motor einschalten
     motortimer = 500;   // nach einer Wartezeit von 500 * 100
                         // soll der Motor wieder abgeschaltet werden
   }
 }

}

So erfolgt das Blinken der LED komplett in der ISR.
Und nach dem gleichen Muster und weiteren Zählvariablen, kann man dann 
auch mehrere zeitliche Abläufe quasi gleichzeitig bearbeiten lassen. 
Einzige Einschränkung: alle diese zeitlichen Abläufe müssen ganzzahlige 
VIelfache der Aufruffrequenz der Timer-ISR sein. Wird die ISR alle 10 
Millisekunden aufgerufen, kann ich damit keine Verzögerung von 15 
Millisekunden realisieren. Sorge ich aber dafür, dass die ISR alle 5 
Millisekunden aufgerufen wird, gehts wieder.

von Andreas (Gast)


Lesenswert?

Danke vielmals ich werde mich die Tage einarbeiten und erst dann das 
Projekt umschreiben.

von Andreas F. (codecasa)


Lesenswert?

Soweit so gut habe das prinzip verstanden aber es passt überhaupt nicht 
zum Arduino bzw. ind die IDE des Arduino


Interrupts werden auch irgendwie anders declariert

void Setup
void Loop

von Karl H. (kbuchegg)


Lesenswert?

Andreas Frauenstein schrieb:
> Soweit so gut habe das prinzip verstanden aber es passt überhaupt nicht
> zum Arduino bzw. ind die IDE des Arduino
>
>
> Interrupts werden auch irgendwie anders declariert

Nun ja.
Obiges ist ja auch nur das Prinzip. Das das so ähnlich aussieht wie 
C-Code liegt einfach daran, dass sich so das Prinzip viel kompakter 
zeigen lässt als wie wenn man eine Prosa-Beschreibung dafür macht.

Speziell für das Arduino-System wird dir hier keiner fertigen Code frei 
Haus liefern. Um das Studium, wie man das Prinzip mit den Mitteln der 
Arduino Bibliothek umsetzt, wirst du also nicht umhinkommen.

Die meisten hier programmieren ohne eine derartige Hilfsbibliothek. Mehr 
oder weniger praktisch direkt auf der Hardware. Daher wäre dir so ein 
Code ebenfalls keine Hilfe.

Wenn du das Prinzip verstanden hast, sollte es allerdings kein Problem 
sein, das mit deinr Arduino-Bibliothek zur realisieren. Die Fragen, die 
du beantworten musst, lauten:
* wie aktiviere ich einen Timer
* wie sorge ich für regelmässige Aufrufe einer Interrupt Routine und
  wie steuere ich den Zeitraum von einem Aufruf zum nächsten
* wie muss ich diese Interrupt Routine vereinbaren

Mit diesem Wissen und dem vorgestellten Implementierungsprinzip solltest 
du  in der Lage sein, das alles umzusetzen.


Das du dann allerdings dein eingangs vorgestelltes Programm heftig 
umbauen musst, liegt in der Natur der Sache. Wenn man mit dem falschen 
Verfahren angefangen hat, ist man oft weit weg von einer 
funktionierenden Lösung. Daher auch: Erst mal mit einem Testprogramm 
Erfahrung sammeln.

Ich fang bei solchen Sachen normalerweise erst mal mit der 
zugrundeliegenden 'Maschine' an, die bei dir eben 'zeitliche Abläufe 
abarbeiten' lautet. Menüs und Einschaltmeldung und dergleichen, kommt 
erst viel später. Erst mal muss die arbeitende Maschinerie 
funktionieren.

von Achim S. (achims)


Lesenswert?

Hallo
ich muss Karl Heinz in allen Punkten Recht geben. Habe auch lange 
gebraucht, bis ich es richtig verstanden habe, doch jetzt geht es ohne 
Probleme. Kann bis zu 4 Tasten entprellen. Kann kurz oder land auswerten 
und kann noch viele andere Sachen fast gleichzeitig machen. Habe einen 
Timer laufen mit 10 ms und leite von diesem alles ab. Bin voll 
zufrieden.
achim

von Andreas F. (codecasa)


Lesenswert?

Ja Karl Heinz hat Recht ich habe vorher auch nur mit folgender 
Reihenfolge programmiert:

C64 hehehe
Q- Quick- Basic
Visualbasic
Visual C++

C++

Microcontroller nur Oberflächlich

Wobei Mit Microcontroller zu Programmieren was ganz anderes ist habe 
bemerkt
Alleine schon die Byteoperationen sind ersteinmal zu verstehen g


Habe meine Sachen jetzt mit eine Millis ISR gelöst klappt ganz gut:

//Loop schleife nur für Keypadabfrage
void loop() {
  char key = keypad.getKey();
  if (state_imp) {pmp_isr();};
}



void pmp_isr()
{
  byte value = digitalRead(v_pneumatik);

  if (value == LOW)
  {
    intervall_imp = (storage.impPause * 1000);
  }
  else
  {
    intervall_imp = (storage.impDauer * 1000);
  }
 if (millis() - pMillis > intervall_imp) {
    pMillis = millis();   // aktuelle Zeit abspeichern

    // LED Zustand wecheln.
    if (value == LOW)
      value = HIGH;
    else
      value = LOW;
// Wert auf den Ausgang schreiben
    digitalWrite(v_pneumatik, value);
    aktStatus();
  }
}


Nur nach Job1 das jetztr statt Delay eine Millisfuction aufruft habe ich 
immernoch das Problem das er in dem Menu festhängt und ich danch 
nichtmehr im Menu nach unten kann.

Nur die die Folgende Tastenkombination löst das wieder:
Enter, Back

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.